One of the reports that I really miss in the Microsoft 365 Admin Center is a clear overview of the MFA status for each user. Yes, you can check it sort of under Active Users > Multi-Factor Authentication, but that is not really user-friendly. An easier way is to use PowerShell to get the MFA Status for each user.
New Microsoft 365 Tenants that are created after 22 October 2019 will have MFA enabled by default for all users as part of the security defaults. But with older tenants, you will need to manually enable MFA for each user. The challenge is to make sure all users have enabled it and keep track of it.
With PowerShell, we can easily get the MFA Status of all users and create an Excel list with all the details we need. I have created a script that can do a couple of things to check the MFA status of your users:
- List the MFA Status of all users
- Get all the users that don’t have MFA enabled
- Check the MFA status of a single user
- Check if MFA is enforced
- Checks if a user is admin or not
- Get only the licensed and enabled users
At the end of the article you will find the complete script.
Get the MFA Status with PowerShell
With PowerShell, we can easily get the MFA Status of all our Office 365 users. The basis for the script is the Get-MsolUser cmdlet, which gets the users from the Azure Active Directory.
Get-MsolUser returns all the user details, including the parameter StrongAuthenticationMethods. This parameter will list all the strong authentication methods that a user is using. If this parameter is set, then we know that the user is using MFA.
Requirements
You need to have the MsolService module installed to use this script. Make sure you are connected before you run the script
Connect-MsolService
Getting a list of all users and there MFA Status
You can just run the script without any parameters to get a list with all the users and their MFA Status. The script will check if the user is an admin and will list the default MFA type that the user has set.
You can export the result on the screen or to an CSV file if you like.
# Make sure you are connected to MsolService Get-MFAStatus | FT # Or if you want an excel file Get-MFAStatus | Export-CSV c:\temp\mfastatus.csv -noTypeInformation
Get only the users without MFA
If you have a large tenant then you probably only want to get the users without MFA. You can use the switch withOutMFAOnly
for this.
Get-MFAStatus -withOutMFAOnly
Check the MFA Status of admins
Admins should have MFA enable without a doubt. To quickly check the status of all your admin accounts you can use the switch adminsOnly
Get-MFAStatus -adminsOnly
Check the MFA status on a selection of users
The script also allows you to check the MFA Status of a single user or multiple users.
Get-MFAStatus -UserPrincipalName '[email protected]'
If you want to check the status of a single department for example, then you can do the following:
Get-MsolUser -Department 'Finance' | ForEach-Object { Get-MFAStatus $_.UserPrincipalName }
The complete script
You can find the complete script here below or you can get it here from my Github.
Function Get-MFAStatus { <# .Synopsis Get the MFA status for all users or a single user. .DESCRIPTION This script will get the Azure MFA Status for your users. You can query all the users, admins only or a single user. It will return the MFA Status, MFA type ( .NOTES Name: Get-MFAStatus Author: R. Mens - LazyAdmin.nl Version: 1.0 DateCreated: jan 2021 Purpose/Change: Initial script development Thanks to: Anthony Bartolo .LINK https://lazyadmin.nl .EXAMPLE Get-MFAStatus Get the MFA Status of all enabled and licensed users and check if there are an admin or not .EXAMPLE Get-MFAStatus -UserPrincipalName '[email protected]','[email protected]' Get the MFA Status for the users John Doe and Jane Doe .EXAMPLE Get-MFAStatus -withOutMFAOnly Get only the licensed and enabled users that don't have MFA enabled .EXAMPLE Get-MFAStatus -adminsOnly Get the MFA Status of the admins only .EXAMPLE Get-MsolUser -Country "NL" | ForEach-Object { Get-MFAStatus -UserPrincipalName $_.UserPrincipalName } Get the MFA status for all users in the Country The Netherlands. You can use a similar approach to run this for a department only. .EXAMPLE Get-MFAStatus -withOutMFAOnly | Export-CSV c:\temp\userwithoutmfa.csv -noTypeInformation Get all users without MFA and export them to a CSV file #> [CmdletBinding(DefaultParameterSetName="Default")] param( [Parameter( Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = "UserPrincipalName", Position = 0 )] # Enter a single UserPrincipalName or a comma separted list of UserPrincipalNames [string[]]$UserPrincipalName, [Parameter( Mandatory = $false, ValueFromPipeline = $false, ParameterSetName = "AdminsOnly", Position = 0 )] # Get only the users that are an admin [switch]$adminsOnly = $false, [Parameter( Mandatory = $false, ValueFromPipeline = $false, ParameterSetName = "AllUsers" )] # Set the Max results to return [int]$MaxResults = 1000, [Parameter( Mandatory = $false, ValueFromPipeline = $false, ParameterSetName = "AllUsers" )] # Check only the MFA status of users that have license [switch]$IsLicensed = $true, [Parameter( Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = "AllUsers" )] # Get only the users that don't have MFA enabled [switch]$withOutMFAOnly = $false, [Parameter( Mandatory = $false, ValueFromPipeline = $false )] # Check if a user is an admin. Set to $false to skip the check [switch]$listAdmins = $true ) Begin { # Get all licensed admins $admins = $null if (($listAdmins) -or ($adminsOnly)) { $admins = Get-MsolRoleMember -RoleObjectId $(Get-MsolRole -RoleName "Company Administrator").ObjectId | Where-Object {$_.isLicensed -eq $true} | Select-Object ObjectId,EmailAddress } } Process { # Check if a UserPrincipalName is given # Get the MFA status for the given user(s) if they exist if ($PSBoundParameters.ContainsKey('UserPrincipalName')) { foreach ($user in $UserPrincipalName) { try { $MsolUser = Get-MsolUser -UserPrincipalName $user -ErrorAction Stop [PSCustomObject]@{ DisplayName = $MsolUser.DisplayName UserPrincipalName = $MsolUser.UserPrincipalName isAdmin = if ($listAdmins -and $admins.EmailAddress -match $MsolUser.UserPrincipalName) {$true} else {"-"} MFAEnabled = if ($MsolUser.StrongAuthenticationMethods) {$true} else {$false} MFAType = $MsolUser.StrongAuthenticationMethods | Where-Object {$_.IsDefault -eq $true} | Select-Object -ExpandProperty MethodType MFAEnforced = if ($MsolUser.StrongAuthenticationRequirements) {$true} else {"-"} } } catch { [PSCustomObject]@{ DisplayName = " - Not found" UserPrincipalName = $User isAdmin = $null MFAEnabled = $null } } } } # Get only the admins and check their MFA Status elseif ($adminsOnly) { foreach ($admin in $admins) { $MsolUser = Get-MsolUser -ObjectId $admin.ObjectId | Sort-Object UserPrincipalName -ErrorAction Stop [PSCustomObject]@{ DisplayName = $MsolUser.DisplayName UserPrincipalName = $MsolUser.UserPrincipalName isAdmin = $true MFAEnabled = if ($MsolUser.StrongAuthenticationMethods) {$true} else {$false} MFAType = $MsolUser.StrongAuthenticationMethods | Where-Object {$_.IsDefault -eq $true} | Select-Object -ExpandProperty MethodType MFAEnforced = if ($MsolUser.StrongAuthenticationRequirements) {$true} else {"-"} } } } # Get the MFA status from all the users else { $MsolUsers = Get-MsolUser -EnabledFilter EnabledOnly -MaxResults $MaxResults | Where-Object {$_.IsLicensed -eq $isLicensed} | Sort-Object UserPrincipalName foreach ($MsolUser in $MsolUsers) { if ($withOutMFAOnly) { # List only the user that don't have MFA enabled if (-not($MsolUser.StrongAuthenticationMethods)) { [PSCustomObject]@{ DisplayName = $MsolUser.DisplayName UserPrincipalName = $MsolUser.UserPrincipalName isAdmin = if ($listAdmins -and $admins.EmailAddress -match $MsolUser.UserPrincipalName) {$true} else {"-"} MFAEnabled = $false MFAType = "-" MFAEnforced = if ($MsolUser.StrongAuthenticationRequirements) {$true} else {"-"} } } }else{ [PSCustomObject]@{ DisplayName = $MsolUser.DisplayName UserPrincipalName = $MsolUser.UserPrincipalName isAdmin = if ($listAdmins -and $admins.EmailAddress -match $MsolUser.UserPrincipalName) {$true} else {"-"} MFAEnabled = if ($MsolUser.StrongAuthenticationMethods) {$true} else {$false} MFAType = $MsolUser.StrongAuthenticationMethods | Where-Object {$_.IsDefault -eq $true} | Select-Object -ExpandProperty MethodType MFAEnforced = if ($MsolUser.StrongAuthenticationRequirements) {$true} else {"-"} } } } } } }
Wrapping up
If you found this script useful, then please share it. If you have any questions then just drop a comment below.
This is pretty great, thank you. I’m attempting to get a list of users with a specific Strong Authentication Method Type set specifically to “PhoneAppNotification”. As it turns out, Microsoft offers users the ability to put their cell phone numbers on their accounts, which get registered as a Strong Authentication Method, even when MFA isnt configured. Because of that I have thousands of users that get returned when basic Strong Authentication queries are run.
Hi Jason,
You can use the following code to only list the users with PhoneAppNotification:
$msolUsers = get-msoluser -EnabledFilter EnabledOnly -MaxResults 1000
foreach ($MsolUser in $MsolUsers) {
$methodType = $MsolUser.StrongAuthenticationMethods | Where-Object {$_.IsDefault -eq $true} | Select-Object -ExpandProperty MethodType
# List only the user that don't have MFA enabled
if ($methodType -eq 'PhoneAppNotification') {
write-host $MsolUser.UserPrincipalName
}
}