Phishing-Resistant MFA Setup: Block AiTM in 12 Steps [2026]

A password stopped protecting accounts years ago. By 2026, a six-digit code from an authenticator app or a push notification isn’t holding the line either. Adversary-in-the-middle (AiTM) phishing kits now sit between a user and a real login page, relaying every keystroke and every one-time code in real time, then walking off with the session cookie the moment authentication finishes. A separate technique, device-code phishing, skips credential theft altogether and tricks a victim into authorizing an attacker’s session directly. Security researchers tracking 2026 phishing trends describe AiTM reverse-proxy kits as having moved “from elite threat-actor capability into commodity tooling,” which means the barrier to running one of these campaigns has mostly disappeared.

This tutorial walks through building phishing-resistant MFA end to end: auditing what you have now, rolling out FIDO2 security keys and passkeys, writing Conditional Access policies that actually block AiTM and device-code abuse, testing the setup against a simulated attack, and standing up monitoring that catches what slips through. The primary keyword here, phishing-resistant MFA, pulls roughly 1,000 monthly US searches according to DataForSEO data pulled in August 2026, and the topic sits squarely in identity security, one of the fastest-moving corners of the cybersecurity cluster this year.

Google · Preferred Sources

Don't miss new tech stories on Google

Add Tech Insider once in the Google app and our stories appear in your news suggestions.

Add Now

Why Standard MFA No Longer Stops Account Takeovers

Multi-factor authentication was supposed to be the thing that made phishing irrelevant. For a while it worked, because most phishing kits could only steal a password, not a live session. That changed once reverse-proxy phishing kits matured. An AiTM kit hosts a page that looks identical to the real login screen, but every request the victim makes actually passes through to the legitimate identity provider and back. The victim enters a password, gets prompted for a push approval or a TOTP code, approves it, and the kit captures the resulting session cookie before the victim ever notices anything wrong. From that point, the attacker has a fully authenticated session and doesn’t need the password or the second factor again.

Okta’s identity security team explains the underlying weakness plainly: for an MFA mechanism to resist AiTM attacks, “the authenticator used should be cryptographically bound to the domain and be able to distinguish between the real domain and the fake domain generated by the attacker.” SMS codes, TOTP apps, and push notifications have no idea what domain they’re being used on. A code is a code. A push approval is a push approval. None of them can tell the difference between login.microsoftonline.com and a look-alike proxy domain sitting one hop away.

Device-code phishing works differently but arrives at the same outcome. OAuth 2.0’s device authorization grant exists for a legitimate reason: it lets a device with no keyboard, like a smart TV or a conference room console, authenticate by displaying a short code that a user types into a browser on a different device. Attackers abuse this by generating a real device code from a target service, then sending it to a victim disguised as a meeting invite, an IT verification step, or a Teams message. The victim types the code into the real Microsoft or Google login page, believing they’re joining a call or verifying their identity, and unknowingly grants the attacker’s session full access. No proxy, no fake domain, no password theft. It’s authentication abuse, not credential theft, and that’s exactly why it slips past defenses built to catch phishing pages.

The fix for both techniques is the same category of control: authentication methods that are cryptographically bound to the origin they were registered against. FIDO2 security keys and passkeys check the domain before they’ll release a signed assertion, which means a proxy sitting on a look-alike domain simply gets refused. Government guidance backs this up directly. The Government of Canada’s Cyber Centre states that “phishing-resistant MFA continues to prevent AitM campaigns, whether from traditional kits or proxy-based AitM phishing kits,” and recommends pairing it with a second layer, noting that “both phishing-resistant MFA and registered device CAPs break the authentication flow when there is an AitM phishing kit in the middle of the connection.”

Prerequisites: Accounts, Tools, and Versions You’ll Need

This walkthrough uses Microsoft Entra ID (formerly Azure AD) as the primary identity provider since it covers the largest share of enterprise seats and has the most mature phishing-resistant MFA tooling, but the same principles apply to Okta, Google Workspace, and other identity providers with adjustments to the console screens. Before starting, confirm you have the following in place.

  • An Entra ID tenant with Entra ID P1 or P2 licensing (Conditional Access and authentication strengths require P1 at minimum; risk-based policies and Continuous Access Evaluation benefit from P2)
  • Global Administrator or Conditional Access Administrator role for setup, plus a separate Authentication Policy Administrator account for day-to-day management
  • Microsoft Graph PowerShell SDK version 2.25 or later (Install-Module Microsoft.Graph -Scope CurrentUser)
  • At least two FIDO2 hardware security keys per pilot user (one primary, one backup) — YubiKey 5 series with firmware 5.7 or later, or an equivalent FIDO2-certified key
  • A modern browser: Chrome 120+, Edge 120+, or Safari 17+, all of which support WebAuthn and platform passkeys natively
  • Windows 11 23H2 or later, or macOS Sonoma 14.4 or later, for platform passkey support via Windows Hello or Touch ID
  • Access to Entra ID sign-in logs and, ideally, a SIEM (Microsoft Sentinel, Splunk, or similar) for the monitoring steps later in this guide
  • Python 3.11+ if you want to run the optional detection script in the troubleshooting section

None of this requires a security operations center or a six-figure budget. A small business running Microsoft 365 Business Premium already has Entra ID P1 bundled in, and a handful of $25-per-key hardware tokens covers the first wave of admin accounts. The bigger investment is time: plan on a phased rollout over four to eight weeks for anything beyond a five-person team.

Step 1: Audit Your Current MFA Methods and Exposure

You can’t fix what you can’t see. Start by pulling a report of every registered authentication method across the tenant, broken down by method type. This tells you how many accounts are still relying on SMS, voice calls, or app-based push, all of which are vulnerable to AiTM relay.

# Connect to Microsoft Graph with the required scopes
Connect-MgGraph -Scopes "Reports.Read.All","UserAuthenticationMethod.Read.All"

# Pull authentication method registration details for every user
$report = Get-MgReportAuthenticationMethodUserRegistrationDetail -All

# Break down usage by method type
$report | Select-Object -ExpandProperty MethodsRegistered |
  Group-Object | Sort-Object Count -Descending |
  Format-Table Name, Count -AutoSize

# Flag admins who have NOT registered a FIDO2 key or passkey
$report | Where-Object {
  $_.IsAdmin -eq $true -and
  $_.MethodsRegistered -notcontains "fido2SecurityKey" -and
  $_.MethodsRegistered -notcontains "passKeyDeviceBound"
} | Select-Object UserPrincipalName, MethodsRegistered

Run this before you touch a single policy. In most mid-size organizations, the first pass turns up privileged accounts (Global Admins, finance approvers, help desk staff with password-reset rights) still sitting on SMS or an authenticator app with no phishing-resistant fallback. Those are your first migration targets, not your general user base.

Step 2: Enable Security Defaults and a Baseline Conditional Access Policy

If the tenant has no Conditional Access policies at all, start with a baseline before layering in phishing-resistant requirements. Go to Entra admin center, Protection, Conditional Access, and create a policy named “Baseline — Require MFA for All Users” that targets all users, all cloud apps, and requires MFA as a grant control. Set it to Report-only first so you can watch its impact in the sign-in logs for 48 to 72 hours before enforcing it. This step matters because it’s the safety net every later, more restrictive policy builds on top of. Skipping it and jumping straight to phishing-resistant enforcement is one of the fastest ways to lock yourself out of your own tenant, which is covered in the pitfalls section below.

Step 3: Roll Out FIDO2 Security Keys and Passkeys

FIDO2 and passkeys are the actual fix, not a nice-to-have layered on top. The UK’s National Cyber Security Centre puts it simply: “The key reason for this is that passkeys are resistant to phishing, as they can’t be intercepted, reused or stolen like passwords.” The same cryptographic binding applies to hardware security keys, which are effectively passkeys stored on dedicated hardware instead of a device’s secure enclave, following the FIDO Alliance’s open passkey standard.

Okta describes the practical effect of that domain check this way: “the mechanism can immediately stop the attack so that the attacker cannot capture the credentials or session cookie and replay them.” In the Entra admin center, go to Protection, Authentication methods, Policies, and enable both FIDO2 Security Key and Passkey (device-bound). For FIDO2, you can optionally restrict allowed AAGUIDs to specific vendors if your procurement only supports a certain key model. Then enable self-service registration so pilot users can enroll their own keys from My Sign-Ins without opening a help desk ticket.

# Enable FIDO2 as an allowed authentication method via Graph API
$params = @{
  "@odata.type" = "#microsoft.graph.fido2AuthenticationMethodConfiguration"
  state = "enabled"
  isSelfServiceRegistrationAllowed = $true
  isAttestationEnforced = $true
  keyRestrictions = @{
    isEnforced = $false
    enforcementType = "allow"
    aaGuids = @()
  }
}

Update-MgPolicyAuthenticationMethodPolicyAuthenticationMethodConfiguration `
  -AuthenticationMethodConfigurationId "Fido2" `
  -BodyParameter $params

For users on managed Windows or Mac devices, enable platform passkeys through Windows Hello for Business or Touch ID as a lower-friction option than a physical key. Reserve hardware keys for shared devices, break-glass accounts, and anyone who moves between machines regularly, since a platform passkey is bound to a single device by default.

Step 4: Build Authentication Strength and Conditional Access Policies

Authentication strengths let you define exactly which combination of methods satisfies a policy, rather than accepting “any MFA” as good enough. Entra ID ships a built-in “Phishing-resistant MFA” authentication strength that only accepts FIDO2, Windows Hello for Business, passkeys, or certificate-based authentication. Nothing on that list can be relayed by an AiTM proxy.

MFA MethodResists AiTM RelayResists Device-Code PhishingTypical Setup TimeApprox. Cost
SMS one-time codeNoNo1 minFree (carrier fees apply)
Voice call codeNoNo1 minFree (carrier fees apply)
TOTP authenticator appNoNo3 minFree
Push notification approvalNoNo3 minFree
Number matching pushPartialNo3 minFree
Passkey (platform, device-bound)YesYes2 minFree (built into OS)
FIDO2 hardware security keyYesYes5 min$25–$70 per key
Certificate-based authenticationYesYes15–30 min (PKI setup)Varies (existing PKI)

Create the Conditional Access policy that enforces this strength for your highest-risk group first. Name it something explicit like “Require Phishing-Resistant MFA — Admins” so anyone auditing the tenant later understands its purpose at a glance.

# Create a Conditional Access policy requiring the built-in
# phishing-resistant MFA authentication strength for admin roles
$policy = @{
  displayName = "Require Phishing-Resistant MFA - Admins"
  state = "enabledForReportingButNotEnforced"
  conditions = @{
    users = @{
      includeRoles = @(
        "62e90394-69f5-4237-9190-012177145e10", # Global Administrator
        "194ae4cb-b126-40b2-bd5b-6091b380977d"  # Security Administrator
      )
    }
    applications = @{ includeApplications = @("All") }
  }
  grantControls = @{
    operator = "AND"
    authenticationStrength = @{
      id = "00000000-0000-0000-0000-000000000004" # Phishing-resistant MFA
    }
  }
}

New-MgIdentityConditionalAccessPolicy -BodyParameter $policy

Note the state is set to enabledForReportingButNotEnforced. Watch the report-only results in the Conditional Access Insights workbook for at least a week before flipping it to enabled. This catches admins who haven’t registered a phishing-resistant method yet, before they get locked out.

Step 5: Block Legacy Authentication and Device-Code Flow Abuse

Phishing-resistant MFA doesn’t help if attackers can route around it entirely through legacy protocols like POP, IMAP, or older Exchange ActiveSync connections that don’t support modern authentication. Create a Conditional Access policy that blocks legacy authentication tenant-wide; nearly every phishing-resistant deployment guide treats this as a non-negotiable companion policy.

Device-code phishing needs its own, separate control, because the device authorization grant is a distinct OAuth flow that a “block legacy auth” policy won’t touch. Microsoft’s own documentation on the OAuth 2.0 device code flow confirms this is a first-class, supported authentication path, which is exactly why attackers exploit it: it’s real, sanctioned infrastructure, not a bug. Restrict which apps are allowed to use the device code flow, and require phishing-resistant MFA even when that flow is used, by scoping a Conditional Access policy specifically to the client flows attackers actually rely on.

# Conditional Access policy targeting device-code and legacy auth flows
$deviceCodePolicy = @{
  displayName = "Block Legacy Auth and Restrict Device Code Flow"
  state = "enabled"
  conditions = @{
    users = @{ includeUsers = @("All") }
    applications = @{ includeApplications = @("All") }
    clientAppTypes = @("exchangeActiveSync", "other")
  }
  grantControls = @{
    operator = "OR"
    builtInControls = @("block")
  }
}

New-MgIdentityConditionalAccessPolicy -BodyParameter $deviceCodePolicy

Combine this with a hard organizational policy: device codes should only ever be entered on a screen the user personally initiated, such as signing into a smart TV app they just opened. Any device code arriving via chat, email, or a phone call from “IT” is a red flag, full stop. Training catches what the policy engine structurally can’t, since the device code flow is technically legitimate traffic.

Step 6: Enforce Token Protection and Sign-In Frequency

Even with phishing-resistant MFA in place, a stolen refresh token from an already-compromised device can still be replayed elsewhere unless it’s bound to the device that requested it. Entra ID’s token protection feature, found in Conditional Access session controls, cryptographically ties a sign-in session token to the specific device, so a copied token fails validation on any other machine. Pair this with a sign-in frequency control that forces re-authentication every 4 to 8 hours for sensitive apps, which shrinks the window an attacker has if a session is somehow captured despite the other controls.

Step 7: Protect Admins and Privileged Roles First

Rolling out phishing-resistant MFA to 5,000 employees at once is how projects stall. Sequence the rollout by blast radius instead. Global Administrators, Security Administrators, Privileged Role Administrators, and anyone with standing access to finance systems or customer data goes first, typically within the first one to two weeks. These accounts represent the smallest population and the highest impact if compromised, which makes them the fastest return on the time you’ll spend troubleshooting enrollment issues.

Use Privileged Identity Management (PIM), if licensed, to require phishing-resistant MFA specifically at role activation time, not just at initial sign-in. This closes a gap where an admin authenticates with a weaker method in the morning and later elevates to Global Administrator without a fresh, stronger check.

Step 8: Turn On Continuous Access Evaluation

Continuous Access Evaluation (CAE) shortens the gap between a risk signal firing and a session getting revoked, from the standard token lifetime of up to 24 hours down to near real time for supported events like a user being disabled, a password reset, or a location the network flags as high-risk. Enable it under Entra ID, Security, Conditional Access, Continuous access evaluation settings, and confirm the setting is applied at the tenant level rather than per-app, since partial CAE coverage leaves the same AiTM session-replay window open for apps that aren’t covered.

Step 9: Simulate an AiTM Phishing Attack Against Your Own Tenant

Don’t take the policy’s word for it. Test it. Attack simulation training in Microsoft Defender for Office 365, or a third-party platform paired with a reverse proxy tool in an isolated lab, lets you run a controlled AiTM phishing campaign against a small group of consenting test accounts. The goal isn’t to catch anyone off guard; it’s to confirm that accounts protected by the phishing-resistant Conditional Access policy actually reject the relayed authentication attempt, while accounts still on legacy MFA get flagged as at-risk in the report.

# Launch a Defender for Office 365 attack simulation via Graph API
# (requires AttackSimulation.ReadWrite.All scope)
Connect-MgGraph -Scopes "AttackSimulation.ReadWrite.All"

$simulation = @{
  displayName = "AiTM-Credential-Harvest-Q3-2026"
  attackTechnique = "credentialHarvesting"
  landingPage = @{
    landingPageStyle = "credentialHarvest"
  }
  payload = @{
    payloadType = "email"
  }
}

New-MgSecurityAttackSimulationSimulation -BodyParameter $simulation

# After the simulation runs, pull results segmented by MFA method
Get-MgSecurityAttackSimulationSimulationReportSimulationUserCoverage `
  -SimulationId $simulation.Id

Run this quarterly, not once. Phishing kits update their evasion techniques constantly, and a policy that blocked a simulation in January isn’t guaranteed to catch a kit’s September variant without a fresh test.

Step 10: Monitor Sign-In Logs for AiTM and Device-Code Indicators

Policies reduce risk; they don’t eliminate the need to watch for what gets through. Sign-in logs carry specific indicators of AiTM and device-code abuse if you know what to query for: sign-ins from a new IP within minutes of a successful MFA prompt, token issuance events without a corresponding interactive sign-in, and device-code grants from applications your organization doesn’t normally use. A Kusto Query Language (KQL) rule in Microsoft Sentinel can catch most of this automatically.

// KQL: flag device-code sign-ins followed by high-risk activity
// within 30 minutes, a common AiTM/device-code phishing pattern
SigninLogs
| where AuthenticationProtocol == "deviceCode"
| project TimeGenerated, UserPrincipalName, IPAddress, AppDisplayName, Id
| join kind=inner (
    AADRiskyUsers
    | where RiskLevel in ("high", "medium")
    | project UserPrincipalName, RiskLevel, RiskLastUpdatedDateTime
) on UserPrincipalName
| where RiskLastUpdatedDateTime between (
    TimeGenerated .. (TimeGenerated + 30m)
  )
| project TimeGenerated, UserPrincipalName, IPAddress, AppDisplayName, RiskLevel

Route the output of this query into an automated playbook that disables the affected account and revokes its refresh tokens immediately, rather than waiting for a human to review an alert queue during business hours. AiTM sessions get used within minutes of capture, so detection speed matters more than detection accuracy at this stage.

Step 11: Roll Out Company-Wide With a Phased Migration Plan

Once admins and privileged roles are covered and the simulation results look clean, expand in waves: IT and security staff next, then finance and HR (common targets for business email compromise), then engineering and general staff, then contractors and service accounts last. Give each wave a two-week enrollment window with a hard deadline, backed by an email and a help desk walkthrough, before enforcement flips on for that group. A phased rollout also gives you room to catch edge cases, like shared kiosk accounts or shift workers without a personal device, before they become a company-wide fire drill.

Step 12: Build Break-Glass Accounts and an Incident Response Playbook

Every phishing-resistant MFA rollout needs at least two break-glass (emergency access) accounts excluded from the enforcement policies, with credentials stored offline in a physical safe, not in the same password manager everyone else uses. These accounts exist for the scenario where a Conditional Access misconfiguration locks out every admin simultaneously. Monitor sign-ins to these accounts specifically, since any activity on them outside of a declared emergency is itself a critical alert.

# Create a break-glass account excluded from Conditional Access
$breakGlassUser = @{
  accountEnabled = $true
  displayName = "BreakGlass-Emergency-01"
  userPrincipalName = "[email protected]"
  passwordProfile = @{
    forceChangePasswordNextSignIn = $false
    password = ""
  }
  mailNickname = "breakglass01"
}

New-MgUser -BodyParameter $breakGlassUser

# Exclude the account explicitly in every Conditional Access policy
# under conditions.users.excludeUsers, then verify with:
Get-MgIdentityConditionalAccessPolicy | ForEach-Object {
  [PSCustomObject]@{
    Policy = $_.DisplayName
    ExcludesBreakGlass = $_.Conditions.Users.ExcludeUsers -contains $breakGlassUser.Id
  }
}

Document the incident response playbook alongside the account: who is authorized to use it, under what conditions, and the mandatory post-use review. An unmonitored break-glass account defeats the purpose of everything built in the previous eleven steps.

Common Pitfalls When Deploying Phishing-Resistant MFA

Most failed rollouts trace back to one of a handful of repeatable mistakes. Watch for these specifically.

  • Enforcing before testing in report-only mode. Flipping a Conditional Access policy straight to enabled without a report-only period is the single most common cause of self-inflicted lockouts, especially for admin accounts that haven’t registered a hardware key yet.
  • Forgetting shared and service accounts. Meeting-room displays, kiosk terminals, and non-interactive service accounts can’t register a FIDO2 key or approve a passkey prompt. These need explicit, narrowly scoped exceptions, not a blanket exclusion from the policy.
  • Treating number-matching push as phishing-resistant. Number matching reduces MFA fatigue attacks, where a user gets bombarded with push requests until they approve one by mistake, but it does nothing against a live AiTM proxy relaying the exact number to display. It’s an improvement over plain push, not a replacement for FIDO2 or passkeys.
  • Skipping the device-code flow policy entirely. Teams focus so heavily on blocking legacy authentication that they overlook device-code phishing, which uses a completely different, modern OAuth flow that a legacy-auth block doesn’t touch.
  • No backup authentication method for lost or damaged keys. Every user needs a registered second FIDO2 key or a temporary access pass workflow, or a single lost YubiKey turns into a help desk emergency and, worse, a tempting excuse to “just this once” fall back to SMS.

Troubleshooting Phishing-Resistant MFA: 8 Common Issues

These are the issues that generate the most help desk tickets during a rollout, along with the fix for each.

SymptomLikely CauseFix
“This browser or device doesn’t support your organization’s security policy”Browser doesn’t support WebAuthn or is outdatedUpdate to Chrome 120+, Edge 120+, or Safari 17+; avoid legacy Internet Explorer mode
FIDO2 key not detected during registrationUSB port issue, missing driver, or NFC not enabled on mobileTry a different USB port, enable NFC in device settings, or use the manufacturer’s diagnostic tool
User locked out after Conditional Access policy enforcedPolicy enforced before user registered a phishing-resistant methodUse a break-glass account to disable the policy temporarily, register the method, then re-enable
Passkey doesn’t sync across devicesDevice-bound passkey used instead of a synced (cloud) passkeyRegister a synced passkey through the platform’s password manager (iCloud Keychain, Google Password Manager) for multi-device use
Device-code sign-in blocked unexpectedly for a legitimate smart-TV appOverly broad device-code restriction policyScope the policy to specific high-risk app IDs rather than blocking the device-code flow tenant-wide
Attack simulation shows accounts bypassing phishing-resistant policyPolicy targets a group the user isn’t actually a member ofVerify group membership and policy assignment scope, then re-run the simulation
Token protection blocking legitimate sign-ins from a new laptopSession token bound to the old device wasn’t refreshed after a hardware swapForce a fresh interactive sign-in on the new device before relying on token protection
CAE not revoking access immediately after account disableCAE only partially enabled or app doesn’t support CAE eventsConfirm tenant-wide CAE is enabled and check the app’s CAE support status in the Enterprise Applications list

Advanced Tips for Hardening Beyond the Basics

Once the core 12 steps are stable, a few additional controls close remaining gaps. First, enable named locations and require phishing-resistant MFA specifically for sign-ins from outside expected corporate IP ranges or countries, even for users who already have a registered FIDO2 key, since this catches the rare case of a physically stolen key combined with a known PIN. Second, pair Conditional Access with a compliant-device requirement so that even a correctly authenticated session gets rejected if it originates from an unmanaged, unpatched machine. Third, review authentication method registration reports monthly rather than at rollout time only, since new hires and returning employees are the most common source of policy drift back toward weaker methods.

Finally, consider certificate-based authentication for service-to-service and machine identities that can’t use a physical key at all. It provides the same cryptographic domain binding as FIDO2 without requiring a human to tap a token, which makes it the right fit for automated pipelines, APIs, and infrastructure accounts that still need protection against credential replay.

Complete Working Project: Policy Bundle and Detection Script

Combine the pieces from this tutorial into a single deployable bundle: an authentication strength definition, a Conditional Access policy targeting admins first, a device-code restriction policy, and a Sentinel detection rule. Save the following as a PowerShell script and run it section by section during a scheduled maintenance window, checking report-only results after each stage before moving to the next.

# phishing-resistant-mfa-rollout.ps1
# A complete, ordered rollout script. Run interactively, section by section.

Connect-MgGraph -Scopes "Policy.ReadWrite.ConditionalAccess",`
  "Policy.ReadWrite.AuthenticationMethod","User.ReadWrite.All",`
  "AttackSimulation.ReadWrite.All"

# 1. Enable FIDO2 and passkeys tenant-wide
Update-MgPolicyAuthenticationMethodPolicyAuthenticationMethodConfiguration `
  -AuthenticationMethodConfigurationId "Fido2" `
  -BodyParameter @{ state = "enabled"; isSelfServiceRegistrationAllowed = $true }

# 2. Create the admin-scoped phishing-resistant policy (report-only)
New-MgIdentityConditionalAccessPolicy -BodyParameter @{
  displayName = "Phase1-PhishingResistant-Admins"
  state = "enabledForReportingButNotEnforced"
  conditions = @{
    users = @{ includeRoles = @("62e90394-69f5-4237-9190-012177145e10") }
    applications = @{ includeApplications = @("All") }
  }
  grantControls = @{
    authenticationStrength = @{ id = "00000000-0000-0000-0000-000000000004" }
  }
}

# 3. Block legacy authentication tenant-wide
New-MgIdentityConditionalAccessPolicy -BodyParameter @{
  displayName = "Phase1-BlockLegacyAuth"
  state = "enabled"
  conditions = @{
    users = @{ includeUsers = @("All") }
    applications = @{ includeApplications = @("All") }
    clientAppTypes = @("exchangeActiveSync", "other")
  }
  grantControls = @{ builtInControls = @("block") }
}

# 4. Confirm report-only impact before enforcing (run after 7 days)
Get-MgIdentityConditionalAccessPolicy |
  Where-Object { $_.DisplayName -like "Phase1-*" } |
  Select-Object DisplayName, State

Write-Host "Review report-only sign-in impact in the Conditional Access Insights workbook before enforcing."

This script deliberately stops short of auto-enforcing anything. Every phase requires a human to review report-only data and manually flip the state, which is intentional friction meant to prevent exactly the kind of lockout described in the pitfalls section above.

Applying This Beyond Microsoft Entra ID

The 12 steps above use Entra ID as the reference implementation because it currently has the deepest phishing-resistant tooling and the largest installed base, but the underlying strategy (audit, register FIDO2/passkeys, enforce via policy, restrict device-code flows, monitor, and phase the rollout) applies regardless of which identity provider issues your sessions. Here’s how the same moves translate to the two other platforms most readers are likely running.

Okta

In Okta, the equivalent of an authentication strength lives under Security, Authenticators, where you define a custom authenticator enrollment policy that lists FIDO2 (WebAuthn) and Okta FastPass as the only accepted factors for a given app or group. Okta Sign-On Policies then take the place of Conditional Access, scoped the same way: admins first, then IT and security, then the general population. Okta FastPass itself is phishing-resistant by design since it performs the same origin-binding check as WebAuthn before completing a sign-in. For device-code style abuse, review any OAuth 2.0 device authorization grant integrations under Applications and restrict which client apps are permitted to request that grant type, mirroring the Conditional Access policy built in Step 5.

Google Workspace

Google Workspace handles this through security key enforcement under Admin Console, Security, Authentication, 2-Step Verification, where an administrator can require security keys specifically for members of an organizational unit rather than the whole domain. This gives you the same admins-first sequencing without needing a separate policy engine. Google’s Advanced Protection Program, originally built for high-risk users like journalists and campaign staff, bundles security-key enforcement with additional account-recovery restrictions and is worth evaluating for your Global Administrator equivalents (Super Admins) even outside its original target audience. Google does not expose a device-code flow in the same way Entra ID does for most consumer-facing OAuth integrations, but any custom-built internal tools using the device authorization grant should still be audited and restricted the same way.

Ping Identity, Duo, and Other SAML/OIDC Providers

Most enterprise identity providers built on SAML or OIDC, including Ping Identity and Cisco Duo, support WebAuthn as an authenticator type and expose some form of adaptive or risk-based policy engine comparable to Conditional Access. The exact menu labels differ, but the checklist to work through stays identical: confirm WebAuthn/FIDO2 is enabled as an authenticator, build a policy that requires it specifically (not just “any second factor”) for privileged accounts, disable or tightly scope any OAuth device-code equivalents, and pilot with admins before expanding. If your identity provider doesn’t support WebAuthn natively yet, treat that as a blocking gap worth escalating, since every other control in this tutorial depends on having at least one domain-bound authenticator available to enforce.

Measuring Success After Rollout

Track three numbers monthly once the rollout stabilizes: the percentage of active users with a registered phishing-resistant method, the percentage of sign-ins actually satisfying the phishing-resistant authentication strength (registration doesn’t guarantee usage if a weaker fallback method still exists), and the count of AiTM or device-code indicators caught by the Sentinel detection rule. A mature deployment should show phishing-resistant coverage above 95% for privileged roles within the first quarter and steadily climbing for the general population as the phased rollout completes. If usage lags well behind registration numbers, check for legacy Conditional Access policies that still accept weaker methods as a fallback, since a dangling exception undermines the entire project.

Frequently Asked Questions

Is phishing-resistant MFA the same thing as FIDO2?
Not exactly. FIDO2 is one implementation of phishing-resistant MFA, alongside passkeys and certificate-based authentication. All three share the same core property: cryptographic binding to the domain that requested authentication, which is what defeats AiTM relay.

Can attackers bypass FIDO2 or passkeys at all?
Not through AiTM relay or device-code phishing, since both rely on the domain-binding check that FIDO2 and passkeys enforce. Physical theft of an unlocked key combined with a known PIN remains a theoretical risk, which is why pairing phishing-resistant MFA with named-location and compliant-device policies adds meaningful defense in depth.

Do I need Entra ID P2 to do this, or does P1 cover it?
Conditional Access and authentication strengths, including the built-in phishing-resistant MFA strength, are available with Entra ID P1. Risk-based Conditional Access and some Continuous Access Evaluation scenarios require P2.

What happens if an employee loses their only FIDO2 key?
This is why every user needs a registered backup method during enrollment, either a second key or a Temporary Access Pass issued by an administrator for re-registration. Without a backup path, a lost key becomes a full lockout.

Does phishing-resistant MFA stop device-code phishing specifically?
It significantly reduces the impact, since the resulting session still needs to satisfy the phishing-resistant Conditional Access policy for sensitive actions, but the device-code grant itself needs a separate, dedicated policy restricting which apps can use that flow at all. Treat the two as complementary controls, not one fixing the other.

How long does a full company rollout typically take?
For organizations under 500 users, four to six weeks from admin rollout through full company enforcement is realistic. Larger organizations with complex app ecosystems and shared-device populations often need eight to twelve weeks to account for exceptions and legacy application compatibility testing.

Can I use phishing-resistant MFA with non-Microsoft identity providers?
Yes. Okta, Google Workspace, Ping Identity, and most modern identity providers support FIDO2 and passkeys through the same WebAuthn standard. The Conditional Access policy syntax differs by vendor, but the underlying cryptographic protection and rollout sequencing described in this tutorial carry over directly.

Is number-matching push notification good enough if I can’t deploy hardware keys?
It’s a meaningful improvement over plain push approval and should be enabled regardless, but it is not phishing-resistant. A live AiTM proxy can relay the matching number to the victim in real time. Treat number matching as a stopgap while you plan the migration to FIDO2 or passkeys, not as an end state.

Related Coverage

Sofia Lindström

Sofia Lindström

Editor-in-Chief

Sofia Lindström is the Editor-in-Chief at Tech Insider, where she leads editorial strategy and oversees coverage across AI, cybersecurity, and enterprise technology. With over a decade in Swedish tech journalism, she previously served as technology editor at Dagens Industri and covered the Nordic startup ecosystem for Breakit. Sofia holds an MSc in Media Technology from KTH Royal Institute of Technology and is a frequent speaker at Web Summit and Slush. She is passionate about making complex technology accessible to business leaders.

View all articles