Configure Microsoft Entra ID Passkey (FIDO2) Registration Campaigns & Phishing-Resistant MFA via Microsoft Graph PowerShell

In late 2026, Microsoft began automatically transitioning tenants toward Passkeys (FIDO2)—including device-bound passkeys inside the Microsoft Authenticator app (iOS and Android), Windows Hello for Business, and hardware security keys (YubiKey / Feitian)—while nudging users away from phishable SMS, Voice, and push-fatigue MFA methods via Passkey Registration Campaigns.

Rather than letting Microsoft-managed defaults roll out unexpectedly to all users, enterprise identity administrators should take explicit control of the fido2 Authentication Method configuration and the registrationEnforcement campaign using the Microsoft Graph REST API / PowerShell SDK, and pair it with a Phishing-Resistant MFA Authentication Strength policy for privileged roles.


Architecture: Entra ID Passkey (FIDO2) Onboarding & Enforcement Flow

Microsoft Entra ID Passkey (FIDO2) Registration & Enforcement Pipeline
Step 1: Auth Method Policy
Enable FIDO2 / Passkeys
  • Endpoint: authenticationMethodConfigurations/Fido2
  • Set isAttestationEnforced
  • Allow Authenticator Passkeys via keyRestrictions
Step 2: User Nudge
Registration Campaign
  • Prompts users during interactive sign-in
  • Configurable snooze days & max snooze count
  • Seamless passkey creation in Authenticator
Step 3: Zero-Trust Gate
Phishing-Resistant Strength
  • Conditional Access Authentication Strength
  • Requires FIDO2, WHfB, or Entra CBA
  • Blocks Adversary-in-the-Middle (AiTM) proxies

Comparison: Microsoft Authenticator Push MFA vs. Passkey (FIDO2) in Authenticator

Security DimensionStandard Authenticator Number Matching (Push)Passkey (FIDO2) in Microsoft Authenticator / Security Key
Cryptographic ProtocolProprietary OATH / Push notificationW3C WebAuthn / FIDO2 CTAP2 public-key cryptography
Adversary-in-the-Middle (AiTM) ResistanceVulnerable if user types the number shown on a reverse-proxy phishing page (evilginx)100% Immune — browser binds cryptographic challenge to exact origin (login.microsoftonline.com)
Proximity VerificationNone (user can approve from anywhere unless GPS Conditional Access is set)Bluetooth (BLE) Cross-Device Proximity Check required when signing in on a PC
Entra Authentication Strength TierMultifactor authentication (Standard)Phishing-resistant MFA (Highest Tier)

Step 1: Audit Users Currently Lacking a Phishing-Resistant Passkey (FIDO2 / WHfB)

Using our UserAuthenticationMethod.Read.All permission in the LAB 365 tenant, we can audit every user's registered authentication methods to identify who has already registered a FIDO2 Passkey (#microsoft.graph.fido2AuthenticationMethod) or Windows Hello for Business (#microsoft.graph.windowsHelloForBusinessAuthenticationMethod), and who is still relying on phishable MFA:

POWERSHELL
# Connect to Microsoft Graph with Certificate-Based App-Only Auth
Connect-MgGraph `
    -ClientId "c841ae33-4093-4385-8a90-6a530761f9b9" `
    -TenantId "ab85c7a1-366d-44ba-acc6-924fa0950045" `
    -CertificateThumbprint "BEAC429DE404B46FF030811C0C9DE00DE701C027" `
    -NoWelcome

$Users = Get-MgUser -Filter "accountEnabled eq true and userType eq 'Member'" -All `
    -Property Id, DisplayName, UserPrincipalName

$PasskeyReport = foreach ($User in $Users) {
    $Methods = Get-MgUserAuthenticationMethod -UserId $User.Id
    $ODataTypes = $Methods | ForEach-Object { $_.AdditionalProperties["@odata.type"] }

    $HasFido2 = $ODataTypes -contains "#microsoft.graph.fido2AuthenticationMethod"
    $HasWhfb  = $ODataTypes -contains "#microsoft.graph.windowsHelloForBusinessAuthenticationMethod"

    [PSCustomObject]@{
        DisplayName         = $User.DisplayName
        UserPrincipalName   = $User.UserPrincipalName
        HasPasskeyFido2     = $HasFido2
        HasWindowsHello     = $HasWhfb
        PhishingResistant   = ($HasFido2 -or $HasWhfb)
        RegisteredMethodCnt = $Methods.Count
    }
}

$PasskeyReport | Format-Table -AutoSize

Step 2: Enable FIDO2 Passkeys (Including Authenticator App AAGUIDs) via Microsoft Graph

To allow users to register both hardware FIDO2 keys (YubiKey) and Passkeys in Microsoft Authenticator (iOS AAGUID de1e552d-db1d-4423-a619-566b625cdc84 and Android AAGUID 90a3ccdf-635c-4729-a248-9b709135078f), update the Fido2 configuration under authenticationMethodsPolicy:

POWERSHELL
Connect-MgGraph -Scopes "Policy.ReadWrite.AuthenticationMethod" -NoWelcome

$Fido2Config = @{
    "@odata.type"               = "#microsoft.graph.fido2AuthenticationMethodConfiguration"
    id                          = "Fido2"
    state                       = "enabled"
    isSelfServiceRegistrationAllowed = $true
    isAttestationEnforced       = $false
    keyRestrictions             = @{
        isEnforced      = $false
        enforcementType = "allow"
        aaGuids         = @()
    }
    includeTargets              = @(
        @{
            targetType             = "group"
            id                     = "all_users"
            isRegistrationRequired = $false
        }
    )
}

Invoke-MgGraphRequest `
    -Method PATCH `
    -Uri "https://graph.microsoft.com/v1.0/policies/authenticationMethodsPolicy/authenticationMethodConfigurations/Fido2" `
    -Body ($Fido2Config | ConvertTo-Json -Depth 6)
Tip on isAttestationEnforced: If you want to restrict users exclusively to Microsoft Authenticator Passkeys and enterprise-approved YubiKeys, set isAttestationEnforced = $true, keyRestrictions.isEnforced = $true, enforcementType = "allow", and include the Microsoft Authenticator iOS (de1e552d-db1d-4423-a619-566b625cdc84) and Android (90a3ccdf-635c-4729-a248-9b709135078f) AAGUIDs in aaGuids.

Step 3: Require Phishing-Resistant MFA for Privileged Admins via Conditional Access

Once your administrators have registered their FIDO2 Passkey, lock down privileged roles (Global Administrator, Exchange Administrator, Security Administrator) using the built-in Phishing-resistant MFA Authentication Strength (00000000-0000-0000-0000-000000000004):

POWERSHELL
Connect-MgGraph -Scopes "Policy.ReadWrite.ConditionalAccess" -NoWelcome

$CaPolicy = @{
    displayName = "CA01 - Require Phishing-Resistant Passkey MFA for Admins"
    state       = "enabledForReportingButNotEnforced" # Switch to 'enabled' after pilot verification
    conditions  = @{
        applications = @{
            includeApplications = @("All")
        }
        users = @{
            includeRoles = @(
                "62e90394-69f5-4237-9190-012177145e10", # Global Administrator
                "29232cdf-9323-42fd-ade2-1d097af3e4de", # Exchange Administrator
                "194ae4cb-b126-40b2-bd5b-6091b380977d"  # Security Administrator
            )
        }
    }
    grantControls = @{
        operator               = "OR"
        authenticationStrength = @{
            id = "00000000-0000-0000-0000-000000000004" # Built-in Phishing-Resistant MFA
        }
    }
}

New-MgIdentityConditionalAccessPolicy -BodyParameter $CaPolicy