External MFA in Entra ID: how it works and what it means for custom controls
The preview label is gone from the documentation for external authentication methods in Microsoft Entra ID, and the feature now goes by the name External MFA. If your third-party MFA provider is still wired in through a Conditional Access custom control, this is the integration Microsoft wants you on. This post covers what actually happens during the sign-in, why the result counts as MFA where a custom control never did, and what I would check before migrating.
Photo: Getty Images on Unsplash
What changed this week
externalAuthenticationMethodConfiguration for the tenant policy, externalAuthenticationMethod for a user's registration) already moved to v1.0 in January. The public preview started in May 2024 with nine providers on board: Cisco Duo, Entrust, HYPR, Ping Identity, RSA, Silverfort, Symantec VIP, Thales and TrustBuilder.Custom controls themselves are still where they were: a preview feature that never left preview. Microsoft has positioned external authentication methods as their replacement since the 2024 preview announcement, but as I write this there is no published retirement date. I wouldn't wait for one: the functional limits of custom controls described below are reason enough to move.
What happens during a sign-in
authorization_endpoint (taken from the provider's discovery document) with a form POST. It uses the implicit flow with response_type=id_token and passes an id_token_hint: a token signed by Entra ID that describes the user (oid, tid, sub, preferred_username) with the provider's client ID as audience. That hint is deliberately issued already expired, so it can only ever serve as a hint and never as a credential.The provider validates the hint against Entra's published keys, optionally looks the user up in Graph using
oid and tid, does its own authentication, and POSTs an id_token back to https://login.microsoftonline.com/common/federation/externalauthprovider. Entra ID then checks that token more strictly than most people expect: {
"iss": "https://mfa.provider.example",
"aud": "<client ID of Entra ID at the provider>",
"sub": "<same sub as in the id_token_hint>",
"nonce": "<nonce from the request>",
"acr": "possessionorinherence",
"amr": ["otp"],
"iat": 1772100000,
"exp": 1772100300
}
sub must match the hint, the nonce must be echoed, acr must be one of the values Entra asked for, and amr must contain exactly one value from a fixed list. Entra ID maps that amr to a factor type (otp, sms, tel, fido, hwk, pop, sc and swk are possession; fpt, face, iris, retina and vbm are inherence) and checks that it differs from the type of the first factor. Only then is MFA considered satisfied, and from that point the session carries MFA exactly as it would after an Authenticator approval. The provider reports which kind of factor was used, and Entra ID decides whether that adds up to MFA.A few details that explain most failed integrations: the discovery URL must end in
/.well-known/openid-configuration without query string, the issuer must match character for character (an explicit :443 breaks it), the JWKS must include x5c, and the kid encoding in token and JWKS must line up. Entra ID caches provider metadata for 24 hours, which matters for key rollover, and abandons the attempt about 5 minutes after the redirect. If the provider's multitenant app has no admin consent in your tenant, you get AADSTS900491; consent needs at least Privileged Role Administrator. External MFA as an authentication method
Users register it in Security info under External Auth methods, through the registration wizard at sign-in, or an admin registers it for them. Registered users don't appear in the authentication method registration reports, which will make your MFA coverage numbers look worse than they are.
On system-preferred MFA the documentation contradicts itself. The February 2025 change that added external methods to system-preferred MFA ranks them third, after Temporary Access Pass and passkeys but above Authenticator notifications, and it also lets users in scope of the external method delete their other second factors even when one is the default. The manage page, however, uses the example of a user with Authenticator who gets number matching first and has to pick the external method themselves. Test this with a pilot user who has both before you write the end-user instructions.
External MFA doesn't satisfy authentication strengths, not even the built-in Multifactor authentication strength. Policies need the plain Require multifactor authentication grant. If you require phishing-resistant MFA for admins through a strength, or protect PIM activation with an authentication context that points to a strength, External MFA won't get those users through.
Where custom controls fall short
PIM activation with "require MFA" doesn't accept the custom control, so as far as I can tell PIM falls back to Microsoft MFA, which for a user whose only second factor is the custom control means registering a Microsoft method first. The preview announcement for external authentication methods explicitly listed PIM activation as something they satisfy.
Mandatory MFA for Azure is stated plainly: the custom controls preview doesn't meet the requirement, external authentication methods do. With phase 2 rolling out since October 2025 (Azure CLI, Azure PowerShell, IaC tools and the REST API for create, update and delete operations), this has become a practical problem for admins whose only second factor is a custom control.
Security info requires MFA in the current session (since August 2025 a fresh one if the last was more than 10 minutes ago). A custom control doesn't produce that MFA, so in practice users also need a Microsoft method registered just to manage their security info. That is how tenants on custom controls end up running two MFA systems side by side without really meaning to.
Running both during the migration
- Inventory every policy that uses a custom control, including report-only and disabled ones.
- Ask your provider for their External MFA integration (App ID, client ID, discovery URL); a provider that only supports custom controls is the real blocker.
- Add the method, grant consent, scope it to a pilot group.
- Register the pilot users, or let them register themselves.
- Exclude the pilot group from the custom control policy and include it in the MFA policy; check sign-in logs, PIM activation and Security info.
- Widen the group, then turn the custom control policy off and delete the control.
Connect-MgGraph -Scopes "Policy.Read.All","UserAuthMethod-External.ReadWrite.All"
# Conditional Access policies that require a custom control
Get-MgIdentityConditionalAccessPolicy -All |
Where-Object { $_.GrantControls.CustomAuthenticationFactors } |
Select-Object DisplayName, State,
@{N='CustomControls'; E={ $_.GrantControls.CustomAuthenticationFactors -join ', ' }},
@{N='BuiltIn'; E={ $_.GrantControls.BuiltInControls -join ', ' }},
@{N='Operator'; E={ $_.GrantControls.Operator }}
# External MFA methods in the authentication methods policy
$amp = Invoke-MgGraphRequest -Method GET -Uri "https://graph.microsoft.com/v1.0/policies/authenticationMethodsPolicy"
$amp.authenticationMethodConfigurations |
Where-Object { $_.'@odata.type' -eq '#microsoft.graph.externalAuthenticationMethodConfiguration' } |
ForEach-Object { [pscustomobject]@{ Id = $_.id; Name = $_.displayName; State = $_.state; DiscoveryUrl = $_.openIdConnectSetting.discoveryUrl } }
# Register External MFA for a user on their behalf
# (the signed-in admin needs Authentication Administrator or Privileged Authentication Administrator)
$body = @{ configurationId = "<Id from the previous output>"; displayName = "<method name>" } | ConvertTo-Json
Invoke-MgGraphRequest -Method POST -Uri "https://graph.microsoft.com/v1.0/users/<user id>/authentication/externalAuthenticationMethods" -Body $body -ContentType "application/json"
What users see
This week I would run the inventory script, send your MFA vendor a request for their External MFA integration details, and set up a pilot group with one or two admins who use PIM, because that's where the difference shows first.
Update March 2026: The general availability announcement on the Microsoft Entra blog (24 March) put a date on custom controls: they will be deprecated on 30 September 2026. Also in March (page dated 18 March), the system-preferred ranking on Learn was rewritten and now places Microsoft Authenticator notifications above External MFA, in line with the number matching example on the manage page.
Update June 2026: In Microsoft Entra ID security updates: What organizations need to do now Microsoft split this into two dates: custom controls retire on 30 September 2026 and reach end of life in May 2027. Learn now also has a migration guide from custom controls to External MFA.
Update July 2026: Message Center MC1422061 spells out what the September date means: from then on you can't create or edit custom controls, and existing ones keep working until May 2027. Because editing a custom control already meant deleting and recreating it, any change your provider needs in the control's JSON after September is no longer possible.
Sources
- Manage an external MFA method in Microsoft Entra ID
- Microsoft Entra external MFA method provider reference
- Custom controls in Conditional Access
- Mandatory Microsoft Entra multifactor authentication for Azure
- System-preferred authentication
- Combined security information registration
- Microsoft Graph: externalAuthenticationMethodConfiguration resource type
- Microsoft Graph: create externalAuthenticationMethod
- External MFA in Microsoft Entra ID is now generally available (Microsoft Entra blog)
- Microsoft Entra ID security updates: What organizations need to do now (Microsoft Entra blog)
- Migrate from custom controls to External MFA
- MC1422061: retirement of Custom Controls in Conditional Access