Azure mandatory MFA Phase 2: which identities break at the Resource Manager layer
Since 1 July 2026, no tenant can push Phase 2 of Azure's mandatory MFA back any further. Every create, update or delete that a user account sends to Azure Resource Manager now needs MFA, whatever client it comes from. The timeline has been covered plenty elsewhere, so this post is about the mechanics: where the check actually happens, why your Conditional Access exclusions don't matter here, which accounts typically fall over, and how to find them in your logs before the first deployment fails.
Photo: Getty Images on Unsplash
What is enforced, and where
https://management.azure.com is in scope. The client doesn't matter. Azure CLI, Azure PowerShell, the Azure mobile app, the SDKs, plain REST calls and IaC tools (which authenticate through the CLI or PowerShell app IDs) all end up at the same endpoint.Only create, update and delete operations are enforced, reads aren't. That explains why many tenants thought they were fine after the rollout started: an inventory script that only runs
Get-AzResource keeps working, and the first failure shows up weeks later when somebody's deployment runs.The boundaries of the scope are just as useful to know. Microsoft Graph is generally out of scope, because only
management.azure.com is enforced; a script that uses a user account for Graph calls isn't affected by this (your own Conditional Access is a separate matter). By the same definition, data plane endpoints such as Key Vault or Storage aren't covered. Workload identities, meaning managed identities and service principals, aren't affected by either phase, and neither is the Entra Connect or Cloud Sync service account. Sovereign clouds currently aren't enforced at all.The error on the client side also shows how the enforcement is built. Microsoft's Phase 2 announcement says enforcement is applied through Azure Policy, and the FAQ says that during system enforcement Microsoft deploys the same policy you can assign yourself. A blocked write in Azure CLI comes back as
RequestDisallowedByPolicy with the text "Users must authenticate with multi-factor authentication to create or update resources", which is the display name of the built-in definition. There are two of those: one for create and update (4e6c27d5-a6ee-49cf-b2b4-d8fe90fa2b8b, Audit or Deny) and one for delete (db4a9d17-db75-4f46-9fcb-9f9526604417, AuditAction or DenyAction). With Azure CLI 2.76 or later and Az PowerShell 14.3 or later, the error also includes a ready-made az login --claims-challenge or Connect-AzAccount -ClaimsChallenge command so an interactive user can step up (see the CLI troubleshooting page). Older versions give you vaguer errors, which is a good reason to get admin workstations and build agents onto current versions.One thing I keep coming back to: Azure Policy's deny effect evaluates create and update requests, and denyAction currently only supports delete. POST actions such as listing storage account keys or restarting a VM are neither. I haven't seen Microsoft state whether system enforcement covers them, so I wouldn't treat that as a gap to rely on. I treat it as a reason why your own Conditional Access policy requiring MFA for Azure management remains the actual control, with the platform enforcement as a floor underneath it.
Conditional Access exclusions and system enforcement
The practical consequence is that your Conditional Access exclusion list is now a list of candidate failures. Every account that was excluded from MFA "for technical reasons" and writes anything in Azure is on it. There is no opt-out, test tenants are included, and once enforcement has started for your tenant the only remaining lever is a Global Administrator asking Microsoft Support to lift it temporarily.
The identities that typically break
svc-deploy account with Contributor on a subscription, signing in with Connect-AzAccount -Credential or az login -u -p, uses the resource owner password credentials (ROPC) flow, and ROPC can't do MFA. The Learn page also lists the SDK variants, including DefaultAzureCredential or EnvironmentCredential with AZURE_USERNAME and AZURE_PASSWORD set, which is easy to miss in application code that nobody on the identity team ever reads. Service accounts synced from Active Directory are affected in exactly the same way.Shared admin accounts are the next group. An
azureadmin@ account used by a whole team has usually been excluded from MFA, or has MFA registered on one person's phone, which is its own problem. Phase 2 forces the question; the right answer is personal admin accounts.Break-glass accounts are required to perform MFA too. Microsoft recommends a passkey (FIDO2) or certificate-based authentication for them, and both satisfy the requirement; the emergency access guidance now lists passkeys as the recommended method and CBA for organisations that already have a PKI. If your emergency procedure relied on falling back to CLI or PowerShell with a long password because the portal already asked for MFA since Phase 1, that fallback is gone.
Guest administrators are the last group I always check: partners and vendors with an RBAC role on your subscriptions. For B2B guests the MFA has to be done either in your tenant or in their home tenant, with your cross-tenant access settings set to trust their MFA claims. If you don't trust inbound MFA, they need to register a method in your tenant, which is easier to arrange before their deployment fails.
Finding the affected accounts
Caller: AzureActivity
| where CategoryValue == "Policy"
| extend p = parse_json(Properties)
| extend policies = parse_json(tostring(p.policies))
| mv-expand policies
| where tostring(policies.policyDefinitionId) in~ (
"/providers/Microsoft.Authorization/policyDefinitions/4e6c27d5-a6ee-49cf-b2b4-d8fe90fa2b8b",
"/providers/Microsoft.Authorization/policyDefinitions/db4a9d17-db75-4f46-9fcb-9f9526604417")
| summarize Events = count(), LastSeen = max(TimeGenerated) by Caller, OperationNameValue
| sort by Events desc
797f4846-ba00-4fd7-ba43-dac1f8f63013), so filter on that resource in both the interactive and non-interactive user sign-in tables: union SigninLogs, AADNonInteractiveUserSignInLogs
| where TimeGenerated > ago(30d)
| where ResourceIdentity == "797f4846-ba00-4fd7-ba43-dac1f8f63013"
| where ResultType == "0"
| where AuthenticationRequirement == "singleFactorAuthentication"
| summarize SignIns = count(), Clients = make_set(AppDisplayName),
Protocols = make_set(AuthenticationProtocol), IPs = make_set(IPAddress, 20),
LastSeen = max(TimeGenerated) by UserPrincipalName, UserType
| sort by SignIns desc
AuthenticationRequirement reflects what was required for that sign-in, not what the user happened to do. In a tenant where Conditional Access already requires MFA for Azure management, what's left is mostly your exclusions, which is exactly the list you want. In a tenant without such a policy, almost everything shows as single factor, and the useful signals become ropc in the protocol column (that's a script with a password) and IP addresses that belong to build agents or automation servers. UserType gives you the guests for free. Moving automation to workload identities
Connect-AzAccount -Identity. Pipelines should use workload identity federation, so no secret exists at all: in GitHub Actions the azure/login action with OpenID Connect and a federated credential on an app registration or user-assigned managed identity, in Azure DevOps an Azure Resource Manager service connection with workload identity federation (existing secret-based connections that Azure DevOps created itself can be converted in place). For code that runs somewhere else, such as an on-premises scheduler, a service principal with a certificate is the fallback, preferably not a client secret: Connect-AzAccount -ServicePrincipal -ApplicationId $appId -Tenant $tenantId -CertificateThumbprint $thumbprint
The short version: run the sign-in query over the last 30 days, put every UPN it returns next to your Conditional Access exclusion list, and give each account an owner and a target identity type (managed identity, federated credential or certificate) before the next deployment that depends on it.
Sources
- Planning for mandatory multifactor authentication for Azure and other admin portals
- Azure blog: Azure mandatory multifactor authentication Phase 2 starting in October 2025
- MC1143999: Azure mandatory MFA Phase 2 postponement
- Tutorial: Apply MFA self-enforcement through Azure Policy
- Azure CLI troubleshooting: multifactor authentication
- Conditional Access: user exclusions in the MFA policy for all users
- Manage emergency access admin accounts
- Cross-tenant access settings for B2B collaboration
- Use GitHub Actions to connect to Azure with OpenID Connect
- Connect to Azure with an Azure Resource Manager service connection
- Conditional Access for workload identities