In this guide, you will learn how to get the MFA status of Office 365 users with PowerShell.
I’ll show you how to get MFA status for a single and a list of users.
In addition, I’ll show you how to export Office 365 MFA status report to CSV.
Let’s get started.
Get MFA Status with PowerShell Requirments
The examples in this guide use the Microsoft Graph module to check the MFA status for Office 365 users. You will need to have the Graph module installed.
The Get-MGUser cmdlet is used to get single and all users from your Office 365 tenant.
The Get-MGUserAuthenticationMethod cmdlet is used to get the MFA authentication methods for each user.
Important
The PowerShell commands report the authentication method registered for each user, this is how the MFA status is determined. Unfortunately, Microsoft does not provide a command that simply says if an account has MFA enabled or not, it has to be calculated.
When passwordAuthenticationMethod is the only authentication method listed this means the user does not have MFA enabled. The script I provide below will check the authentication methods and create an MFA Status field (Enabled or Disabled).
Example 1. Get MFA Status Office 365 for a Single User
To check the MFA status of a single user is very easy, you don’t need a bloated script for this.
Step 1. Connect to Microsoft Graph
Before you can get Office 365 Users and check the MFA status you first need to connect to Microsoft Graph.
The below command will permit you to read the full set of Azure user profile properties.
Connect-MgGraph -Scopes "User.Read.All"
Note: Some users have mentioned that the script fails with request authorization failed. In this case, try using Connect-MgGraph -Scopes “UserAuthenticationMethod.Read.All”
You will be prompted to sign in with your account.
When you have authenticated PowerShell should display “Welcome to Microsoft Graph!”
Step 2. Run the Get-MGUserAuthenticationMethod cmdlet
Run the below command to get the MFA status for a single user.
Get-MGUserAuthenticationMethod -userid abbie.peters@activedirectorypro.com | fl
In this example, I’m checking the MFA status for the user abbie.peters@activedirectorypro.com.
The authentication method of microsoft.graph.passwordAuthenticationMethod is the only method listed, this means MFA is not enabled for this user.
Now I’ll check the authentication methods for my account.
In the screenshot above, you can see my account returns multiple authentication methods, this means my account has MFA enabled.
It gets much more complicated when checking all users, the good news is I’ve created a script you can use.
Example 2. MFA Status Office 365 Report for All Users PowerShell
You can copy the script below or download the MFAStatusReport.ps1 PowerShell script.
By default, the script will get the MFA status for all users. I’ll show you how to change it to check the status of a list of users.
Note: Depending on how many users you have in your tenant the script can take several minutes to complete.
<#
=============================================================================================
Name: Get MFA Status Report
Description: Gets MFA status for all users and authentication methods
Version: 1.0
Website: activedirectorypro.com
Script by: activedirectorypro.com
Instructions: https://activedirectorypro.com/mfa-status-powershell
============================================================================================
#>
#Get all Azure users
$users = get-mguser -All
$results=@();
Write-Host "`nRetreived $($users.Count) users";
#loop through each user account
foreach ($user in $users) {
Write-Host "`n$($user.UserPrincipalName)";
$myObject = [PSCustomObject]@{
user = "-"
MFAstatus = "_"
email = "-"
fido2 = "-"
app = "-"
password = "-"
phone = "-"
softwareoath = "-"
tempaccess = "-"
hellobusiness = "-"
}
$MFAData=Get-MgUserAuthenticationMethod -UserId $user.UserPrincipalName #-ErrorAction SilentlyContinue
$myobject.user = $user.UserPrincipalName;
#check authentication methods for each user
ForEach ($method in $MFAData) {
Switch ($method.AdditionalProperties["@odata.type"]) {
"#microsoft.graph.emailAuthenticationMethod" {
$myObject.email = $true
$myObject.MFAstatus = "Enabled"
}
"#microsoft.graph.fido2AuthenticationMethod" {
$myObject.fido2 = $true
$myObject.MFAstatus = "Enabled"
}
"#microsoft.graph.microsoftAuthenticatorAuthenticationMethod" {
$myObject.app = $true
$myObject.MFAstatus = "Enabled"
}
"#microsoft.graph.passwordAuthenticationMethod" {
$myObject.password = $true
# When only the password is set, then MFA is disabled.
if($myObject.MFAstatus -ne "Enabled")
{
$myObject.MFAstatus = "Disabled"
}
}
"#microsoft.graph.phoneAuthenticationMethod" {
$myObject.phone = $true
$myObject.MFAstatus = "Enabled"
}
"#microsoft.graph.softwareOathAuthenticationMethod" {
$myObject.softwareoath = $true
$myObject.MFAstatus = "Enabled"
}
"#microsoft.graph.temporaryAccessPassAuthenticationMethod" {
$myObject.tempaccess = $true
$myObject.MFAstatus = "Enabled"
}
"#microsoft.graph.windowsHelloForBusinessAuthenticationMethod" {
$myObject.hellobusiness = $true
$myObject.MFAstatus = "Enabled"
}
}
}
##Collecting objects
$results+= $myObject;
}
# Display the custom objects
$results
To run the script open PowerShell and first connect to MS Graph.
Connect-MgGraph -Scopes "User.Read.All"
Then enter the path and name of the script to execute it.
The script will display how many accounts it found and output the account it is processing.
When the script is completed it will display the MFA status and authentication methods for each user.
To export the MFA status report to CSV use the export-CSV parameter.
.\MFAStatusReport.ps1 | export-csv -path c:\it\mfastatus-csv
Check MFA Status for a List of Users
If you want to run the script on a list of users comment line #14 and add this code.
$users = ForEach ($mguser in $(get-content -path C:\it\users.txt)) {
get-mguser -userid $mguser
}
Then create a text file with a list of users. You can save the list anywhere you want just make sure to update the path in the script.
Now run the script and it will only process the accounts listed in the text file.
MFA Status Report with the 365 Pro Toolkit
The 365 Pro Toolkit makes it easy to get the MFA status for all users. Check the MFA status and the authentication method for all users in your tenant. The report can be exported to CSV, Excel or PDF.
List of MFA Authentication Methods
Below is a list of the authentication methods the PowerShell script checks for.
- emailAuthenticationMethod – Represents an email address registered to a user
- fido2AuthenticationMethod – FIDO2 security key registered to a user (USB device)
- microsoftAuthenticatorAuthenticationMethod – This is the Microsoft authenticator app.
- passwordAuthenticationMethod – The user’s password.
- phoneAuthenticationMethod – This means a user has registered their phone using SMS or voice call.
- softwareOathAuthenticationMethod – Software OATH token registered to a user.
- temporaryAccessPassAuthenticationMethod – Temporary time-limited passcode.
- windowsHelloForBusinessAuthenticationMethod – Windows hello for business registered to a user.
In the script, these will have #microsoft.graph in the name.
To learn more about the authentication methods refer to the Microsoft article authenticationMethods resource type.
I hope you found this article useful, if you have comments or questions post them below.
Great script, just a small note from my side – secondary email is not a valid MFA method in EntraID (https://support.microsoft.com/en-us/account-billing/set-up-an-email-address-as-your-verification-method-250b91e4-7627-4b60-b861-f2276a9c0e39) and can only be used for password resets.
Therefore MFA enabled should remain “FALSE” even if a secondary mail is set up for the account in my opinion.
Great article. You can now use this feature to check one or more users for ‘”isMfaCapable” without counting the number of factors –
https://learn.microsoft.com/en-us/graph/api/authenticationmethodsroot-list-userregistrationdetails?view=graph-rest-1.0&tabs=powershell
Good to know. Thanks for the info.
Hello Robert,
Stumbled over your blog when i was trying to get my own user from our environment. It seems
some scopes only does work in conditional environments like this;
Connect-MgGraph -TenantId “domaintenantname” -ClientId id -Scopes “User.Read” -UseDeviceAuthentication
But as i am a beginner i just started this afternoon reading all about the Microsoft MS Graph SDK. Is it possible your App is released anytime soon? Is it still “beta” testing? Best regards
Hopefully it will be released by the end of this month.
This is the error I get:
get-mguser : The term ‘get-mguser’ is not recognized as the name of a cmdlet, function, script file, or operable program.
Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At C:\Scripts\MFAStatusReport.ps1:13 char:10
+ $users = get-mguser -All
+ ~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (get-mguser:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
Can you check from the graph module.
find-module microsoft.graph
a little late to the party but I also confirm I had to use scoping “UserAuthenticationMethod.Read.All”
Thank you for the script!!!!!
Script is helpful. Thanks! I was also looking for a way to differentiate between users who were enrolled in Microsoft Authenticator – Outlook Mobile (Authenticator Lite) vs the actual authenticator app. Both show as type microsoftAuthenticatorAuthenticationMethod. The only thing I found that seems to differentiate them is the device tag property. With the Authenticator app it seems to show as “SoftwareTokenActivated”. If it’s the outlook app it shows something else like Android, etc. Some slight modifications and you can capture this info as well if needed.
##Add an outlook field to the object:
$myObject = [PSCustomObject]@{
user = “-”
MFAstatus = “_”
email = “-”
fido2 = “-”
app = “-”
outlook = “-”
password = “-”
phone = “-”
softwareoath = “-”
tempaccess = “-”
hellobusiness = “-”
}
##Add a check for deviceTag if type is Authenticator.
“#microsoft.graph.microsoftAuthenticatorAuthenticationMethod” {
if($method.AdditionalProperties[“deviceTag”] -eq ‘SoftwareTokenActivated’) {
$myObject.app = $true
$myObject.MFAstatus = “Enabled”
}
else{
$myObject.outlook = $true
$myObject.MFAstatus = “Enabled”
}
Robert,
Nice script! Is there a way to pull only what authentication methods are registered? For example, when I run the script all I want to see is the users displayname, {[@odata.type, #microsoft.graph.microsoftAuthenticatorAuthenticationMethod], [displayName, iPhone].
I need the method type and displayname of the device that is registered. I’m trying to check user accounts for rouge devices by device name.
You can also use buil-in Get-MgUser property CountVariable:
$Users=get-mguser -all -CountVariable Count
Write-Host “`nRetreived $Count users”;
For large number of accounts in Azure should be better to get only enabled users and user type members by -Filter
Get-MgUser -Filter ‘AccountEnabled eq true’
Great script, thank you!
One typo I’ve found:
Get all Azure users on line 12 should be #Get all Azure users
Otherwise error while executing.
Kr
Thomas
Thanks Thomas. I have updated the script.
This doesn’t tell you which users have MFA, it tells you what MFA methods they have configured, these methods are independent of whether it’s actually enabled. It doesn’t matter what it shows in the Auth Methods endpoint, it can still be disabled in the Admin Center. I have personally tested this. You aught to have a warning banner at the top that this article is wrong as this misconception is doing the rounds.
This was already mentioned in the box labeled important at the top of the article.
“The PowerShell commands report the authentication method registered for each user, this is how the MFA status is determined. Unfortunately, Microsoft does not provide a command that simply says if an account has MFA enabled or not, it has to be calculated.”
Hi Robert,
I don’t think you follow.
You can have all the methods you like added for a user, but they can be completely overridden in the Admin Center. The methods will still show up in the Graph API, but they are ignored during login and the user will not get prompted for MFA.
As I mentioned in the article, Microsoft does not provide a command using graph API to simply check if MFA is enabled or not. This script determines this based on the AuthenticationMethods. If you know of a better way to check if MFA is enabled please let me know and I’ll update the script.
But it doesn’t… It tells you what MFA methods the user would use if it were enabled, but that’s a completely different setting. Your warning message explains that there’s no direct setting but that your script somehow “calculates” whether MFA is enabled or not. It absolutely does not do that. At best, it gives you an indication that they may have had MFA once upon a time. That’s completely useless from a security posture perspective.
If you’re using PowerShell just use Get-MsolUser and check StrongAuthenticationRequirements. I expect they will expose this setting in Graph someday soon. MSOL deprecation has been extended until March 30th 2024, I imagine this is one of the reasons why.
Look, I’m not gonna argue with you any more, it’s black and white and I can’t be much more clear about what’s wrong with your article. Hopefully others will scroll this far down and understand what I’m explaining.
Agree to disagree. The article is transparent and it clearly states how the MFA status is determined From the article: “The PowerShell commands report the authentication method registered for each user, this is how the MFA status is determined”. The script creates the MFA status field because there is no status field to query in Azure.
MSOL was set to be retired on August 2022 and that is why the script is using the Graph module.
Would have to agree with Robert here. What Richard is referring to is Per User MFA, which is not the recommended way to implement MFA anymore. If you are following best practices to enforce MFA through Conditional Access whether they have Per User MFA enabled is irrelevant.
Hello,
very good example of usage MGraph module. I have only one comment regarding MFAStatus evaluation as the logic in the script is not getting the right status. When the user had in the past activated MFA, have some Authentication methods in the profile and turn off the MFA the methods are still in the profile but user is using Single factor authentication (as you can see in the Sign-in log in the Azure. Currently I did not find any property using MGraph module indicating the user has MFA turned on. Only expanding property SignInActivity we can get last sign-in activity and authentication requirements. But not so useful and very early development state 🙂
When i run the script, the get-mguserauthentication command fails with request authorization failed, even though i’ve connected with the user.read.all scope. any ideas?
Are you first running the command “Connect-MgGraph -Scopes “User.Read.All”
Then running the script or get-mguserauthentication command
same error as Damien here.
Fixed after also scoping “UserAuthenticationMethod.Read.All”
It’s possible that you need to edit the article 🙂
Interesting.
Seems like Connect-MgGraph -Scopes “User.Read.All” is working for some but not others. I’m not sure why. I’ll update the article to mention the other permissions.
Thanks, Tim.
Yes that fixed it, thanks! And thanks for the very helpful script as well. This has saved me a lot of pain when working on MFA projects where SSPR is already enabled.
Great script but it seems like it is not designed for automated execution. When I connect to graph using Access Token (Get-MsalToken) execution fails after about 1 hour (we have almost 10k users in our organization). Any ideas?