Simplify user tasks like bulk creation, updates, password resets, deletions, license checks & more — all from one place.
🚀 Launch ToolkitWhile enabling Multi-Factor Authentication (MFA) is a top security priority, monitoring which users haven’t activated MFA is just as important. A single MFA-disabled account can become an entry point for attackers.
This article walks you through a Graph PowerShell script that fetches and displays only the users who have not enabled MFA in your Microsoft 365 tenant — all without relying on beta endpoints or legacy modules.
# Connect to Microsoft Graph
Connect-MgGraph -Scopes "AuditLog.Read.All", "User.Read.All", "Directory.Read.All"
# Get list of users who have enabled MFA from audit logs
$uri = "https://graph.microsoft.com/v1.0/auditLogs/directoryAudits" +
"?`$filter=activityDisplayName eq 'Enable Strong Authentication'" +
"&`$orderby=activityDateTime desc"
$response = Invoke-MgGraphRequest -Method GET -Uri $uri
# Extract UPNs of MFA-enabled users from audit logs
$mfaAuditRecords = $response.value | Where-Object { $_.targetResources -and $_.targetResources[0].userPrincipalName }
$mfaEnabledUPNs = @{}
foreach ($record in $mfaAuditRecords) {
$upn = $record.targetResources[0].userPrincipalName
if (-not $mfaEnabledUPNs.ContainsKey($upn)) {
$mfaEnabledUPNs[$upn] = $true
}
}
# Get all users in the tenant
$allUsers = Get-MgUser -All -Property UserPrincipalName, AccountEnabled, AssignedLicenses, Department
# Filter users who are NOT in the MFA-enabled list
$mfaDisabledUsers = $allUsers | Where-Object { -not $mfaEnabledUPNs.ContainsKey($_.UserPrincipalName) }
# Prepare results
$results = foreach ($user in $mfaDisabledUsers) {
[PSCustomObject]@{
'UserPrincipalName' = $user.UserPrincipalName
'MFA Activated' = "No"
'License Status' = if ($user.AssignedLicenses.Count -gt 0) { "Licensed" } else { "Unlicensed" }
'Department' = $user.Department
'Sign In Status' = if ($user.AccountEnabled) { "Allowed" } else { "Denied" }
}
}
# Display result
if ($results.Count -eq 0) {
Write-Host "All users in the tenant have MFA enabled." -ForegroundColor Green
} else {
$results | Sort-Object UserPrincipalName | Format-Table -AutoSize
}
Here’s how you can take this script further:
$results | Export-Csv -Path "MFA-DisabledUsers.csv" -NoTypeInformation
Filter users created in the past 30/90 days to spot new hires without MFA.
Combine this script with Send-MailMessage to auto-notify IT teams of any new MFA-disabled accounts.
Add filtering to scope the result to specific departments, locations, or roles.
Error | Cause | Solution |
Access Denied | Insufficient Graph permissions | Ensure AuditLog.Read.All, User.Read.All, and Directory.Read.All are granted |
NullReferenceException when accessing targetResources | Some audit records may lack userPrincipalName | Add checks to skip such entries |
Variable reference is not valid: $_ | Improper use inside strings | Use "$($upn): $($_)" for safe error messaging |
Script returns no results | All users have MFA enabled, or audit data is incomplete | Test against known MFA-disabled accounts or extend date range |
This script is incredibly useful for:
Detecting users who have not enabled MFA is just as important as confirming those who have. This Graph PowerShell script provides a fast and reliable way to identify these users by analyzing audit logs — without relying on preview APIs or external tools.
By running this audit regularly, you can stay ahead of threats and maintain tight identity security controls across your Microsoft 365 environment.
© m365corner.com. All Rights Reserved. Design by HTML Codex