With the recent announcement of the Azure AD API deprecation, I’ve made an effort to try and migrate all of my scripts to use Microsoft Graph API. Microsoft Graph API is the latest standard for managing everything Microsoft 365 and it is continuing to be developed for the foreseeable future. In this article, I’m going to share the script to Get MFA Methods using MSGraph API and PowerShell SDK.
Previously, I had to get this information using the old MSOnline (MSOL) module, however, since that is also deprecated, I thought it would be a good opportunity to freshen up my MSGraph skills and get this going.
Table Of Contents
Requirements
In order for this to work, there are a couple of requirements that need to be put in place prior to running the script. While it is not a technical requirement, it would be ideal to have a basic understanding of Microsoft Graph API application and delegated permissions, scopes, apps, consent and maybe a sprinkle of Service Principals.
This will cover everything you need to know and get you up and running in no time.
Now for the actual technical requirements:
- An App/Service Principal to connect to Graph API -or granted consent to connect to Graph API as yourself
- Microsoft.Graph PowerShell Module
- Graph API Scopes (Delegated or Application permissions)
- UserAuthenticationMethod.Read.All
- Directory.Read.All
- User.Read.All
Script Parameters
UserId
Specify the UserPrincipalName or Id for the user you want to check authentication methods for.
MethodType
Specify the method type you would like to filter for.
Get MFA Methods using MSGraph API
Now let’s get to the PowerShell script. As mentioned, this is a function that will gather all of the authentication methods a user has registered for their account. All Auth methods except for “Password Authentication” are strong authentication methods. Another note, this uses Get-MgUserAuthenticationMethod under the hood and formats everything in a way that’s human readable.
Function Get-MsGraphAuthenticationMethod { <# .SYNOPSIS List MFA Authentication Methods for users using Graph API. A session using Connect-Graph must be open as a requirement. .NOTES Name: Get-MsGraphAuthenticationMethod Author: [email protected] Version: 1.1 DateCreated: 2021-Jan-20 .EXAMPLE Get-MsGraphAuthenticationMethod -UserId [email protected], [email protected] .EXAMPLE Get-MsGraphAuthenticationMethod -UserId [email protected], [email protected] -MethodType MicrosoftAuthenticatorApp, EmailAuthencation .LINK https://thesysadminchannel.com/get-mfa-methods-using-msgraph-api-and-powershell-sdk/ - #> [CmdletBinding()] param( [Parameter( Mandatory = $true, Position = 0 )] [Alias('UserPrincipalName')] [string[]] $UserId, [Parameter( Mandatory = $false )] [ValidateSet('AuthenticatorApp', 'PhoneAuthentication', 'Fido2', 'WindowsHelloForBusiness', 'EmailAuthentication', 'TemporaryAccessPass', 'Passwordless', 'SoftwareOath')] [string[]] $MethodType ) BEGIN { $ConnectionGraph = Get-MgContext if (-not $ConnectionGraph) { Write-Error "Please connect to Microsoft Graph" -ErrorAction Stop } } PROCESS { foreach ($User in $UserId) { try { $DeviceList = Get-MgUserAuthenticationMethod -UserId $User -ErrorAction Stop $DeviceOutput = foreach ($Device in $DeviceList) { #Converting long method to short-hand human readable method type. switch ($Device.AdditionalProperties["@odata.type"]) { '#microsoft.graph.microsoftAuthenticatorAuthenticationMethod' { $MethodAuthType = 'AuthenticatorApp' $AdditionalProperties = $Device.AdditionalProperties["displayName"] } '#microsoft.graph.phoneAuthenticationMethod' { $MethodAuthType = 'PhoneAuthentication' $AdditionalProperties = $Device.AdditionalProperties["phoneType", "phoneNumber"] -join ' ' } '#microsoft.graph.passwordAuthenticationMethod' { $MethodAuthType = 'PasswordAuthentication' $AdditionalProperties = $Device.AdditionalProperties["displayName"] } '#microsoft.graph.fido2AuthenticationMethod' { $MethodAuthType = 'Fido2' $AdditionalProperties = $Device.AdditionalProperties["model"] } '#microsoft.graph.windowsHelloForBusinessAuthenticationMethod' { $MethodAuthType = 'WindowsHelloForBusiness' $AdditionalProperties = $Device.AdditionalProperties["displayName"] } '#microsoft.graph.emailAuthenticationMethod' { $MethodAuthType = 'EmailAuthentication' $AdditionalProperties = $Device.AdditionalProperties["emailAddress"] } '#microsoft.graph.temporaryAccessPassAuthenticationMethod' { $MethodAuthType = 'TemporaryAccessPass' $AdditionalProperties = 'TapLifetime:' + $Device.AdditionalProperties["lifetimeInMinutes"] + 'm - Status:' + $Device.AdditionalProperties["methodUsabilityReason"] } '#microsoft.graph.passwordlessMicrosoftAuthenticatorAuthenticationMethod' { $MethodAuthType = 'Passwordless' $AdditionalProperties = $Device.AdditionalProperties["displayName"] } '#microsoft.graph.softwareOathAuthenticationMethod' { $MethodAuthType = 'SoftwareOath' $AdditionalProperties = $Device.AdditionalProperties["displayName"] } } [PSCustomObject]@{ UserPrincipalName = $User AuthenticationMethodId = $Device.Id MethodType = $MethodAuthType AdditionalProperties = $AdditionalProperties } } if ($PSBoundParameters.ContainsKey('MethodType')) { $DeviceOutput | Where-Object {$_.MethodType -in $MethodType} } else { $DeviceOutput } } catch { Write-Error $_.Exception.Message } finally { $DeviceList = $null $MethodAuthType = $null $AdditionalProperties = $null } } } END {} }
Script Examples
Get-MsGraphAuthenticationMethod -UserId [email protected], [email protected]
Get-MsGraphAuthenticationMethod -UserId [email protected], [email protected] -MethodType AuthenticatorApp, TemporaryAccessPass
Conclusion
Hopefully this script to Get MFA Methods using MSGraph API and PowerShell SDK would be useful to replace the legacy method of querying MSOnline to get the user’s strong auth methods. Since this utilizes Microsoft Graph and REST APIs in the backend, it can work extremely fast with PowerShell 7 and Foreach-Object -Parallel.
I use this on a regular basis to see if a user has MFA enabled on their account. The only downside so far is that it does not show the default method type, but I’m sure that’s somewhere down the pipeline.
If you liked this script and wanted to get more exposure to Graph API, I’ve just recently created the subreddit https://reddit.com/r/graphapi for folks to who want to learn and ask questions. I’m also going to be posting all my conversion scripts from the Azure AD module to GraphAPI so be sure check in time to time on our Graph API category posts
Hello smart people, I’m trying to provide a report of users which have SMS and/or call to phone registered as an auth method for MFA. But crucially be able to distinguish between the two.
Using the native reports in the portal you only get returned “mobile phone” and does not distinguish if this is SMS or call to phone.
Looking into graph this query again only returns “mobilephone” https://graph.microsoft.com/beta/reports/authenticationMethods/userRegistrationDetails/{ID}
This query which is being deprecated does list in the sample response on the page “mobileSMS” however when I use the query I get back “mobilephone”https://learn.microsoft.com/en-us/graph/api/reportroot-list-credentialuserregistrationdetails?view=graph-rest-beta&tabs=powershell#response-1
If anyone has any pointers it would be much appreciated. Thanks.
Thanks for this. I modified the script to read from a CSV of users and output to a CSV file.
It was the switch statement I was after.
Thank you for providing.
The email authmethod is also not a strong authentication method. This is why it’s left in the methods list when MFA is revoked or reset…
Not sure what I’m doing wrong, but when trying to run this script nothing happens. I don’t even get the pop-up dialog box to sign in.
Is seems that you have to import the module:
Import-Module .\Get-MsGraphAuthenticationMethod.ps1
If the ‘MethodType’ is ‘PasswordAuthentication’ does that mean that MFA is not enabled for that account?
Yes that is correct.
This was very useful in building a script based on Mark’s question above.
We have over 10k users and needed a report for our InfoSec. It took about 15 hours to run but I was able to return accounts that did not have MFA configured
Hi Kevin, I am interesting on your script based on Mark’s.
I have the same request internally and I am searching someting that can help us.
Thanks
Hi Paul, Great script. One enhancement could be that all this is saved in csv format.
Hi Mark – Thanks for the feedback. Typically this should be done outside of the function since some users won’t want to export it and some will.
If you’re checking everyone in the domain, exporting to a csv would be very helpful. However if checking 1 or 2 users it makes more sense to output it to the console