External MFA in Entra ID: how it works and what it means for custom controls

Samantha Kloos-Kilkens
Feb 26, 2026 · Samantha Kloos-Kilkens

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.

A covered footbridge connecting two brick buildings Photo: Getty Images on Unsplash

What changed this week

On 24 February Microsoft updated the documentation: the preview label is gone from Manage an external MFA method in Microsoft Entra ID, the feature is renamed to External MFA, and the button in the admin center under Authentication methods is now called Add external MFA. The Graph resources for it (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

External MFA is built on OpenID Connect, and the provider reference is worth reading in full even if you never build a provider. The flow is short. The user completes the first factor in Entra ID. Conditional Access decides MFA is needed, the user picks the external method, and Entra ID sends the browser to the provider's 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
}
The 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

External MFA lives in the authentication methods policy next to Authenticator and passkeys, scoped to groups like any other method. You need three values from the provider: the App ID of their (usually multitenant) app, a client ID and the discovery URL. The display name you enter is what users see in the method picker and can't be changed afterwards, so choose it with that in mind. It's a second factor only; it can't be used as first factor or for SSPR.

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

A custom control is a grant control. Conditional Access redirects the user, gets a positive answer back, and that one policy is satisfied. Nothing is added to the session that says MFA happened. The custom controls page lists what that rules out: ID Protection policies requiring MFA, SSPR, satisfying MFA claim requirements, sign-in frequency, PIM, Intune enrollment, cross-tenant trusts and joining devices to Entra ID. The ones I'd look at first are PIM, Azure and Security info.

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

Microsoft supports custom controls and External MFA in parallel and recommends two Conditional Access policies with separate pilot groups: the existing one with the custom control, and a copy with Require multifactor authentication. A user in both policies is sent to the provider twice, once for MFA and once for the custom control. The order I'd follow:
  1. Inventory every policy that uses a custom control, including report-only and disabled ones.
  2. 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.
  3. Add the method, grant consent, scope it to a pilot group.
  4. Register the pilot users, or let them register themselves.
  5. 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.
  6. Widen the group, then turn the custom control policy off and delete the control.
For the inventory and the admin registration, Graph PowerShell is enough:
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

The method shows up in the picker under the display name you chose, and selecting it sends the browser to the provider's own page. Sign-in frequency decides how often that happens, so this is a good moment to check your reauthentication settings instead of copying the custom control setup. One known gap: Windows 10 OOBE doesn't support External MFA for an identity that has no other method, and Microsoft has no plans to add it there; Windows 11 works.

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.

Written by an Argus IT expert

Want an expert like this in your team, or work like this yourself in security, IAM or cloud?

Stay in the Loop

Subscribe to our newsletter for a friendly nudge whenever we publish a new article or have news to share.