Scripts/Get-MFAStatus.ps1
function Get-MFA { <# .SYNOPSIS Retrieves the MFA status for all users. Script inspired by: https://activedirectorypro.com/mfa-status-powershell/ .DESCRIPTION Retrieves the MFA status for all users. The output will be written to: Output\UserInfo\ .PARAMETER OutputDir OutputDir is the parameter specifying the output directory. Default: Output\UserInfo .PARAMETER Encoding Encoding is the parameter specifying the encoding of the CSV output file. Default: UTF8 .PARAMETER Application Application is the parameter specifying App-only access (access without a user) for authentication and authorization. Default: Delegated access (access on behalf a user) .EXAMPLE Get-MFA Retrieves the MFA status for all users. .EXAMPLE Get-MFA Retrieves the MFA status for all users via application authentication. .EXAMPLE Get-MFA -Encoding utf32 Retrieves the MFA status for all users and exports the output to a CSV file with UTF-32 encoding. .EXAMPLE Get-MFA -OutputDir C:\Windows\Temp Retrieves the MFA status for all users and saves the output to the C:\Windows\Temp folder. #> [CmdletBinding()] param( [string]$OutputDir, [string]$Encoding, [switch]$Application ) if (!($Application.IsPresent)) { Connect-MgGraph -Scopes UserAuthenticationMethod.Read.All,User.Read.All -NoWelcome } try { $areYouConnected = Get-MgUser -ErrorAction stop } catch { Write-logFile -Message "[WARNING] You must call Connect-MgGraph -Scopes 'UserAuthenticationMethod.Read.All,User.Read.All' before running this script" -Color "Red" break } if ($Encoding -eq "" ){ $Encoding = "UTF8" } if ($OutputDir -eq "" ){ $OutputDir = "Output\UserInfo" if (!(test-path $OutputDir)) { New-Item -ItemType Directory -Force -Name $OutputDir | Out-Null write-logFile -Message "[INFO] Creating the following directory: $OutputDir" } } else { if (Test-Path -Path $OutputDir) { write-LogFile -Message "[INFO] Custom directory set to: $OutputDir" } else { write-Error "[Error] Custom directory invalid: $OutputDir exiting script" -ErrorAction Stop write-LogFile -Message "[Error] Custom directory invalid: $OutputDir exiting script" } } Write-logFile -Message "[INFO] Running Get-MFA" -Color "Green" Write-logFile -Message "[INFO] Identifying all the authentication methods utilized within the environment" -Color "Green" $users = Get-MgUser -All $MFAEmail = 0 $MFAfido2 = 0 $MFAapp = 0 $MFAphone = 0 $MFAsoftwareoath = 0 $MFAhellobusiness = 0 $MFAstatusAmount = 0 $results=@(); foreach ($user in $users) { $myObject = [PSCustomObject]@{ user = "-" MFAstatus = "Disabled" # Default to 'Disabled' email = "-" fido2 = "-" app = "-" password = "-" phone = "-" softwareoath = "-" hellobusiness = "-" temporaryAccessPass = "-" certificateBasedAuthConfiguration = "-" } try { $MFAData= Get-MgUserAuthenticationMethod -UserId $user.UserPrincipalName $myobject.user = $user.UserPrincipalName; 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 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.windowsHelloForBusinessAuthenticationMethod" { $myObject.hellobusiness = $true $myObject.MFAstatus = "Enabled" } "#microsoft.graph.temporaryAccessPassAuthenticationMethod" { $myObject.temporaryAccessPassAuthenticationMethod = $true $myObject.MFAstatus = "Enabled" } "#microsoft.graph.certificateBasedAuthConfiguration" { $myObject.certificateBasedAuthConfiguration = $true $myObject.MFAstatus = "Enabled" } } } } catch { Write-logFile -Message "[ERROR] Error while retrieving the MFA status for $user | Error: $_ " -Color "Red" } if($myObject.MFAstatus -eq "Enabled") { $MFAstatusAmount++ } $results+= $myObject; } $date = Get-Date -Format "yyyyMMddHHmm" $filePath = "$OutputDir\$($date)-MFA-AuthenticationMethods.csv" $results | Export-Csv -Path $filePath -NoTypeInformation -Encoding $Encoding Write-logFile -Message "[INFO] Output written to $filePath" -Color "Green" $MFAEmail = (Import-Csv -Path "$filePath" -Delimiter "," | Where-Object { $_.email -eq "True" } | Measure-Object).Count $MFAfido2 = (Import-Csv -Path "$filePath" -Delimiter "," | Where-Object { $_.fido2 -eq "True" } | Measure-Object).Count $MFAapp = (Import-Csv -Path "$filePath" -Delimiter "," | Where-Object { $_.app -eq "True" } | Measure-Object).Count $MFAphone = (Import-Csv -Path "$filePath" -Delimiter "," | Where-Object { $_.phone -eq "True" } | Measure-Object).Count $MFAsoftwareoath = (Import-Csv -Path "$filePath" -Delimiter "," | Where-Object { $_.softwareoath -eq "True" } | Measure-Object).Count $MFApassword = (Import-Csv -Path "$filePath" -Delimiter "," | Where-Object { $_.password -eq "True" } | Measure-Object).Count $MFAhellobusiness = (Import-Csv -Path "$filePath" -Delimiter "," | Where-Object { $_.hellobusiness -eq "True" } | Measure-Object).Count $MFAstatusAmount = (Import-Csv -Path "$filePath" -Delimiter "," | Where-Object { $_.MFAstatus -eq "Enabled" } | Measure-Object).Count $temporaryAccessPassAuthenticationMethod = (Import-Csv -Path "$filePath" -Delimiter "," | Where-Object { $_.temporaryAccessPassAuthenticationMethod -eq "True" } | Measure-Object).Count $certificateBasedAuthConfiguration = (Import-Csv -Path "$filePath" -Delimiter "," | Where-Object { $_.certificateBasedAuthConfiguration -eq "Enabled" } | Measure-Object).Count write-host "$MFAstatusAmount out of $($users.count) users have MFA enabled:" write-host " - $MFAEmail x Email" write-host " - $MFAfido2 x Fido2" write-host " - $MFAapp x Microsoft Authenticator App" write-host " - $MFAphone x Phone" write-host " - $MFAsoftwareoath x SoftwareOAuth" write-host " - $MFAhellobusiness x HelloBusiness" write-host " - $temporaryAccessPassAuthenticationMethod x Temporary Access Pass (TAP)" write-host " - $certificateBasedAuthConfiguration x Certificate Based Auth Configuration" write-host "" Write-logFile -Message "[INFO] Retrieving the user registration details" -Color "Green" $results=@(); $date = Get-Date -Format "yyyyMMddHHmm" $filePath = "$OutputDir\$($date)-MFA-UserRegistrationDetails.csv" Get-MgReportAuthenticationMethodUserRegistrationDetail -all | ForEach-Object { $myObject = [PSCustomObject]@{ Id = "-" IsAdmin = "-" IsMfaCapable = "-" IsMfaRegistered = "-" IsPasswordlessCapable = "-" IsSsprCapable = "-" IsSsprEnabled = "-" IsSsprRegistered = "-" IsSystemPreferredAuthenticationMethodEnabled = "-" MethodsRegistered = "-" SystemPreferredAuthenticationMethods = "-" UserDisplayName = "-" UserPreferredMethodForSecondaryAuthentication = "-" UserPrincipalName = "-" UserType = "-" AdditionalProperties = "-" } $myobject.Id = $_.Id $myobject.IsAdmin = $_.IsAdmin $myobject.IsMfaCapable = $_.IsMfaCapable $myobject.IsMfaRegistered = $_.IsMfaRegistered $myobject.IsPasswordlessCapable = $_.IsPasswordlessCapable $myobject.IsSsprCapable = $_.IsSsprCapable $myobject.IsSsprEnabled = $_.IsSsprEnabled $myobject.IsSsprRegistered = $_.IsSsprRegistered $myobject.IsSystemPreferredAuthenticationMethodEnabled = $_.IsSystemPreferredAuthenticationMethodEnabled $myobject.MethodsRegistered = $_.MethodsRegistered | out-string $myobject.SystemPreferredAuthenticationMethods = $_.SystemPreferredAuthenticationMethods | out-string $myobject.UserDisplayName = $_.UserDisplayName $myobject.UserPreferredMethodForSecondaryAuthentication = $_.UserPreferredMethodForSecondaryAuthentication $myobject.UserPrincipalName = $_.UserPrincipalName $myobject.UserType = $_.UserType $myobject.AdditionalProperties = $_.AdditionalProperties | out-string $results+= $myObject; } $results | Export-Csv -Path $filePath -NoTypeInformation -Encoding $Encoding Write-logFile -Message "[INFO] Output written to $filePath" -Color "Green" } |