Back to script library
Entra / Microsoft 365 · Users & guests

Report MFA status for admins

Use the User Registration Details API to report admin accounts that are not MFA-enabled.

Connect & set up

Run these once per session. All scopes are read-only unless the script makes changes.

Connect-MgGraph -Scopes UserAuthenticationMethod.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 -Scopes UserAuthenticationMethod.Read.All, AuditLog.Read.All
Select-MgProfile Beta
Write-Host "Retrieving information about users holding Microsoft 365 administrative roles"
$AdminRoleHolders = [System.Collections.Generic.List[Object]]::new()
[array]$AdminRoles = Get-MgDirectoryRole | Select-Object DisplayName, Id | Sort-Object DisplayName
ForEach ($Role in $AdminRoles) {
[array]$RoleMembers = Get-MgDirectoryRoleMember -DirectoryRoleId $Role.Id | ? {$_.AdditionalProperties."@odata.type" -eq "#microsoft.graph.user"}
ForEach ($Member in $RoleMembers) {
$UserDetails = Get-MgUser -UserId $Member.Id
$ReportLine = [PSCustomObject] @{
User = $UserDetails.UserPrincipalName
Id = $UserDetails.Id
Role = $Role.DisplayName
RoleId = $Role.Id }
$AdminRoleHolders.Add($ReportLine) }
}
$AdminRoleHolders = $AdminRoleHolders | Sort User
$Unique = $AdminRoleHolders | Sort-Object User -Unique
# Create a slightly different report where each user has their assigned roles in one record
$UniqueAdminRoleHolders = [System.Collections.Generic.List[Object]]::new()
ForEach($User in $Unique) {
$Records = $AdminRoleHolders | Where-Object {$_.id -eq $User.Id}
$AdminRoles = $Records.Role -join ", "
$ReportLine = [PSCustomObject] @{
Id = $User.Id
User = $User.User
Roles = $AdminRoles }
$UniqueAdminRoleHolders.Add($ReportLine)
}
Write-Host ("There are {0} user accounts holding Microsoft 365 administrative roles." -f $UniqueAdminRoleHolders.count)
Write-Host "Scanning for MFA status"
# Retrieve member accounts that are licensed
[array]$Users = Get-MgUser -Filter "assignedLicenses/`$count ne 0 and userType eq 'Member'" -ConsistencyLevel eventual -CountVariable Records -All
$UserRegistrationDetails = [System.Collections.Generic.List[Object]]::new()
ForEach ($User in $Users) {
Write-Host ("Checking admin roles and MFA status for {0}" -f $User.DisplayName)
$Uri = "https://graph.microsoft.com/beta/reports/authenticationMethods/userRegistrationDetails/" + $User.Id
$AccessMethodData = Invoke-MgGraphRequest -Uri $Uri -Method Get
# Check if Admin
$AdminAccount = $False; $AdminRolesHeld = $Null
If ($user.id -in $UniqueAdminRoleHolders.Id) {
$AdminAccount = $True
$AdminRolesHeld = ($UniqueAdminRoleHolders | ? {$_.Id -eq $User.Id} | Select -ExpandProperty Roles) }
$ReportLine = [PSCustomObject] @{
User = $User.Displayname
Id = $User.Id
AdminAccount = $AdminAccount
AdminRoles = $AdminRolesHeld
MfaRegistered = $AccessMethodData.isMfaRegistered
defaultMfaMethod = $AccessMethodData.defaultMfaMethod
isMfaCapable = $AccessMethodData.isMfaCapable
Methods = $AccessMethodData.MethodsRegistered -join ", " }
$UserRegistrationDetails.Add($ReportLine)
} #End ForEach
[Array]$ProblemAdminAccounts = $UserRegistrationDetails | Where-Object {$_.AdminAccount -eq $True -and $_.MfaRegistered -eq $False }
If ($ProblemAdminAccounts) {
Cls
Write-Host "The following accounts have administrative roles and are not enabled for MFA."
Write-Host "-----------------------------------------------------------------------------"
Write-Host ""
$ProblemAdminAccounts | Select User, AdminRoles
}
$UserRegistrationDetails | Export-Excel -Path c:\temp\UserRegistrationDetails.xlsx
Attribution