Identity Azure

Rolling Out FIDO2 Passwordless Authentication in Entra ID: Security Keys, Passkeys, and Windows Hello for Business

Passwordless is the only credible answer to AiTM phishing kits that defeat every push-and-OTP MFA flavor you have deployed. The goal of this playbook is concrete: make a phishing-resistant credential the primary sign-in for your workforce, with passwords demoted to a legacy fallback you actively measure and shrink. We wire up FIDO2 security keys, device-bound and synced passkeys, and Windows Hello for Business (WHfB) cloud Kerberos trust across a hybrid Entra tenant, then gate sensitive apps behind Conditional Access authentication strengths.

Scope: a hybrid estate (Entra ID plus on-prem AD synced by Entra Connect). It works cloud-only too, you just skip the Kerberos-object steps in Section 3.

1. The passwordless landscape: pick the right credential per persona

Get the taxonomy right first, because the four options have materially different security postures and you assign them to different populations.

Credential Where the private key lives Attestation Phishing-resistant Best for
FIDO2 security key Dedicated hardware (YubiKey, Feitian, etc.), never leaves Yes (vendor AAGUID + cert) Yes Admins, shared workstations, BYOD-to-corp, no-TPM machines
Device-bound passkey (Authenticator / platform) Single phone or TPM, never leaves Yes (Authenticator), platform-dependent Yes Frontline and mobile-first staff
Synced passkey (iCloud Keychain, Google PM) HSM-wrapped, then synced to the provider cloud No (sync providers don’t attest) Yes Low-privilege users, contractor convenience
Windows Hello for Business TPM on the PC, gesture-unlocked n/a (key trust to TPM) Yes The daily driver for managed Windows endpoints

Two principal-level calls fall out of this table:

2. Enable the Passkey (FIDO2) authentication method with profiles and AAGUID allow-lists

As of the March 2026 GA, the Passkey (FIDO2) method moved from a single tenant-wide blob to passkey profiles: named, group-scoped rule sets for attestation, passkey type, and AAGUID restrictions. This is a breaking change, existing global settings migrate into a Default passkey profile on opt-in, and you cannot opt back out. Plan the model before you click the banner.

Hard limits: the Passkey (FIDO2) policy has a 20 KB ceiling, and you get at most three profiles including Default. Budget your AAGUID lists accordingly.

2.1 Opt in and shape the Default profile

In the Entra admin center: Entra ID > Security > Authentication methods > Policies > Passkey (FIDO2). Click the banner to opt in to profiles, then on the Configure tab:

2.2 Design profiles per persona

A clean three-profile model within the limit:

Profile Target groups Passkey types Enforce attestation Key restrictions
Default (locked down) All users Device-bound Yes Block: consumer/synced AAGUIDs
Admins (hardware only) Tier-0, IT, Execs Device-bound Yes Allow: approved security-key AAGUIDs only
Frontline + Authenticator Pilot, Frontline Device-bound Yes Allow: Authenticator iOS/Android AAGUIDs

Behaviors that bite teams in production:

2.3 Find and pin AAGUIDs

An AAGUID is the 128-bit make/model identifier the FIDO2 spec mandates. Get approved values from your key vendor, or read them off an already-registered credential under the user’s Authentication methods. You can also enumerate registered passkeys via Graph to discover what is in use:

# Microsoft Graph (v1.0) — list a user's FIDO2 credentials incl. their AAGUID and model
GET https://graph.microsoft.com/v1.0/users/{userId}/authentication/fido2Methods
# Graph PowerShell equivalent, then group by model to inventory your fleet
Connect-MgGraph -Scopes "UserAuthenticationMethod.Read.All"
Get-MgUserAuthenticationFido2Method -UserId "ada@contoso.com" |
  Select-Object DisplayName, AaGuid, Model

Put the approved AAGUIDs in the Admins profile as an Allow list with Enforce attestation = Yes. That combination is what makes “only company-issued keys for Tier-0” an enforced control rather than a wiki page.

3. Windows Hello for Business cloud Kerberos trust: the Entra Kerberos object

WHfB authenticates to Entra ID with a TPM-bound key. To get SSO to on-prem AD resources (file shares, IIS/Kerberos apps), Entra ID must mint a partial Kerberos TGT for your AD domain. Cloud Kerberos trust is the modern, low-friction way: no PKI, no certificate templates, no NDES. The same Entra Kerberos object also powers FIDO2-key SSO to on-prem, so if you already enabled security-key sign-in to on-prem, you are done here.

3.1 Create the Entra Kerberos server object

Run from the Entra Connect server (or any box with Microsoft.Online.PasswordSynchronization.Rpc.dll). You need Domain Admin + Enterprise Admin on-prem and a Hybrid Identity Administrator in Entra.

# Ensure TLS 1.2, then install the module from the PowerShell Gallery
[Net.ServicePointManager]::SecurityProtocol = `
  [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12
Install-Module -Name AzureADHybridAuthenticationManagement -AllowClobber

If modern auth (MFA/FIDO2) protects your admin sign-in, use the -UserPrincipalName form so the cmdlet opens an interactive sign-in rather than a password prompt:

$domain = $env:USERDNSDOMAIN
$upn    = "kerbadmin@contoso.onmicrosoft.com"   # Hybrid Identity Administrator UPN
$domainCred = Get-Credential                      # Domain Admin / Enterprise Admin

# Creates CN=AzureADKerberos in OU=Domain Controllers and publishes to Entra ID
Set-AzureADKerberosServer -Domain $domain -UserPrincipalName $upn -DomainCredential $domainCred

Run it once per AD domain that contains synced users (multi-forest = one object per domain per forest).

One tenant per AD domain. The AzureADKerberos object is strictly one-per-domain and tenant-bound. Running Set-AzureADKerberosServer for a second tenant in the same domain overwrites the first. There is no shared-domain, two-tenant cloud Kerberos trust.

3.2 Configure the WHfB policy (Intune Settings Catalog)

Three settings turn on cloud-trust WHfB. Create a Settings Catalog policy under Windows Hello for Business:

Setting Value
Use Windows Hello For Business true
Use Cloud Trust For On Prem Auth Enabled
Require Security Device true

Prefer a custom OMA-URI policy? The PassportForWork CSP paths are verbatim ({TenantId} is your directory GUID):

./Device/Vendor/MSFT/PassportForWork/{TenantId}/Policies/UsePassportForWork        bool  True
./Device/Vendor/MSFT/PassportForWork/{TenantId}/Policies/UseCloudTrustForOnPremAuth bool  True
./Device/Vendor/MSFT/PassportForWork/{TenantId}/Policies/RequireSecurityDevice      bool  True

Trust-model conflicts are silent foot-guns. If Use certificate for on-premises authentication is enabled anywhere in scope, certificate trust wins over cloud Kerberos trust, leave it not configured. And if both GPO and Intune configure WHfB, GPO wins and Intune is ignored. Pick one channel per device.

4. Provisioning and self-service registration, with TAP as the bootstrap

The chicken-and-egg problem: to register a strong credential the user must first prove identity strongly. A Temporary Access Pass (TAP) is the time-boxed bootstrap that breaks the loop, the user signs in with the TAP, then enrolls a passkey or WHfB PIN.

4.1 Enable and tune the TAP policy

Enable Temporary Access Pass under Authentication methods, scoped to a sg-passwordless-onboarding group. For onboarding, prefer one-time passes with a short life:

Connect-MgGraph -Scopes "Policy.ReadWrite.AuthenticationMethod"
# Confirm TAP is enabled in the method policy
Get-MgPolicyAuthenticationMethodPolicyAuthenticationMethodConfiguration `
  -AuthenticationMethodConfigurationId "TemporaryAccessPass"

4.2 Issue a TAP at the service desk

# UserAuthenticationMethod.ReadWrite.All required
$body = @{
  isUsableOnce      = $true        # single-use bootstrap
  lifetimeInMinutes = 60           # valid range is 10..43200 (30 days)
  startDateTime     = (Get-Date).ToUniversalTime().ToString("o")
}
New-MgUserAuthenticationTemporaryAccessPassMethod `
  -UserId "newhire@contoso.com" -BodyParameter $body |
  Select-Object TemporaryAccessPass, IsUsableOnce, LifetimeInMinutes

The user takes that code to Security info, signs in, and registers a security key or Authenticator passkey. WHfB provisions during Windows OOBE or under Settings > Accounts > Sign-in options after the first TAP sign-in.

Two registration gates people miss: users must have completed MFA within the last 5 minutes before a passkey registration is accepted, and guests/B2B users cannot register passkeys in the resource tenant at all. Plan a different path for external collaborators.

5. Enforce phishing-resistant MFA with Conditional Access authentication strengths

Enabling the methods does not require anyone to use them. The enforcement lever is a Conditional Access (CA) policy with the Require authentication strength grant control. Use the built-in Phishing-resistant MFA strength, whose allowed combinations are exactly the three credentials we care about, internally windowsHelloForBusiness, fido2, and x509CertificateMultiFactor:

Retrieve the built-in policy so you reference the correct immutable ID instead of guessing it:

# Built-in strengths are fixed and unmodifiable; grab the phishing-resistant one
GET https://graph.microsoft.com/v1.0/identity/conditionalAccess/authenticationStrength/policies?$filter=policyType eq 'builtIn'
Connect-MgGraph -Scopes "Policy.Read.All","Policy.ReadWrite.ConditionalAccess"
$pr = Get-MgPolicyAuthenticationStrengthPolicy |
  Where-Object { $_.PolicyType -eq 'builtIn' -and $_.DisplayName -eq 'Phishing-resistant MFA' }
$pr.Id; $pr.AllowedCombinations

Now bind it, starting in report-only to measure breakage before you block:

$params = @{
  DisplayName = "PR1 - Phishing-resistant MFA for admins"
  State       = "enabledForReportingButNotEnforced"   # flip to 'enabled' after pilot
  Conditions  = @{
    Users        = @{ IncludeGroups = @("<sg-tier0-admins-object-id>") }
    Applications = @{ IncludeApplications = @("All") }
  }
  GrantControls = @{
    Operator                    = "OR"
    AuthenticationStrength      = @{ Id = $pr.Id }
  }
}
New-MgIdentityConditionalAccessPolicy -BodyParameter $params

You cannot combine Require MFA and Require authentication strength in the same CA policy, the built-in MFA strength already equals Require MFA. Use separate policies. And because CA is evaluated after primary auth, a phishing-resistant strength does not block the password prompt itself, it forces a phishing-resistant method before access is granted.

Keep a separate, tighter strength on the Register security information user action so new hires can use a TAP to bootstrap but cannot use a TAP anywhere else.

6. Hybrid edge cases: RDP, on-prem SSO, and legacy fallbacks

Passwordless rollouts stall here if you have not pre-mapped the gaps.

7. Lifecycle: revocation, lost-device recovery, and audit

A credential you cannot revoke or report on is a liability. Revoke a lost key or passkey from the user’s Authentication methods, or via Graph:

# Delete a specific FIDO2 / device-bound passkey credential
Remove-MgUserAuthenticationFido2Method -UserId "ada@contoso.com" -Fido2AuthenticationMethodId "<methodId>"
# Force re-auth everywhere by revoking refresh tokens
Revoke-MgUserSignInSession -UserId "ada@contoso.com"

Lost-device recovery is onboarding in reverse: helpdesk verifies identity out-of-band, issues a fresh one-time TAP, the user registers a replacement, the old credential is deleted. Because you delete the lost credential’s entry, that key is dead even if found.

Rotate the Entra Kerberos key on the same cadence as your AD krbtgt rotations, and only with this cmdlet so both sides stay in sync:

Set-AzureADKerberosServer -Domain $domain -UserPrincipalName $upn `
  -DomainCredential $domainCred -RotateServerKey

Audit with KQL in the sign-in logs to prove adoption and catch stragglers still using passwords against sensitive apps:

SigninLogs
| where TimeGenerated > ago(30d)
| where ResultType == 0
| extend method = tostring(AuthenticationDetails[0].authenticationMethod)
| summarize signins = count() by method, bin(TimeGenerated, 1d)
| order by TimeGenerated asc
// Phishing-resistant coverage for a sensitive app: who is NOT yet passwordless
SigninLogs
| where AppDisplayName == "Contoso Finance"
| summarize total = count(),
            phishResistant = countif(AuthenticationRequirement == "multiFactorAuthentication"
              and AuthenticationDetails has_any ("FIDO2", "Windows Hello", "Passkey"))
            by UserPrincipalName
| extend pct = round(100.0 * phishResistant / total, 1)
| where pct < 100
| order by pct asc

8. Pilot-to-production rollout waves and break-glass

Sequence the program; do not flip the tenant.

  1. Wave 0 - Foundations. Enable methods, create the Entra Kerberos object, deploy the WHfB Intune policy to a device pilot ring. No enforcement.
  2. Wave 1 - Admins (hardware keys). Issue security keys, register via TAP, enforce the Phishing-resistant MFA strength on Tier-0 in block mode. Highest value, smallest blast radius.
  3. Wave 2 - Knowledge workers. WHfB provisions silently as devices hit the policy. Run the CA strength in report-only for two weeks, fix the long tail, then block.
  4. Wave 3 - Frontline + long tail. Authenticator passkeys for mobile-first staff; remediate or exclude legacy apps on a deprecation clock.
  5. Wave 4 - Password de-emphasis. Once coverage is high, scope passwordless cohorts out of password methods and disable SSPR-to-password.

Break-glass is non-negotiable. Keep at least two cloud-only emergency-access accounts excluded from every CA policy (including the phishing-resistant strength), secured with a stored FIDO2 key, and alerted on every sign-in. They are your way back in if a strength policy or the Kerberos object goes sideways at 2 a.m.

Enterprise scenario

A global manufacturer (~28,000 staff, single AD forest, two child domains, Entra hybrid join) had enforced number-matching MFA and still lost three finance accounts to an AiTM kit in one quarter. The mandate from the CISO: phishing-resistant primary auth for everyone in 90 days. The constraint that nearly derailed it: roughly 1,400 shop-floor PCs had TPMs disabled in OEM firmware, so WHfB (which requires a security device) simply could not provision on them, and re-imaging 1,400 machines was not happening inside the window.

The platform team split the population by capability instead of forcing one credential. WHfB cloud Kerberos trust covered the ~24,000 TPM-capable managed PCs with zero per-user cost. The 1,400 no-TPM machines, plus all Tier-0 admins, got company-issued FIDO2 keys with an enforced AAGUID allow-list so only the procured model would register. The make-or-break detail was the on-prem SSO gap on the no-TPM fleet: those PCs ran a Kerberos-authenticated MES web app, and the team had to confirm the Entra Kerberos object and the three synced attributes were healthy before removing passwords, otherwise the line would have stopped.

# Pre-cutover gate the team ran per domain: prove Entra Kerberos is healthy
# (KeyVersion must equal CloudKeyVersion, and CloudId must match ID)
Get-AzureADKerberosServer -Domain $domain -UserPrincipalName $upn -DomainCredential (Get-Credential) |
  Select-Object Id, CloudId, KeyVersion, CloudKeyVersion, DomainDnsName

With that verified, they ran the strength in report-only for ten business days, watched the no-TPM ring for failed on-prem SSO, then enforced in block mode wave by wave. Phishing-resistant coverage went from 0 to 96% in 71 days; the remaining 4% were three legacy apps on a hard deprecation date, and credential-phishing incidents went to zero.

Verify

Checklist

Entra IDFIDO2PasswordlessPasskeysWindows Hello

Comments

Keep Reading