Your MFA Number Is Probably Wrong. Here's How to Check It in 5 Minutes.

Someone above you asks a simple question: "What percentage of our users have MFA?"
You open the Entra admin center, find a number that looks right, and send it. It goes into a slide, then into an audit response, then into a cyber insurance renewal form.
That number is probably wrong. You didn't make a mistake. The portal shows more than one "MFA" number, it leaves some users out, and it can be a day and a half old. If you look after more than one tenant, it gets worse, because the step where you add the tenants together is where most people lose the plot.
This post shows you how to get a number you can defend for your own tenant in about five minutes. Then it covers what goes wrong once you have several.
Registered Is Not the Same as Capable
Microsoft's registration report tracks two different things, and they sound almost identical.
- MFA registered means the user has set up a strong authentication method, like the Authenticator app or a FIDO2 key.
- MFA capable means the user has registered a strong method and your authentication methods policy allows them to use it for MFA.
The gap between the two is where people get caught. A user can register a phone number, then you tighten policy and turn SMS off. They still count as registered. They are no longer capable. When you look them up, it says "registered", but they can't do MFA with anything your tenant accepts.
If someone asks whether users are protected, the honest answer is the capable figure. Registered tells you who has been through setup. Capable tells you who can actually pass MFA today.
Note: Neither number tells you whether MFA is required. That is a Conditional Access question, and I covered the policy side in Conditional Access for Azure Virtual Desktop. A user can be fully capable and still sign in with just a password if no policy asks for more. Capable is the floor, not the finish line.
What the Portal Leaves Out
Microsoft documents three limits on this report, and most people never read that page:
- Disabled users are not listed, and neither are recently deleted ones. That is usually what you want, but it means the report's total won't match the user count you see elsewhere, and someone will ask why.
- The data can be up to 36 hours old. A user who registered this morning may not show up yet. If you just ran an MFA push, your number will look worse than it is for a day or so.
- It needs an Entra ID P1 or P2 licence. If the report isn't there, that's why.
None of that is a bug. It does mean a percentage copied from the portal with no date or definition next to it isn't worth much.
Check Your Own Tenant
You need PowerShell 7 (new to it? start with PowerShell basics), the Microsoft Graph PowerShell module, and an account with at least the Reports Reader role. The script only reads data. It needs the AuditLog.Read.All permission, which it requests when you sign in.
# One-time install (the Authentication module comes with it)
Install-Module Microsoft.Graph.Reports -Scope CurrentUser
# Sign in to the tenant you want to check
Connect-MgGraph -Scopes "AuditLog.Read.All" -TenantId "contoso.onmicrosoft.com"
# Pull every user's registration details (-All follows paging for you)
$report = Get-MgReportAuthenticationMethodUserRegistrationDetail -All
$members = $report | Where-Object UserType -eq "member"
$total = $members.Count
$registered = @($members | Where-Object IsMfaRegistered).Count
$capable = @($members | Where-Object IsMfaCapable).Count
"{0} users | registered {1} ({2:P0}) | capable {3} ({4:P0})" -f `
$total, $registered, ($registered / $total), $capable, ($capable / $total)
The output is one line:
412 users | registered 371 (90%) | capable 349 (85%)
That 5-point gap is 22 people who have set something up but can't pass MFA with any method you currently allow. Now check the group that matters most:
# Admins who cannot pass MFA today
$members | Where-Object { $_.IsAdmin -and -not $_.IsMfaCapable } |
Select-Object UserPrincipalName, MethodsRegistered
If that returns anything, fix it before you worry about the percentage. One admin who can't do MFA is a bigger risk than a few points of general coverage.
Pro tip: I filtered to
memberso guests don't skew the figure. Guests usually do MFA in their home tenant, so counting them here makes your coverage look worse than it is. Decide whether they belong in your number, then say which you chose.
Prefer not to install anything? Open Graph Explorer, sign in, consent to AuditLog.Read.All, and run:
GET https://graph.microsoft.com/v1.0/reports/authenticationMethods/userRegistrationDetails?$filter=isMfaCapable eq false
That gives you the list of people to chase, straight from the same data.
Where It Breaks: More Than One Tenant
For one tenant, you're done. Plenty of IT people don't look after one tenant, though. You might run a parent company and two acquisitions, have a separate tenant for a subsidiary, or be an MSP with a client list.
So you run the script once per tenant and put the results in a spreadsheet. This is the step where most multi-tenant reports go wrong.
Mistake 1: averaging the percentages. Say you have three tenants:
| Tenant | Users | Capable | Coverage |
|---|---|---|---|
| Head office | 1,000 | 600 | 60% |
| Acquired firm | 40 | 40 | 100% |
| Subsidiary | 60 | 60 | 100% |
Average the last column and you get 87%. Count the people and you get 700 of 1,100, which is 64%. The two small, tidy tenants hide 400 unprotected users at head office. Always add up users, then divide. Never average percentages.
Mistake 2: one row per check, last one wins. I made this mistake myself. I was tracking how many users weren't covered by an MFA policy, across three tenants. Each tenant had the same check, so I stored one result per check and let each new scan overwrite the last. All three tenants failed, and the summary said 9 users. The real total was 24. It was showing whichever tenant had finished last. Nothing looked broken, because 9 is a believable number.
Mistake 3: mixing dates. You run head office on Monday and the subsidiary on Thursday, and each report can already be 36 hours behind. The total covers a week and belongs to no particular day. Put the date on every row.
Mistake 4: the tenant nobody remembers. The test tenant, the one from the old project, the one a contractor set up. If it isn't in the spreadsheet it isn't in the number, and those are usually the tenants with the worst coverage.
None of these are hard problems. They're repetitive, and repetitive work is where manual reports go wrong.
Doing This Across Every Tenant
This is why I built Unsave. It's a cloud cost and security tool, and the multi-tenant view is the part I care most about. You connect each tenant once. It runs security checks like this one on a schedule, then adds up the results by counting the users affected, not by averaging tenants or keeping the latest scan. When a check fails in three tenants, you see all three, and the total is the real one.
If you look after more than one tenant and you're tired of the spreadsheet, try Unsave free and see your fleet in one place. If you have a single tenant, the script above is all you need. Run it before your next report.
The Short Version
- Report MFA capable, not MFA registered.
- Check admins separately. The percentage can wait.
- Across tenants, add up users. Never average percentages.
- Put a date and a definition next to every number you send.
A coverage number with none of that attached is a guess. With all of it, you can defend it when someone asks follow-up questions.



