Source: https://lazyadmin.nl/powershell/list-office365-mfa-status-powershell/
One of the reports that I really miss in the Microsoft 365 Admin Center is a clear overview of the MFA status of each user. MFA is a really important security measure to protect your tenant. To make sure that our users have configured MFA we are going to use PowerShell to get and export the MFA Status.
You could also use the built-in overview in the Admin Center, but that would be really time-consuming. With PowerShell on the other hand, 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 and report the MFA status of your users:
- List the MFA Status of all users
- List configured MFA types for each user
- 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.
Tip
Add this script to your PowerShell Profile so you can easily check the MFA Status of your users. Read more about it in this article.
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 of 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 a CSV file if you like.
# Make sure you are connected to MsolService Get-MFAStatus.ps1 | FT # Or if you want an excel file Get-MFAStatus.ps1 | 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.ps1 -withOutMFAOnly
Check the MFA Status of admins
Admins should have MFA enabled without a doubt. To quickly check the status of all your admin accounts you can use the switch adminsOnly
Get-MFAStatus.ps1 -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.ps1 -UserPrincipalName '[email protected]'
If you want to check the status of a single department for example, then you can do the following:
Get-MsolUser.ps1 -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. (I recommend using Github to make sure you have the latest version).
Tip
Quickly get the MFA Status of your users by adding a reference to the script in your PowerShell Profile. Read all about it in this article.
<# .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.3 DateCreated: jan 2021 Purpose/Change: List all Configured MFA Types 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, ParameterSetName = "UserPrincipalName", HelpMessage = "Enter a single UserPrincipalName or a comma separted list of UserPrincipalNames", Position = 0 )] [string[]]$UserPrincipalName, [Parameter( Mandatory = $false, ValueFromPipeline = $false, ParameterSetName = "AdminsOnly" )] # 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 = 10000, [Parameter( Mandatory = $false, ValueFromPipeline = $false, ParameterSetName = "Licenend" )] # Check only the MFA status of users that have license [switch]$IsLicensed = $true, [Parameter( Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = "withOutMFAOnly" )] # 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 ) # Connect to Msol if ((Get-Module -ListAvailable -Name MSOnline) -eq $null) { Write-Host "MSOnline Module is required, do you want to install it?" -ForegroundColor Yellow $install = Read-Host Do you want to install module? [Y] Yes [N] No if($install -match "[yY]") { Write-Host "Installing MSOnline module" -ForegroundColor Cyan Install-Module MSOnline -Repository PSGallery -AllowClobber -Force } else { Write-Error "Please install MSOnline module." } } if ((Get-Module -ListAvailable -Name MSOnline) -ne $null) { if(-not (Get-MsolDomain -ErrorAction SilentlyContinue)) { Connect-MsolService } } else{ Write-Error "Please install Msol module." } # Get all licensed admins $admins = $null if (($listAdmins) -or ($adminsOnly)) { $admins = Get-MsolRole | %{$role = $_.name; Get-MsolRoleMember -RoleObjectId $_.objectid} | Where-Object {$_.isLicensed -eq $true} | select @{Name="Role"; Expression = {$role}}, DisplayName, EmailAddress, ObjectId | Sort-Object -Property EmailAddress -Unique } # 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 $Method = "" $MFAMethod = $MsolUser.StrongAuthenticationMethods | Where-Object {$_.IsDefault -eq $true} | Select-Object -ExpandProperty MethodType If (($MsolUser.StrongAuthenticationRequirements) -or ($MsolUser.StrongAuthenticationMethods)) { Switch ($MFAMethod) { "OneWaySMS" { $Method = "SMS token" } "TwoWayVoiceMobile" { $Method = "Phone call verification" } "PhoneAppOTP" { $Method = "Hardware token or authenticator app" } "PhoneAppNotification" { $Method = "Authenticator app" } } } [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 = $Method 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 $MFAMethod = $MsolUser.StrongAuthenticationMethods | Where-Object {$_.IsDefault -eq $true} | Select-Object -ExpandProperty MethodType $Method = "" If (($MsolUser.StrongAuthenticationRequirements) -or ($MsolUser.StrongAuthenticationMethods)) { Switch ($MFAMethod) { "OneWaySMS" { $Method = "SMS token" } "TwoWayVoiceMobile" { $Method = "Phone call verification" } "PhoneAppOTP" { $Method = "Hardware token or authenticator app" } "PhoneAppNotification" { $Method = "Authenticator app" } } } [PSCustomObject]@{ DisplayName = $MsolUser.DisplayName UserPrincipalName = $MsolUser.UserPrincipalName isAdmin = $true "MFA Enabled" = if ($MsolUser.StrongAuthenticationMethods) {$true} else {$false} "MFA Default Type"= $Method "SMS token" = if ($MsolUser.StrongAuthenticationMethods.MethodType -contains "OneWaySMS") {$true} else {"-"} "Phone call verification" = if ($MsolUser.StrongAuthenticationMethods.MethodType -contains "TwoWayVoiceMobile") {$true} else {"-"} "Hardware token or authenticator app" = if ($MsolUser.StrongAuthenticationMethods.MethodType -contains "PhoneAppOTP") {$true} else {"-"} "Authenticator app" = if ($MsolUser.StrongAuthenticationMethods.MethodType -contains "PhoneAppNotification") {$true} else {"-"} 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) { $MFAMethod = $MsolUser.StrongAuthenticationMethods | Where-Object {$_.IsDefault -eq $true} | Select-Object -ExpandProperty MethodType $Method = "" If (($MsolUser.StrongAuthenticationRequirements) -or ($MsolUser.StrongAuthenticationMethods)) { Switch ($MFAMethod) { "OneWaySMS" { $Method = "SMS token" } "TwoWayVoiceMobile" { $Method = "Phone call verification" } "PhoneAppOTP" { $Method = "Hardware token or authenticator app" } "PhoneAppNotification" { $Method = "Authenticator app" } } } 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 {"-"} "MFA Enabled" = if ($MsolUser.StrongAuthenticationMethods) {$true} else {$false} "MFA Default Type"= $Method "SMS token" = if ($MsolUser.StrongAuthenticationMethods.MethodType -contains "OneWaySMS") {$true} else {"-"} "Phone call verification" = if ($MsolUser.StrongAuthenticationMethods.MethodType -contains "TwoWayVoiceMobile") {$true} else {"-"} "Hardware token or authenticator app" = if ($MsolUser.StrongAuthenticationMethods.MethodType -contains "PhoneAppOTP") {$true} else {"-"} "Authenticator app" = if ($MsolUser.StrongAuthenticationMethods.MethodType -contains "PhoneAppNotification") {$true} else {"-"} MFAEnforced = if ($MsolUser.StrongAuthenticationRequirements) {$true} else {"-"} } } } }
Wrapping up
Enabling MFA is one of the important steps to protect your tenant. With this PowerShell script, you can easily check the MFA status of your users.
Make sure you also check this article with 20 other security tips for Office 365.
If you found this script useful, then please share it. If you have any questions then just drop a comment below.