With Microsoft requiring multi-factor authentication for all Azure portal access from October 2026 onwards, knowing exactly which users in your tenant are MFA-registered has never been more critical. Chasing this information through the Entra ID portal one user at a time does not scale. This guide shows you how to pull a complete MFA registration audit report for your entire tenant using PowerShell and the Microsoft Graph API, then export the results to CSV for review or remediation workflows.
Prerequisites
Before running the scripts below, make sure you have the following in place:
- The Microsoft.Graph PowerShell module installed (version 2.x or later recommended)
- An Entra ID account with at least the Reports Reader or Authentication Administrator role
- PowerShell 7.2 or later (the scripts also work on Windows PowerShell 5.1 with minor adjustments)
- Appropriate Graph API permissions:
UserAuthenticationMethod.Read.AllandAuditLog.Read.All
Connecting to Microsoft Graph
Start by installing the module if you have not already done so, then authenticate with the scopes needed for authentication method reporting:
# Install the module (run once, requires admin or user scope)
Install-Module Microsoft.Graph -Scope CurrentUser -Force
# Connect with required scopes
Connect-MgGraph -Scopes "UserAuthenticationMethod.Read.All", "AuditLog.Read.All", "User.Read.All"
# Verify the connection
Get-MgContext | Select-Object Account, TenantId, Scopes Once connected, Graph will prompt you to consent to the requested permissions if this is your first time using these scopes in the tenant. A Global Administrator may need to grant tenant-wide admin consent for UserAuthenticationMethod.Read.All if your organisation restricts user consent.
Pulling the MFA Registration Report
The Microsoft Graph API exposes a dedicated endpoint for credential user registration details. This endpoint returns one record per user, including which authentication methods they have registered and whether they are capable of MFA, passwordless sign-in, and self-service password reset (SSPR).
# Retrieve credential registration details for all users
$registrationDetails = Get-MgReportAuthenticationMethodUserRegistrationDetail -All
# Preview the first result
$registrationDetails | Select-Object -First 1 | Format-List Each object returned contains properties like IsMfaRegistered, IsMfaCapable, IsPasswordlessCapable, IsSsprRegistered, and MethodsRegistered. This gives you everything needed to identify users who are not yet MFA-ready.
Filtering for Non-MFA Users and Exporting to CSV
With the full dataset in memory, you can filter and export in a single pipeline. The example below identifies all users who are not MFA-registered, enriches the records with their display name and UPN, then writes the results to a CSV file you can share with your helpdesk or management team:
# Get all users without MFA registered
$notMfaRegistered = $registrationDetails | Where-Object { -not $_.IsMfaRegistered }
# Build an enriched report
$report = foreach ($user in $notMfaRegistered) {
[PSCustomObject]@{
DisplayName = $user.UserDisplayName
UserPrincipalName = $user.UserPrincipalName
IsMfaRegistered = $user.IsMfaRegistered
IsMfaCapable = $user.IsMfaCapable
IsPasswordlessCapable = $user.IsPasswordlessCapable
IsSsprRegistered = $user.IsSsprRegistered
MethodsRegistered = ($user.MethodsRegistered -join ', ')
UserType = $user.UserType
}
}
# Export to CSV
$reportPath = "C:ReportsMFA_Not_Registered_$(Get-Date -Format 'yyyyMMdd').csv"
$report | Export-Csv -Path $reportPath -NoTypeInformation -Encoding UTF8
Write-Host "Report saved to: $reportPath" -ForegroundColor Green
Write-Host "Total users without MFA: $($report.Count)" Breaking Down Results by Authentication Method
It is also useful to understand which authentication methods your registered users are actually using. The following snippet groups the registered population by their methods so you can see the split between Microsoft Authenticator, FIDO2, phone-based OTP, and other options:
# Only look at users who ARE registered
$mfaRegistered = $registrationDetails | Where-Object { $_.IsMfaRegistered }
# Expand and group by method
$methodBreakdown = $mfaRegistered |
ForEach-Object { $_.MethodsRegistered } |
Group-Object |
Sort-Object Count -Descending |
Select-Object Name, Count
$methodBreakdown | Format-Table -AutoSize
# Example output:
# Name Count
# ---- -----
# microsoftAuthenticatorPush 8421
# softwareOneTimePasscode 2104
# email 1876
# mobilePhone 943
# fido2 312 Putting It All Together: A Scheduled Audit Script
For ongoing compliance, wrap everything into a single script you can run from a scheduled task or a GitHub Actions workflow. The script below connects non-interactively using a service principal (app registration with a certificate), pulls the report, and emails a summary using Microsoft Graph mail sending:
# === CONFIG ===
$TenantId = "your-tenant-id"
$ClientId = "your-app-client-id"
$CertThumb = "your-certificate-thumbprint"
$ReportFolder = "C:Reports"
$AlertEmail = "[email protected]"
# Connect using certificate-based auth (no interactive prompt)
Connect-MgGraph -TenantId $TenantId -ClientId $ClientId -CertificateThumbprint $CertThumb
# Pull registration details
$details = Get-MgReportAuthenticationMethodUserRegistrationDetail -All
$notMfa = $details | Where-Object { -not $_.IsMfaRegistered -and $_.UserType -eq 'member' }
$totalUsers = ($details | Where-Object { $_.UserType -eq 'member' }).Count
$mfaPct = [math]::Round((($totalUsers - $notMfa.Count) / $totalUsers) * 100, 1)
# Export CSV
$csv = Join-Path $ReportFolder "MFA_Audit_$(Get-Date -Format 'yyyyMMdd').csv"
$notMfa | Select-Object UserDisplayName, UserPrincipalName, IsMfaRegistered, MethodsRegistered |
Export-Csv -Path $csv -NoTypeInformation -Encoding UTF8
# Send summary email via Graph
$body = @{
message = @{
subject = "Weekly MFA Registration Audit - $([math]::Round($mfaPct,1))% Compliant"
body = @{
contentType = "Text"
content = "MFA audit complete. $($notMfa.Count) of $totalUsers member accounts are not MFA-registered ($mfaPct% compliant). Report attached."
}
toRecipients = @(@{ emailAddress = @{ address = $AlertEmail } })
}
saveToSentItems = $false
}
Send-MgUserMail -UserId $AlertEmail -BodyParameter $body
Write-Host "Audit complete. $($notMfa.Count) users flagged. Email sent to $AlertEmail." Summary
With just a few dozen lines of PowerShell and the Microsoft Graph module, you can produce a detailed, exportable MFA registration audit for your entire Entra ID tenant. Running this on a schedule gives your IT team continuous visibility into compliance posture ahead of Microsoft’s October 2026 MFA mandate for Azure portal access. From there, you can feed the CSV into a ticketing system, trigger automated nudge emails to unregistered users, or build a Power BI dashboard to track progress over time.
The Get-MgReportAuthenticationMethodUserRegistrationDetail cmdlet is one of the more powerful reporting endpoints in the Graph SDK, and combining it with certificate-based service principal authentication means this workflow can run fully unattended in your environment.
Read next: Setting Up a Service Principal with Certificate Auth for Microsoft Graph – a step-by-step guide to creating the app registration, generating the certificate, and granting the right permissions.