Azure mandatory MFA Phase 2: which identities break at the Resource Manager layer

Samantha Kloos-Kilkens
Aug 12, 2026 · Samantha Kloos-Kilkens

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.

Cars queuing at toll booths, seen from above Photo: Getty Images on Unsplash

What is enforced, and where

Phase 1 (from October 2024) covered the portals: the Azure portal, the Entra and Intune admin centers, and from February 2025 the Microsoft 365 admin center. Phase 2 moves the check to Azure Resource Manager itself. The Learn FAQ puts it plainly: enforcement is on the Resource Manager server side, so any request to 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

Because the check sits in Resource Manager and looks at the token, there's no Conditional Access policy to be excluded from. Entra will happily issue a token without an MFA claim if your own policies allow it, and Resource Manager then refuses the write. The FAQ is explicit that system enforcement applies to all user accounts, including break-glass accounts, administrators with active or eligible roles, and accounts that have user exclusions in your policies. If you configured exclusions in your MFA policy, "they no longer apply" for these operations. Stricter policies, such as a phishing-resistant authentication strength on Azure management, do stay in force.

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

User accounts used as service accounts are the big one. A 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

Start with the status. A Global Administrator can open the Phase 2 page at aka.ms/postponePhase2MFA; its banner shows whether and since when enforcement applies to your tenant. If enforcement hasn't reached your tenant yet, you can assign the two built-in definitions yourself in audit mode, following the Azure Policy tutorial. Don't look for results in the compliance view: these definitions evaluate requests, not resources, so compliance stays at zero resources and the audit events only appear in the Activity Log. The tutorial's sample query leaves out who did it, which is the part I actually need, so I add 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
The sign-in logs work whether or not you're enforced yet. CLI, PowerShell and the SDKs all request a token for the Windows Azure Service Management API (app ID 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
Read the result with some care. 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

The fix is the same everywhere, but the form depends on where the code runs. Anything hosted in Azure (a VM, Functions, an Automation runbook) should use a managed identity, which in PowerShell is 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
If you were using Conditional Access to restrict where the old service account could sign in from, you can carry that over with Conditional Access for workload identities, which needs a Workload Identities Premium license. It only covers single-tenant service principals (app registrations), though: managed identities can't be targeted by those policies. And since you're creating a new identity anyway, give it a role scoped to the resource groups it actually deploys to instead of copying the old account's Contributor on the whole subscription.

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.

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.