Entra / Microsoft 365 · Users & guests
Report MFA status for users
Report the authentication methods registered for Entra ID user accounts.
Connect & set up
Run these once per session. All scopes are read-only unless the script makes changes.
Connect-MgGraph -Scopes UserAuthenticationMethod.Read.All, Directory.Read.All, User.Read.All, AuditLog.Read.All -NoWelcome
Run it
The main script. Copy it, or download the .ps1 and run it from your console.
Connect-MgGraph -Scope UserAuthenticationMethod.Read.All, Directory.Read.All, User.Read.All, Auditlog.Read.All, UserAuthenticationMethod.Read.All -NoWelcome# Get user accounts (exclude guests)Write-Host "Looking for Entra ID user accounts to check"[array]$Users = Get-MgUser -All -Filter "UserType eq 'Member'"If (!($Users)) { Write-Host "No accounts found for some reason... exiting" ; break}Else { Write-Host ("{0} Entra ID member accounts found (not all are user accounts which authenticate)" -f $Users.count ) }$CheckedUsers = 0$Report = [System.Collections.Generic.List[Object]]::new()ForEach ($User in $Users) {# Try and find a sign in record for the user - this eliminates unused accounts# Write-Host "Checking" $User.DisplayName[array]$LastSignIn = Get-MgAuditLogSignIn -Filter "UserId eq '$($User.Id)'" -Top 1If ($LastSignIn) {$CheckedUsers++Write-Host "Sign in found - checking authentication methods for" $User.DisplayName[array]$MfaData = Get-MgUserAuthenticationMethod -UserId $User.Id# Process each of the authentication methods found for an accountForEach ($MfaMethod in $MfaData) {Switch ($MfaMethod.AdditionalProperties["@odata.type"]) {"#microsoft.graph.microsoftAuthenticatorAuthenticationMethod" { # Microsoft Authenticator App$AuthType = 'AuthenticatorApp'$AuthTypeDetails = $MfaMethod.AdditionalProperties["displayName"] }"#microsoft.graph.phoneAuthenticationMethod" { # Phone authentication$AuthType = 'PhoneAuthentication'$AuthTypeDetails = $MfaMethod.AdditionalProperties["phoneType", "phoneNumber"] -join ' ' }"#microsoft.graph.fido2AuthenticationMethod" { # FIDO2 key$AuthType = 'Fido2'$AuthTypeDetails = $MfaMethod.AdditionalProperties["model"] }"#microsoft.graph.passwordAuthenticationMethod" { # Password$AuthType = 'PasswordAuthentication'$AuthTypeDetails = $MfaMethod.AdditionalProperties["displayName"] }"#microsoft.graph.windowsHelloForBusinessAuthenticationMethod" { # Windows Hello$AuthType = 'WindowsHelloForBusiness'$AuthTypeDetails = $MfaMethod.AdditionalProperties["displayName"] }"#microsoft.graph.emailAuthenticationMethod" { # Email Authentication$AuthType = 'EmailAuthentication'$AuthTypeDetails = $MfaMethod.AdditionalProperties["emailAddress"] }"microsoft.graph.temporaryAccessPassAuthenticationMethod" { # Temporary Access pass$AuthType = 'TemporaryAccessPass'$AuthTypeDetails = 'Access pass lifetime (minutes): ' + $MfaMethod.AdditionalProperties["lifetimeInMinutes"] }"#microsoft.graph.passwordlessMicrosoftAuthenticatorAuthenticationMethod" { # Passwordless$AuthType = 'Passwordless'$AuthTypeDetails = $MfaMethod.AdditionalProperties["displayName"] }"#microsoft.graph.softwareOathAuthenticationMethod" { # Software Authenticator App$AuthType = 'Third-party Authenticator App'$AuthTypeDetails = $MfaMethod.AdditionalProperties["displayName"] }} # End switch# Note what we found$ReportLine = [PSCustomObject][Ordered]@{User = $User.DisplayNameUPN = $User.UserPrincipalNameMethod = $AuthTypeDetails = $AuthTypeDetailsLastSignIn = $LastSignIn.CreatedDateTimeLastSignInApp = $LastSignIn.AppDisplayName}$Report.Add($ReportLine)} #End Foreach MfaMethod} # End if} # End ForEach Users# Take the report file and check each user to see if they use a strong authentication method$OutputFile = [System.Collections.Generic.List[Object]]::new()[array]$AuthUsers = $Report | Sort-Object UPN -Unique | Select-Object UPN, User, LastSignIn, LastSignInAppForEach ($AuthUser in $AuthUsers) {$MFAStatus = $Null$Records = $Report | Where-Object {$_.UPN -eq $AuthUser.UPN}$Methods = $Records.Method | Sort-Object -UniqueSwitch ($Methods) {"Fido2" { $MFAStatus = "Good" }"PhoneAuthentication" { $MFAStatus = "Good" }"AuthenticatorApp" { $MFAStatus = "Good" }"Passwordless" { $MFAStatus = "Good" }Default { $MFAStatus = "Check!" }} # End Switch$ReportLine = [PSCustomObject][Ordered]@{User = $AuthUser.UserUPN = $AuthUser.UPNMethods = $Methods -Join ", "MFAStatus = $MFAStatusLastSignIn = $AuthUser.LastSignInLastSignInApp = $AuthUser.LastSignInApp }$OutputFile.Add($ReportLine)}$OutputFile | Out-GridView$OutputFile | Export-CSV -NoTypeInformation c:\Temp\MFAStatus.CSV
Attribution
Author
Office365itpros