68 min read

WebAuthn and Passkeys on Windows: From CTAP to the Credential Provider Model

The know/have/are taxonomy collapses against modern phishing kits. Passkeys, WebAuthn Level 3, CTAP 2.x, and Windows 11 24H2 third-party providers score against the criteria that actually matter -- and recovery is the load-bearing column.

Permalink

1. Two factors, no security

A junior engineer at a mid-size firm types her Microsoft 365 credentials into what looks exactly like the real login.microsoftonline page, approves the push notification on her phone, and an hour later the security team is reading her inbox -- because the attacker was, too. The kit is Tycoon 2FA, the technique is reverse-proxy adversary-in-the-middle, and the marketing claim that "password plus MFA is two factors" just lost to a commodity off-the-shelf service. The same class of phishing-as-a-service kit (Evilginx, Caffeine, EvilProxy, Tycoon 2FA) is the dominant phishing toolset in 2024-2026; the kit sits between the user and the real Microsoft login page, captures the credentials and the post-MFA session cookie in flight, and hands a live session to the attacker [1].

Replay the exact same attack against a colleague whose only authenticator is a WebAuthn passkey. The kit serves the look-alike page; the page hands the browser a WebAuthn PublicKeyCredentialRequestOptions blob with a fresh challenge. The browser builds clientDataJSON with type: "webauthn.get", the actual origin the user is on (the look-alike domain login-microsoft0nline.example, protocol scheme included), and the challenge. The authenticator computes the RP-ID hash from that origin, looks up its stored credential, and finds nothing -- it never registered a passkey for that domain. There is no signature to relay. The kit gets bytes that the real Microsoft server will reject on the first verification step. Microsoft's own documentation puts it bluntly: passkeys "use origin-bound public key cryptography, ensuring credentials can't be replayed or shared with malicious actors" [2].

The know/have/are taxonomy ranks these two ceremonies as the same. Password plus push is "something you know" plus "something you have," and so is password plus a passkey on a YubiKey. The taxonomy predicts that both ceremonies are roughly twice as strong as one factor alone. The phishing kit demolishes one and bounces off the other. The taxonomy is wrong.

The right question is not "how many factors did the user produce?" It is "what does the attacker have to defeat?" The know/have/are buckets group authenticators by what the user feels they are producing. The criteria framework groups them by what an attacker has to defeat. Only the second taxonomy predicts the outcome of a real-world attack. The phishing kit walks through password plus push because nothing in that ceremony binds the user's secret to a specific origin. It bounces off the passkey because the passkey signs over the origin the browser is actually on, and no amount of reverse proxying changes that string.

If the taxonomy is wrong, what is the right one? That is the question §2 answers.

2. The criteria framework: five axes that actually predict outcomes

The replacement for know/have/are is a five-row table. The rows are what an attacker has to defeat, not what the user thinks they are producing. The spine of the table is taken from NIST SP 800-63-4 (final, July 2025) [3], NIST SP 800-63B-4 [4], the FIDO Alliance Authenticator Certification Levels [5], and the IETF channel-binding lineage that runs from RFC 5056 (Williams, November 2007) [6] through RFC 9266 (Whited, July 2022) [7].

Phishing-resistant authenticator

An authenticator whose protocol prevents a relying party impersonator (an adversary-in-the-middle) from inducing the authenticator to release a usable credential value. NIST SP 800-63B-4 formalises the requirement as verifier-impersonation resistance. The practitioner formulation, courtesy of Yubico, is verbatim: an authenticator is phishing-resistant if it binds its output to a communication channel or a verifier name [8].

Axis 1: phishing resistance

The criterion: can a look-alike domain induce the user (or the user's authenticator) to release a credential value that the look-alike then replays to the real verifier? Password plus any unbound second factor (SMS-OTP, TOTP, push) fails the criterion -- the kit just forwards every value the user produces. WebAuthn passes it by construction: the authenticator signs over clientDataJSON, which the browser fills in with the actual origin the user is on, and the signature is computed jointly over a hash of the RP identifier derived from that origin. The RP refuses any signature whose RP-ID hash does not match the registered rpId.

Origin binding

The mechanism by which WebAuthn enforces phishing resistance: the browser writes the user's actual origin into clientDataJSON.origin, the authenticator signs over the SHA-256 hash of the canonical RP identifier (rpIdHash in authenticatorData), and the relying party validates that rpIdHash matches the RP identifier under which the credential was registered. The cryptography is trivial. The value is in the binding.

Microsoft's Entra documentation states the criterion verbatim: passkeys "provide verifier impersonation resistance, which ensures an authenticator only releases secrets to the Relying Party (RP) the passkey was registered with and not an attacker pretending to be that RP" [2].

Axis 2: verifier-compromise resistance

The criterion: if the relying party's authentication database is exfiltrated, can the attacker use the stolen material to log in? Passwords fail this criterion in the worst possible way -- a salted hash is replayable after offline cracking, and a billion-row password dump is the standard primary input to credential stuffing. The public-key model passes the criterion definitionally. The relying party stores only the credential's public key; no signature is ever made by the relying party. Even a complete database leak gives the attacker zero authenticators.

This criterion is older than WebAuthn by half a century. Morris and Thompson's 1979 password paper made the verifier-compromise case for hashing passwords on a multi-user UNIX system [9]; the WebAuthn move is the realisation that even bcrypt'd password databases lose this criterion eventually, because the work factor that protects them today is one Moore's-law decade away from being trivial.

Axis 3: replay and relay resistance

The criterion: can an attacker who observes one successful authentication replay it later, or relay it to a different verifier? OTP-based ceremonies (HOTP [10], TOTP [11]) provide partial replay resistance via a per-instance counter or timestamp, but they offer almost no relay resistance: the AitM kit forwards the OTP through its proxy within the OTP's validity window.

WebAuthn passes the criterion with three layered mechanisms. The first is a fresh challenge issued by the RP for every ceremony, which the authenticator signs over. The second is a per-credential signature counter included in authenticatorData, monotonically increasing on each use (the relying party rejects any assertion whose counter is not strictly greater than the previous one, modulo the synced-passkey carve-out we will reach in §7). The third is channel binding -- the structurally correct answer to relay attacks, which sits at the TLS layer rather than the application layer.

The IETF Token Binding stack (RFC 8471, RFC 8473, both October 2018) [12] [13] was the most ambitious attempt at the channel-binding criterion at the application layer. Both RFCs remain Proposed Standard at the IETF -- the datatracker history pages record no Historic reclassification event for either [14] [15] -- but Chromium removed support in version 70 in October 2018, the same month the RFCs were published, and no major browser has implemented them since [16]. The clientDataJSON.tokenBinding field is therefore a no-op in 2026 production. WebAuthn solves the criterion above the channel by signing the origin into the assertion itself.

The cleaner channel-binding answer is RFC 9266 tls-exporter for TLS 1.3 (Whited, July 2022) [7], which extends RFC 5056's channel-binding framework into the TLS 1.3 world -- but no major browser wires tls-exporter into WebAuthn out of the box as of January 2026. The current WebAuthn deployment treats the origin string in clientDataJSON as the primary channel binding, with HTTPS itself providing the underlying TLS guarantee.

Axis 4: step-up and session continuity

The criterion: can the relying party demand a fresh authentication for a high-value action (transfer money, change password, invite a user), and can it tell the difference between a session that was authenticated with strong factors and one that was authenticated with weak factors? WebAuthn answers this with two flag bits in authenticatorData. UP (user present) is set when the authenticator detected a presence test -- a touch, a click, an NFC tap. UV (user verified) is set when the authenticator additionally verified the user via PIN, biometric, or other gesture. A relying party that demands userVerification: "required" can force UV=1 on the assertion; an RP that issues a fresh challenge for a high-value action gets a fresh signature tied to that challenge.

Generic transactional confirmation -- "sign a description of this specific transaction" -- was attempted in WebAuthn's earliest drafts via the txAuthSimple and txAuthGeneric extensions [17]. Neither extension was ever implemented by browsers, and both are absent from the Level 3 specification surface as of January 2026 [18]. The Secure Payment Confirmation flow in WebAuthn Level 3 [19] is the productised replacement for payment transactions; general transactional authorisation remains an open problem.

Axis 5: recovery and lifecycle

The heretical thesis: this is the only axis that matters in production, and it is the axis on which every modern platform still bottoms out at a single-factor primitive. We will foreshadow it here and land on it in §17. A passkey ceremony that scores AAL3 phishing-resistant at the authentication moment can be a single-factor SMS-OTP at the recovery moment -- and the system's AAL is the recovery flow's AAL, not the authentication ceremony's. Microsoft's Entra documentation already flags account recovery as a load-bearing deployment cost: FIDO2 keys "can increase costs for equipment, training, and helpdesk support -- especially when users lose their physical keys and need account recovery" [2].

The criteria table as a spine

The five axes give the article its spine. Every later section fills in a row of the same five-column table. The columns are the strongest authenticators we have shipped: password, password plus SMS-OTP, password plus TOTP, password plus push with number matching, device-bound FIDO2 hardware key, synced passkey, and a hypothetical "recovery-flow-aware" composite. The criteria-aware ranking (§13) re-orders that table in a way the know/have/are taxonomy cannot.

The know/have/are taxonomy groups authenticators by what the user feels they are producing. The criteria framework groups them by what an attacker has to defeat. Only the second taxonomy predicts the outcome of a real-world attack.

If these are the right axes, when did we figure that out?

3. Where the taxonomy came from

The know/have/are taxonomy did not appear all at once. The 1970s and 1980s operating-systems literature already grouped authentication factors into "something the user knows," "something the user has," and "something the user is" -- it was a way of talking about the design space, not a regulatory criterion. The taxonomy entered U.S. federal procurement via the Department of Defense's Trusted Computer System Evaluation Criteria in December 1985 -- the Orange Book, DOD 5200.28-STD [20] -- which required identification and authentication at every assurance class above D and made passwords the canonical something you know in federal IT. The Orange Book did not invent the taxonomy; it codified it.

Two decades later, in June 2004, NIST canonised the same taxonomy as the U.S. federal regulatory framework. NIST SP 800-63 Electronic Authentication Guideline -- by William Burr, Donna Dodson, and W. Timothy Polk -- defined four assurance levels and tied each to a combination of authenticator categories that the levels could accept [21] [22]. Burr's framework absorbed two decades of accumulated practice with hardware OTP tokens. The canonical commercial OTP product, RSA SecurID, had shipped in 1986 -- a key fob that produced a fresh code each minute using a built-in clock and a factory-encoded seed [23] -- and SP 800-63 explicitly accepted SecurID-class authenticators at the higher assurance levels. The four-level structure (later AAL1 through AAL3 in the post-2017 redesign) lasted through SP 800-63-1 (2011), -2 (2013), -3 (2017), and -4 (2025); every revision is recognisably the same shape [24].

The CSRC bibliographic page for the 2004 first edition renders the leading author as a blank entry preceded by a stray comma, an artefact of Burr's retirement from NIST after publication. The actual cover-page authorship is Burr, Dodson, and Polk -- the citation in the references list above uses the correct three-name form.

In parallel, the cryptographic protocol literature was building the criteria taxonomy that would eventually displace know/have/are. Bellcore's Neil Haller published RFC 1760 in February 1995 -- the S/KEY one-time password system, a Lamport hash chain that produced a fresh login secret each time and that an eavesdropper could not replay [25]. Haller's text already says the technique was first suggested by Leslie Lamport, which makes 1995 the first IETF standardisation of replay-resistance as a design criterion. RFC 4226 (HOTP, December 2005) [10] and RFC 6238 (TOTP, May 2011) [11] generalised the same idea into the synchronised counter and time-based variants the world now calls "authenticator app" codes.

The verifier-impersonation criterion got its first IETF expression in November 2007. Nico Williams' RFC 5056 On the Use of Channel Bindings to Secure Channels defined the concept that "the two end-points of a secure channel at one network layer are the same as at a higher layer," and bound authentication at the higher layer to the channel at the lower layer [6]. RFC 5056 was the protocol-literature acknowledgement that authentication needed to be tied to something the network attacker could not change -- the channel itself, not just the user's typing.

Kim Cameron's The Laws of Identity, published on identityblog.com in May 2005, captured the same idea from a higher-level perspective. The seven Laws are a framework for federated identity on the open Internet; Laws 2 ("minimal disclosure for a constrained use") and 4 ("directed identity") are the conceptual ancestors of WebAuthn's origin binding and per-RP key pair design [26]. Cameron was Microsoft's Chief Identity Architect through this period, and the Laws shaped a generation of Microsoft thinking on identity. The Laws preceded the consortium that would actually ship the protocol by eight years.

Ctrl + scroll to zoom
Forty years of authentication standards, criteria and codification

By 2007 the criteria framework was on paper. By 2013 there was a consortium for it: the FIDO Alliance launched on 12 February 2013 [27], with six founding members [28]. Earlier identity-layer attempts -- Mozilla Persona / BrowserID, launched July 2011, with decommissioning announced January 2016 and the service shut down on 30 November 2016 [29] -- had tried to build a browser-mediated identity layer at the HTTP level and failed to achieve traction. The FIDO consortium took a different bet: solve the authentication ceremony first, leave the identity-layer above it to OIDC and SAML. What happened first in a browser?

4. U2F: the first browser ceremony designed against phishing

December 2014. Yubico, Google, and NXP Semiconductors publish FIDO 1.0 / Universal 2nd Factor (U2F) [30]; U2F 1.0 reached Proposed Standard status on 9 October 2014, with the broader FIDO 1.0 announcement window running through December [31]. The Universal 2nd Factor Wikipedia article catalogues the design tradeoffs explicitly: U2F's challenge-response is "signed (encoding originating domain/website) to prevent interception and reuse" [31]. This was the first time a browser ceremony was designed against the phishing-resistance criterion as a primary goal rather than as an afterthought.

The U2F ceremony has five field-level moving parts. An AppID string identifies the relying party, derived from the page's origin so a phisher's domain cannot produce a U2F signature for the real bank. A challenge is a per-ceremony nonce the relying party generates. A key handle is an opaque blob the authenticator returns at registration and supplies on every later assertion; the relying party uses it to address the right credential on the next challenge. A signature counter increments monotonically on every assertion, letting the relying party detect simple cloning. And the signature itself is an ECDSA P-256 signature over the AppID hash, the challenge, the counter, and a presence flag.

The AppID rule is the load-bearing piece. The browser computes the AppID from the actual origin the user is on; the authenticator signs over its hash; the relying party compares it to the AppID under which the credential was registered. A look-alike domain produces a different AppID, which produces a different signature, which the real verifier rejects. This is the same trick WebAuthn will later generalise as rpId binding -- and it is the trick that makes U2F structurally immune to the AitM kits that will demolish password plus push a decade later.

The canonical deployment paper is Security Keys: Practical Cryptographic Second Factors for the Modern Web, by Juan Lang, Alexei Czeskis, Dirk Balfanz, Marius Schilder, and Sampath Srinivas, in the Financial Cryptography 2016 preproceedings [32]. The paper documents Google's internal rollout: a hardware second factor for every employee, replacing the company's previous OTP-based MFA. The empirical scoreboard for the criteria framework gets its first data point here -- after the rollout, Google reported zero phishing-related account takeovers on employee accounts during the deployment period. This is not a controlled study; it is the largest natural experiment in deployed phishing resistance the industry had seen.

U2F's limitation is that it is, by design, a second factor. The password under it remains the load-bearing weak link: a credential-stuffer can reuse the password against a service that does not require U2F, and a phisher can still capture the password even if they cannot capture the U2F signature. The AppID idea was correct; what was missing was the willingness to make the strong factor the factor, not a layer on top of a weak one. The bridge from U2F to FIDO2 is exactly that move.

The other piece U2F got right and FIDO2 inherited is the principle that the credential is device-bound by default. The U2F Wikipedia summary captures the consequence: "no recovery of the key is possible" if the device is lost [31]. This is the same property that makes synced passkeys, when they arrive in May 2022, a productisation rather than a cryptographic move. The bytes are the same. The lifecycle is different.

If the second factor is doing all the work, why not make it the factor?

5. FIDO2 + CTAP 2.0 + WebAuthn Level 1: the spec lands

March 4, 2019. The World Wide Web Consortium and the FIDO Alliance announced that the Web Authentication specification was an official W3C Recommendation [33]; the dated Recommendation slug is REC-webauthn-1-20190304 [34]. Same day, with January 30, 2019 as the underlying CTAP 2.0 Proposed Standard date [35]. The pair is what the industry markets as FIDO2.

The reframe was decisive. A platform authenticator -- Windows Hello on Windows, Touch ID on macOS, the Android Keystore on Android -- was now a first-class FIDO authenticator. The user's laptop or phone could be the authenticator. The browser did not need a separate USB device; it could call into the OS instead. This is the move that made FIDO2 a consumer technology, not just a security-team technology.

WebAuthn relying party (RP) and rpId

The relying party is the web service that owns the user's account. The rpId is a string identifying that party for credential scoping; it must be a registrable suffix of the page's origin (so login.bank.com may use bank.com as its rpId, but evil.com may not). All WebAuthn signatures are made over the SHA-256 hash of the rpId, which the browser derives from the actual origin and writes into clientDataJSON. The relying party validates the signature against the public key registered for that rpId. Phishing resistance is rpId binding, full stop [19].

The Web IDL surface that WebAuthn Level 1 standardised is small. navigator.credentials.create({publicKey: ...}) registers a new credential; navigator.credentials.get({publicKey: ...}) produces an assertion. Both return PublicKeyCredential objects. The complexity is not in the API; it is in the byte-level structures the API exchanges.

A registration ceremony looks like this. The relying party generates a PublicKeyCredentialCreationOptions blob containing a fresh challenge, the rpId, the user's account identifier, the list of algorithms the RP supports, the desired user verification, and an optional list of credentials the user already has. The browser passes this to the authenticator and gets back two byte blobs. The first is clientDataJSON -- a UTF-8 JSON blob containing type: "webauthn.create", the origin the browser was actually on, and the challenge. The second is authenticatorData -- a binary blob containing the rpIdHash (SHA-256 of the canonical rpId), the flags byte (with UP, UV, AT, ED bits), the signature counter (initially zero, sometimes non-zero), the new credential's identifier, the AAGUID identifying the authenticator model, and the credential's public key in COSE_Key format. An optional attestation statement binds those bytes to a hardware root of trust.

AAGUID (Authenticator Attestation GUID)

A 16-byte identifier the authenticator includes in authenticatorData to identify its make and model. Some authenticators emit an all-zeros AAGUID for privacy. Microsoft's Entra ID hardware-vendor matrix lists dozens of FIDO2 keys with their AAGUIDs and supported transports [36]; the FIDO Metadata Service is the authoritative directory.

Ctrl + scroll to zoom
WebAuthn registration ceremony at the field level

An authentication ceremony is the same shape with one structural change: the RP supplies PublicKeyCredentialRequestOptions with a fresh challenge, the authenticator finds the credential matching the rpId, prompts the user for a gesture (if userVerification is requested), and produces an assertion -- a signature over authenticatorData || SHA-256(clientDataJSON) with the credential's private key. The relying party verifies the signature against the stored public key.

The Windows-side surface debuts in the same window. Microsoft Learn states verbatim that Microsoft "introduced the W3C/Fast IDentity Online 2 (FIDO2) Win32 WebAuthn platform APIs in Windows 10 (version 1903)" [37]. May 2019. webauthn.dll ships. From that moment on, every browser on Windows -- Edge, Chrome, Firefox, Brave -- talks WebAuthn through one Win32 surface. The Microsoft Learn passkey overview makes the underlying architecture explicit: "When these APIs are in use, Windows 10 browsers or applications don't have direct access to the FIDO2 transports for FIDO-related messaging" [37]. The OS is the dispatcher.

The W3C/FIDO press release named the launch implementations: Windows 10, Android, Chrome, Firefox, Edge, and Safari (in preview) [33]. Microsoft, Google, Mozilla, and Apple all shipped within the same year. WebAuthn became the most-implemented strong-authentication standard on the consumer web inside eighteen months.

JavaScript Parse a real-world clientDataJSON and authenticatorData
// A reader can paste in their own clientDataJSON and authenticatorData
// (base64url-encoded as Microsoft returns them) to see how the parser
// walks the bytes. Origin binding is one SHA-256 invocation away from
// being a one-liner; the value is in the binding, not the cryptography.

const clientDataB64 = "eyJ0eXBlIjoid2ViYXV0aG4uZ2V0Iiwib3JpZ2luIjoiaHR0cHM6Ly9sb2dpbi5taWNyb3NvZnRvbmxpbmUuY29tIiwiY2hhbGxlbmdlIjoiUk5KU2V6NjFqdyJ9";
const authDataB64 = "Y9JZsAcVeQOLgxs9Ux7QYZpyTaB-OkpdyPwQk7P9YsoFAAAAFw";

function b64urlDecode(s) {
s = s.replace(/-/g,'+').replace(/_/g,'/');
while (s.length % 4) s += '=';
return Uint8Array.from(atob(s), c => c.charCodeAt(0));
}

const clientDataBytes = b64urlDecode(clientDataB64);
const clientData = JSON.parse(new TextDecoder().decode(clientDataBytes));
console.log("clientDataJSON.type     =", clientData.type);
console.log("clientDataJSON.origin   =", clientData.origin);
console.log("clientDataJSON.challenge=", clientData.challenge);

const authData = b64urlDecode(authDataB64);
const rpIdHash = authData.slice(0, 32);
const flags = authData[32];
const signCount = (authData[33]<<24) | (authData[34]<<16) | (authData[35]<<8) | authData[36];
console.log("authenticatorData rpIdHash =", Array.from(rpIdHash).map(b=>b.toString(16).padStart(2,'0')).join(''));
console.log("authenticatorData flags    = 0x" + flags.toString(16),
          "UP="+(flags&1), "UV="+((flags>>2)&1), "BE="+((flags>>3)&1), "BS="+((flags>>4)&1), "AT="+((flags>>6)&1));
console.log("authenticatorData signCount=", signCount);

Press Run to execute.

The credential's public key is encoded as a COSE_Key map -- a CBOR object whose algorithm identifier is one of the entries in the IANA COSE Algorithms registry [38]. As of the registry's 2026-03-04 update, no post-quantum algorithm is in WebAuthn-recommended status; ECDSA P-256 and EdDSA Ed25519 remain the workhorses. The companion Post-Quantum Cryptography on Windows article walks the algorithm-side rollout.

Level 1 settled the field-level shape. What did the next two years sharpen?

6. CTAP 2.1: the wire protocol every security key is speaking

15 June 2021. The FIDO Alliance published CTAP 2.1 as a Proposed Standard [39]. CTAP 2.1 is the CBOR-on-the-wire version most security keys in 2024-2026 are running; CTAP 2.2 (Proposed Standard, 14 July 2025) [40] refines a few corners, and CTAP 2.3 is the Proposed Standard the FIDO Alliance lists alongside it [41]. Each version adds capability without breaking the previous one's commands.

CTAP 2.x

The Client-to-Authenticator Protocol -- the wire format the browser speaks to a roaming authenticator over USB-HID, NFC, or BLE. CTAP1 (the original U2F messages) carries APDU-style binary structures; CTAP2 carries CBOR-encoded commands. A CTAP2 authenticator (also called a FIDO2 or WebAuthn authenticator) implements the CTAP2 command set; modern keys also implement CTAP1 for backwards compatibility [35].

The CTAP2 command-byte table is the surface a browser actually dispatches to. Each command is a single byte followed by a CBOR-encoded request map. The table below names the commands in order and the criterion-table cell each one strengthens.

Command byteCommand nameWhat it doesCriterion strengthened
0x01authenticatorMakeCredentialRegistration: generate a fresh keypair bound to (rpId, user.id)Phishing resistance (origin binding)
0x02authenticatorGetAssertionAuthentication: sign the challenge with the credential's private keyPhishing + replay + verifier-compromise
0x04authenticatorGetInfoCapability discovery: list supported algorithms, extensions, transports, UV modesStep-up (lets RP know what's available)
0x06authenticatorClientPINManage the PIN, issue pinUvAuthToken with permissions bitmap and rpId scopingStep-up + replay
0x07authenticatorResetWipe all resident credentials on the deviceLifecycle
0x09authenticatorBioEnrollmentOn-token fingerprint enrolment (CTAP 2.1)Step-up (UV=1)
0x0AauthenticatorCredentialManagementList, enumerate, and delete resident credentials per RPLifecycle / recovery
0x0BauthenticatorSelection"Pick this device" prompt when multiple authenticators are presentUX (no criterion change)
0x0CauthenticatorLargeBlobsPer-credential blob store under the credentialStep-up (extension data)
0x0DauthenticatorConfigEnable enterprise attestation, toggle alwaysUv, set minimum PIN lengthVerifier-compromise + lifecycle

Three pieces of CTAP 2.1 are worth pulling out because they meaningfully change the criteria-table cells.

pinUvAuthToken and permissions. CTAP 2.0's PIN-protocol let the browser obtain a pinAuthToken and use it across any command. CTAP 2.1 introduced a permissions bitmap and rpId scoping on the token so that a token issued for one relying party's ceremony cannot be replayed against a different relying party's ceremony on the same authenticator [39]. This closes a class of host-side mischief: an attacker who got the PIN out of one ceremony could not previously be stopped from spending it on a different rpId.

credProtect. A new extension that lets the RP request a higher protection level on the resident credential -- specifically, that the authenticator should refuse to list the credential without a UV=1 gesture. The first generation of WebAuthn discoverable credentials were enumerable by any host that could speak CTAP2 to the connected key; credProtect lets the RP say "don't show this credential's existence to anything that doesn't pass user verification first."

Enterprise attestation. CTAP 2.1 added an explicit enterprise attestation mode in which the authenticator binds its attestation statement to a list of relying parties the device's enrolling organisation has pre-approved. This is the bridge that makes vendor attestation useful in managed enterprises without leaking the user's specific device identity to every relying party.

The largeBlob extension (CTAP 2.1, command 0x0C) gives each credential a small per-credential blob store. RPs use it for things like cached short-lived tokens or per-user policy. The 2024 release notes for the Windows webauthn.dll API surface flagged largeBlob support as one of the additions in Windows 11 22H2 [37]; a March 2023 Review Draft [42] foreshadowed the 2.2 refinements that landed in July 2025.

All of this is for experts. When did this stop being a security-team conversation and start being a consumer product? What changed in May 2022?

7. Passkeys: the productisation moment

5 May 2022. Apple, Google, and Microsoft jointly committed at the FIDO Alliance to a common passwordless sign-in standard [43]. The press release is short on protocol detail and long on user-facing language. The headline commitment, verbatim: "Allow users to automatically access their FIDO sign-in credentials (referred to by some as a 'passkey') on many of their devices, even new ones, without having to reenroll every account" [43]. Passkey entered the public lexicon. Andrew Shikiar, the FIDO Alliance's executive director and CMO at the time, named it in the press call.

"Allow users to automatically access their FIDO sign-in credentials (referred to by some as a 'passkey') on many of their devices, even new ones, without having to reenroll every account." -- Apple, Google, and Microsoft, joint FIDO Alliance announcement, 5 May 2022 [43]

The cryptographic move in May 2022 was small. The protocol bytes are the same FIDO2 / WebAuthn / CTAP2 bytes that shipped in March 2019. What changed was twofold: (a) the three platform vendors aligned their sync fabrics so that a passkey created on a user's phone would appear on the user's laptop, and (b) the user-facing terminology consolidated from a confusing menagerie ("discoverable credential," "resident key," "client-side discoverable credential") onto a single product term -- passkey.

Discoverable credential (resident key, passkey)

A WebAuthn credential whose user.id and account metadata are stored on the authenticator, so the authenticator can produce an assertion without the relying party first supplying a credential identifier. The CTAP 2.0 spec calls these resident keys [35]; the WebAuthn Level 2 spec calls them client-side discoverable credentials [44]; the May 2022 vendor commitment rebranded them as passkeys [43]. All three terms refer to the same on-the-wire object.

Discoverable credentials unlock usernameless sign-in. The relying party does not need to tell the authenticator which credential to use; the authenticator looks up its own resident credentials for the supplied rpId, shows the user the matching account, and asks for the user-verification gesture. This is the UX primitive every consumer-passkey flow leans on.

WebAuthn Level 3 (W3C Candidate Recommendation, latest snapshot dated 13 January 2026 [19] [18]) is the spec generation that productises passkeys. Level 3 standardises:

  • The hybrid transport (formerly known as caBLE), §6.3.3 of the L3 spec, which lets a phone act as a roaming authenticator for a nearby laptop via QR code plus ephemeral ECDH plus BLE proximity. We cover hybrid in §12.
  • JSON-serialisation helpers -- PublicKeyCredentialCreationOptionsJSON and PublicKeyCredentialRequestOptionsJSON -- that make WebAuthn easier to drive from a server SDK without manual base64url juggling.
  • getClientCapabilities() so the relying party can probe what the client supports before issuing the ceremony.
  • The credProps, prf, largeBlob, credProtect, and Secure Payment Confirmation extensions, each of which sharpens one cell of the criteria table.

The mid-2025 cadence picked up: CTAP 2.2 Proposed Standard on 14 July 2025 [40] refined hybrid-transport semantics and tightened credProtect.

The synced-vs-bound distinction is the structural new thing about passkeys. Before May 2022 a FIDO2 credential lived in one secure element; lose the YubiKey, lose the credential. Synced passkeys put the private key into a sync fabric -- Apple iCloud Keychain (originally 2013) [45], Google Password Manager (Chrome password sync, late 2000s onward), Microsoft Authenticator (originally 2015) [46], and Microsoft Account passkey sync (general availability for consumer accounts on 2 May 2024) [47] -- and let it appear on every device the user signs into. The mechanism is end-to-end encryption against a sync-fabric key that the platform vendor cannot read; Apple's Advanced Data Protection model is the strongest current public realisation [48].

The price: the long-term private key has left the original authenticator. NIST is unambiguous about the consequence. The April 2024 supplement Incorporating Syncable Authenticators into NIST SP 800-63B [49] -- since absorbed into NIST SP 800-63B-4 final, July 2025 [4] -- classifies synced passkeys at AAL2, not AAL3, because the key is no longer pinned to a single tamper-resistant element. Yubico's commentary captures the dichotomy verbatim: "FIDO passkeys that are not synced -- device-bound passkeys like YubiKeys -- and are properly stored in dedicated hardware have an AAL3 rating" [8].

The WebAuthn spec made the distinction observable. Two new flag bits in authenticatorData -- BE (Backup Eligible) and BS (Backup State) -- tell the relying party whether the credential is in principle syncable (BE=1) and whether it is currently backed up (BS=1) [19]. The RP can decide policy from those flags: a banking RP can require BE=0 (device-bound) credentials for AAL3 transactions, while accepting BS=1 (synced) credentials for AAL2 sign-in.

Microsoft's own numbers tell the productisation story in raw counts. The May 2024 Microsoft Security blog announcing passkey support for consumer accounts notes that Microsoft was "detecting around 115 password attacks per second" when Windows Hello first shipped in 2015; "less than a decade later, that number has surged 3,378% to more than 4,000 password attacks per second" [47]. The 1 May 2025 World Passkey Day post escalates again: "we observed a staggering 7,000 password attacks per second (more than double the rate from 2023). [...] now we see nearly a million passkeys registered every day." It also reports that "passkey sign-ins are eight times faster than a password and multifactor authentication," and that "more than 99% of people who sign into their Windows devices with their Microsoft account do so using Windows Hello" [50].

Passkeys are not a new cryptographic primitive. They are a productisation moment in which discoverable credentials became consumer-grade UX. The protocol moves were two years earlier; the product move is what changed the criteria-table scoreboard.

Passkeys are a productisation moment. On Windows specifically, what does the platform actually do between navigator.credentials.create and the TPM?

8. The Windows platform authenticator: webauthn.dll end-to-end

May 2019. Windows 10 version 1903. The Win32 platform WebAuthn API shipped, and from that moment on every browser and every native application on Windows that wants to do WebAuthn calls webauthn.dll. The header file webauthn.h is in the Windows SDK and is also published on GitHub at github.com/microsoft/webauthn [51]. The reference page on Microsoft Learn enumerates every function the API surfaces [52]. The 1903 ship date and the subsequent feature additions are documented verbatim by Microsoft Learn: "Microsoft has long been a proponent of passwordless authentication, and has introduced the W3C/Fast IDentity Online 2 (FIDO2) Win32 WebAuthn platform APIs in Windows 10 (version 1903). Starting in Windows 11, version 22H2, WebAuthn APIs support ECC algorithms and starting in Windows 11 version 24H2 WebAuthn APIs support plugin passkey managers" [37].

"When these APIs are in use, Windows 10 browsers or applications don't have direct access to the FIDO2 transports for FIDO-related messaging." -- Microsoft Learn, WebAuthn APIs for password-less authentication on Windows [37]

That sentence is the entire architectural premise. The OS dispatches FIDO2 ceremonies. The browser does not own the CTAP2 stack, the USB-HID transport, the NFC reader, the BLE pairing, or the Hello UV gesture. It hands webauthn.dll a request and gets back an assertion.

The API surface is a small set of functions. The ceremony surface is two functions, the management surface is the remainder.

  • WebAuthNAuthenticatorMakeCredential -- the registration entry point. Caller supplies origin / rpId / user / algorithms / attestation preference / authenticator-selection criteria. Returns an attestation object.
  • WebAuthNAuthenticatorGetAssertion -- the authentication entry point. Caller supplies origin / rpId / allowed credential IDs (or empty for usernameless) / user-verification preference / mediation (Conditional UI, see §9). Returns an assertion.
  • WebAuthNGetApiVersionNumber -- a monotonically increasing integer that lets callers feature-detect. Version 1 is Windows 10 1903; versions step up as Windows adds ECC algorithms (22H2), the plugin model (24H2), and the EXPERIMENTAL_*2 surface (Insider builds via KB5072046 [51]).
  • WebAuthNGetCancellationId / WebAuthNCancelCurrentOperation -- cooperative cancellation; the browser asks webauthn.dll to drop the active ceremony.
  • WebAuthNGetPlatformCredentialList / WebAuthNDeletePlatformCredential -- resident-credential management for synced passkeys held by the OS provider.
  • WebAuthNIsUserVerifyingPlatformAuthenticatorAvailable -- the isUVPAA capability probe; the RP uses this to decide whether to offer a passkey enrolment flow at all.
  • WebAuthNFreeAssertion / WebAuthNFreeCredentialAttestation / WebAuthNFreePlatformCredentialList -- caller-side memory release; the OS allocates on the heap and the caller is responsible for Free.
  • WebAuthNGetErrorName / WebAuthNGetW3CExceptionDOMError -- translate the Win32 HRESULT into a WebAuthn-spec error string.
Ctrl + scroll to zoom
Call graph for a platform-bound passkey registration on Windows

The criteria-framework consequence of that call graph is that the private key never leaves the TPM. Microsoft Learn states the property verbatim: "The private keys can only be used after they're unlocked by the user using the Windows Hello unlock factor (biometrics or PIN)" [53]. The TPM enforces use through its own access-control rules; even kernel malware on the host cannot exfiltrate the raw private key, only request operations gated on the user's gesture. This is what gets a Windows-platform-bound passkey on a TPM to AAL3 even when synced passkeys are bounded at AAL2.

The API version sentinel tells a clean feature-evolution story.

Windows releaseAPI version (approx.)Notable additions
Windows 10 1903 (May 2019)v1Initial Win32 surface: make/get credential, isUVPAA
Windows 10 1909 / 20H1v2UV preference, signal-handling refinements
Windows 11 21H2 (Oct 2021)v3Hybrid transport (caBLE) entrypoints
Windows 11 22H2 (Sep 2022)v4-v5ECC algorithms (ECDSA P-256 platform credentials), Conditional UI mediation
Windows 11 23H2 (Oct 2023)v6largeBlob, credProps, refined cancellation
Windows 11 24H2 (Oct 2024)v7Plug-in passkey managers (WebAuthNPlugin*), redesigned Hello UX
Insider builds (KB5072046)v7+EXPERIMENTAL_WebAuthNPluginAddAuthenticator2, EXPERIMENTAL_WebAuthNPluginPerformUserVerification2, EXPERIMENTAL_WebAuthNPluginUpdateAuthenticatorDetails2 [51]
The three EXPERIMENTAL_*2 APIs in github.com/microsoft/webauthn are Insider-only and will lose the EXPERIMENTAL_ prefix as they stabilise. The naming convention is the standard Windows SDK signal for "we want feedback before this becomes load-bearing public API."

The criterion-table consequence of dispatching FIDO2 through one OS surface is that every browser is automatically as strong as the OS. Edge does not need its own attestation logic; neither does Chrome, Firefox, or Brave. They all call the same webauthn.dll, which routes the registration to the TPM (for platform-bound passkeys), to USB-HID (for roaming security keys), or to a plug-in (for Windows 11 24H2 third-party providers, §10).

The webauthn.dll surface answers one half of the question. The other half is: what does the user actually see?

JavaScript Compute SHA-256 over an origin and verify the rpIdHash
// Origin binding is computationally trivial. The value is in the binding,
// not the cryptography. This snippet computes SHA-256 of an origin's
// effective rpId and compares against the rpIdHash a real authenticator
// would have signed. Paste in a clientDataJSON.origin and the
// authenticatorData.rpIdHash from the earlier snippet to verify.

async function rpIdHash(rpId) {
const enc = new TextEncoder().encode(rpId);
const hash = await crypto.subtle.digest("SHA-256", enc);
return Array.from(new Uint8Array(hash)).map(b => b.toString(16).padStart(2,'0')).join('');
}

(async () => {
const goodOrigin = "login.microsoftonline.example";
const badOrigin  = "login-microsoft0nline.example";
const goodRpId   = "login.microsoftonline.example";
const badRpId    = "login-microsoft0nline.example";
console.log("rpIdHash(", goodRpId, ") =", await rpIdHash(goodRpId));
console.log("rpIdHash(", badRpId,  ") =", await rpIdHash(badRpId));
// The two hashes differ in every byte. A passkey registered against
// login.microsoftonline.example cannot be induced to sign for the look-alike
// because the authenticator computes the second hash from clientDataJSON.origin
// and refuses to use the credential bound to the first one.

// Replay resistance illustration: a signCount of 0x10 followed by 0x0F
// is illegal (counter regressed). RPs reject this for BS=0 credentials.
const oldCount = 0x10, newCount = 0x0F;
console.log("signCount regression (BS=0)?", newCount <= oldCount ? "REJECT" : "ACCEPT");
})();

Press Run to execute.

9. Conditional UI: passkey autofill that looks like password autofill

The bridge between users' password-trained mental model and the new asymmetric-crypto reality is a UX primitive called Conditional Mediation -- the spec name -- or Conditional UI in informal use. The relying party renders a normal-looking username field. The browser sees that the page has called navigator.credentials.get({mediation: "conditional", publicKey: {...}}) and quietly offers the user's passkey as one of the autofill suggestions, alongside whatever the user has typed and whatever the password manager remembers. The user clicks the passkey suggestion, completes a Windows Hello gesture, and they are signed in. No popup. No modal. No "do you want to use a passkey?" dialog.

Conditional UI / Conditional Mediation

A WebAuthn invocation mode in which the browser offers the user's discoverable credentials inside the same autofill UI it uses for saved passwords, rather than via a modal credential picker. The relying party calls navigator.credentials.get({mediation: "conditional", publicKey: {...}}); the browser silently consults the platform authenticator (and, on Windows 11 24H2, the plug-in passkey providers) for credentials matching the rpId. The capability is probed via PublicKeyCredential.isConditionalMediationAvailable() [19].

The canonical engineer-perspective walkthrough is Adam Langley's Passkeys post on imperialviolet.org, dated 22 September 2022 [55]. Langley walks the flag-page invocation needed on early Chrome Canary builds -- chrome://flags#webauthn-conditional-ui -- and the capability surface: isUserVerifyingPlatformAuthenticatorAvailable() to decide whether to offer enrolment, isConditionalMediationAvailable() to decide whether to render the autofill hint at all. The post is the first time most working engineers saw what passkeys would actually look like at the page level.

On Windows the browser calls WebAuthNAuthenticatorGetAssertion with the Conditional mediation flag set; webauthn.dll consults its resident credential store, finds passkeys matching the rpId, and surfaces a small in-line affordance for each. The full-screen Windows Hello modal becomes a small in-place gesture acquisition. From the user's perspective the password-manager metaphor is unchanged; from the cryptography's perspective the work product is a public-key signature over an origin-bound challenge.

The L3 spec section 5.1.4 is the normative reference for the mediation modes [19]. The four modes are: silent (no user interaction), optional (browser decides), conditional (autofill), and required (modal). Conditional is the one that makes passkeys feel like passwords -- and that is precisely why it took the consumer-passkey rollout off the security-team conversation and into product reviews.

The Microsoft Learn passkey overview ties the UX to the Windows ship vehicle: "Starting in Windows 11, version 22H2 with KB5030310, Windows provides a native experience for passkey management" [53]. The Settings -> Accounts -> Passkeys page is the management UI; Conditional Mediation surfaces those passkeys at sign-in time. The passkeys.dev developer directory [56] is the FIDO Alliance's collected resource for relying parties implementing the flow.

The UX implication is the one Adam Langley underlined in the September 2022 post: the password-autofill metaphor is the load-bearing UX primitive that makes passkeys consumer-ready. The cryptography was solved in 2014. The UX took eight more years.

But what if the user's passkey lives in 1Password or Bitwarden, not in Windows itself?

10. The Windows 11 24H2 third-party passkey provider model

8 October 2024. Microsoft published the Windows Developer Blog post Passkeys on Windows: authenticate seamlessly with passkey providers [57] as a pre-conference announcement ahead of the FIDO Alliance's Authenticate 2024 conference (14-16 October 2024 in Carlsbad, California). The post announced three deliverables: "1. A plug-in model for third-party passkey providers. 2. Enhanced native UX for passkeys. 3. A Microsoft synced passkey provider." 1Password and Bitwarden were the named launch partners; Dashlane joined the roster shortly thereafter. The post says verbatim: "Microsoft is partnering closely with 1Password, Bitwarden and others on integrating this capability" [57].

The plug-in model is the first OS-level passkey-provider API on a major desktop platform. macOS Sonoma and iOS 17 had shipped a parallel design (ASCredentialIdentityStore plus ASCredentialProviderExtension) [58]; Android 14 had added Credential Manager support [59]; Windows 11 24H2 is the desktop OS that matches the mobile platforms. The mechanism is a COM interface called IPluginAuthenticator, declared in pluginauthenticator.idl [51]. A passkey-manager vendor ships a packaged Windows app that registers a COM object implementing the interface, supplies an AAGUID and a friendly name, and lets the OS dispatch ceremonies to it.

The Plugin API surface is six functions on the OS side and one COM interface on the vendor side. From webauthnplugin.h and the Microsoft Learn reference [37]:

  • WebAuthNPluginAddAuthenticator -- register the plug-in with the OS. The vendor app calls this on first run.
  • WebAuthNPluginAuthenticatorAddCredentials -- supply the OS with the credentials the plug-in currently has, so the OS can render them in pickers.
  • WebAuthNPluginAuthenticatorRemoveCredentials -- the inverse; remove credentials the plug-in no longer holds.
  • WebAuthNPluginPerformUserVerification -- request Windows Hello UV on behalf of the plug-in. The plug-in does not take the UV gesture itself; Windows Hello does, so the gesture-to-credential trust path is OS-mediated.
  • WebAuthNPluginRemoveAuthenticator -- the vendor's uninstall path.
  • WebAuthNPluginGetAuthenticatorList -- enumerate which plug-ins the OS knows about.

Three additional EXPERIMENTAL_*2 functions ship in Insider build KB5072046 and refine the registration, UV, and update flows. The list, verbatim from the github.com/microsoft/webauthn README: EXPERIMENTAL_WebAuthNPluginAddAuthenticator2, EXPERIMENTAL_WebAuthNPluginPerformUserVerification2, EXPERIMENTAL_WebAuthNPluginUpdateAuthenticatorDetails2 [51].

The Microsoft-authored reference implementation is the Contoso Passkey Manager sample in microsoft/Windows-classic-samples [60]. The sample's build manifest is explicit: "Windows SDK version 10.0.26100.7175 or higher. Operating system requirements: Windows 11 version 25H2. Build Major Version = 26200 and Minor Version >= 6725. Windows 11 version 24H2. Build Major Version = 26100 and Minor Version >= 6725" [60]. The Microsoft Learn tutorial Third-party passkey providers on Windows walks the same sample step by step [61].

Ctrl + scroll to zoom
Windows 11 24H2 plug-in architecture: browser to webauthn.dll to plug-in provider

The user-facing flow follows the same logic as the macOS / iOS / Android equivalents. The user installs 1Password or Bitwarden from the Microsoft Store. The vendor app calls WebAuthNPluginAddAuthenticator on first launch. The user enables the provider in Settings -> Accounts -> Passkeys -> Advanced options [57]. From that point on, when any browser or native app on Windows starts a WebAuthn ceremony, webauthn.dll presents the user with a picker -- "use a passkey from Windows Hello, from 1Password, from Bitwarden, from a hardware security key, or from your phone" -- and routes the ceremony to the selected provider. The plug-in itself returns an attestation object and an assertion; Windows Hello handles user verification on the plug-in's behalf via WebAuthNPluginPerformUserVerification. The Windows trust boundary still owns the gesture acquisition.

The criterion-table consequence is mixed. The plug-in model strengthens user choice and recovery, because a user with an existing 1Password / Bitwarden vault can reuse the recovery primitives they already know. It weakens verifier-compromise resistance relative to a pure platform-bound passkey, because the long-term key now lives in the vendor's vault rather than the TPM -- and the vendor's vault becomes another point of compromise. It does not change phishing resistance, replay resistance, or step-up, because those are properties of the WebAuthn ceremony and the plug-in still produces a WebAuthn-shaped assertion.

What 1Password, Bitwarden, and Dashlane each ship in their plug-in implementations follows the same template: registration requests get either a packed attestation statement (for vendor-signed batch attestation keys) or a none attestation (most consumer flows), and authentication assertions come back the same shape as any other WebAuthn assertion. The plug-in itself decides whether the credential is BE=1, BS=1 (synced in the vendor's cloud) or BE=0, BS=0 (device-bound to the local install).

A plug-in supplies the credential. But the attestation statement on registration tells the relying party what kind of credential it is. That's a separate API surface -- what shapes does it come in?

11. The seven attestation conveyance formats

The IANA WebAuthn registry lists seven format identifiers for the attestation statement a registration ceremony can produce [62]. The registry is reachable via RFC 8809 (Hodges, Mandyam, M.B. Jones, August 2020) [63] and the canonical normative definitions are in WebAuthn Level 2 §§8.2-8.8 [44], whose dated Recommendation is at REC-webauthn-2-20210408 [64]. The seven, in registry order: packed, tpm, android-key, android-safetynet, fido-u2f, apple, and none. Each is one option a relying party can require, accept, or ignore.

Attestation conveyance

The mechanism by which a WebAuthn registration ceremony optionally produces a signature over the new credential's public key (and authenticatorData containing the rpIdHash), chained to a vendor or platform root. The relying party validates the chain to establish that the new credential's private key is held by a specific authenticator model or certification level. Attestation is distinct from authentication; attestation runs once at registration, authentication runs every sign-in. The WebAuthn attestation parameter on registration controls whether the RP asks for an attestation statement at all (values: none, indirect, direct, enterprise).

The table below summarises what each format teaches the relying party.

FormatWhat the RP verifiesTrust anchor requiredCriterion strengthenedCurrent adoption
packedSignature over authenticatorData || clientDataHash by batch attestation key or self-attestation keyVendor X.509 cert chain or none (self)Verifier-compromise (model identity), optional anti-fraudDefault for most CTAP2 keys; dominant in production
tpmTPM 2.0 TPM2_Certify-style quote over the new credential public keyAIK / EK chain to TPM vendor rootVerifier-compromise + device-bound storageWindows platform-bound passkeys
android-keyAndroid Keystore attestation chainGoogle-rooted hardware-attestation CAVerifier-compromise + StrongBox / TEE residencyAndroid platform passkeys
android-safetynetSafetyNet API-derived attestation tokenGoogle SafetyNet CALegacy; decliningLegacy Android; SafetyNet deprecation announced June 2022; migration deadline end of January 2024; complete shutdown end of January 2025
fido-u2fECDSA P-256 signature with vendor X.509 certVendor U2F-era certVerifier-compromise (legacy)Legacy U2F-era hardware keys; declining
appleAnonymous Apple-issued attestation chainApple anonymous-attestation CAVerifier-compromise without device de-anonymisationApple platform passkeys
noneNo attestation; credential public key plus AAGUID onlyNoneNoneThe default for synced-passkey consumer flows

A few of these deserve a paragraph each.

packed is the spec default and the most widely deployed. The authenticator emits one signature over the concatenation of authenticatorData and a hash of clientDataJSON, using one of three keys: (a) a per-authenticator-model batch attestation key whose X.509 chain anchors to the vendor's attestation root (the privacy-vs-anti-fraud trade-off -- the cert reveals the device model, but not which specific user owns which device); (b) an Anonymisation CA or Enterprise Attestation key, which lets a managed enterprise distinguish its own devices without leaking that information to consumer relying parties; or (c) a self-attestation key derived from the credential itself, which proves only that the private key signs and makes no identity claim.

tpm is the format the Windows platform authenticator emits when the user has a TPM 2.0. The signing object is a TPM TPM2_Quote-style structure with the TPM's Attestation Identity Key (AIK), chained back to the TPM vendor's Endorsement Key (EK) root certificate. This is the most cryptographically opinionated attestation in the registry: it proves the credential is held by a specific TPM vendor's part. The Windows TPM article in this series walks the AIK / EK chain end to end.

apple is Apple's anonymous-attestation design. The X.509 chain ends in an Apple anonymous-attestation CA; cryptographically the relying party can verify the cert chain back to Apple's root, but the cert itself is engineered to not reveal the user's specific device. This is the privacy-vs-anti-fraud trade-off resolved in favour of privacy: a relying party gets "this came from a real Apple device" without learning which Apple device.

android-safetynet is the legacy format that lots of installed-base Android passkeys still use. Google announced the SafetyNet Attestation API's deprecation in June 2022 in favour of Play Integrity; the migration deadline was extended to end of January 2024, with complete shutdown landing end of January 2025 [65]. Any new Android passkey registered in 2025 or later uses android-key or none instead. Relying parties with old android-safetynet credentials in their database must accept both formats during the transition window; new credentials use the new path.

fido-u2f is the U2F-era legacy format, descended directly from the December 2014 U2F design [30]. ECDSA P-256 signing key plus a vendor X.509 cert. Modern keys still emit it for U2F-mode CTAP1 ceremonies, but every modern CTAP2 ceremony uses packed instead.

none is the most-deployed format in consumer flows -- and the recommended default for any relying party that does not have a specific anti-fraud requirement. The RP asks for attestation: "none"; the authenticator returns just the credential public key and the AAGUID, with no signature chain. The privacy benefit is real: attestation deanonymises the user's device by model, and a relying party that does not need that information should not collect it. The 2024-2026 best practice is attestation: "none" for consumer passkey flows. NIST SP 800-63B-4 (final) inherits this caution [4].

All seven formats assume the authenticator is on the same device as the browser. What happens when it isn't?

12. Hybrid transport: a phone authenticator for a laptop browser

A user on a borrowed Windows laptop with no Windows passkey signs in to their bank by scanning a QR code with their iPhone. The phone is the authenticator. The laptop is the WebAuthn client. The protocol that ties them together is hybrid transport, formerly known as caBLE (Cloud-Assisted Bluetooth Low Energy), standardised in W3C WebAuthn Level 3 §6.3.3 [19].

Hybrid transport (caBLE)

A WebAuthn transport in which a roaming authenticator (typically a mobile phone) cooperates with a WebAuthn client on a nearby device (typically a laptop) via three concurrent channels: an out-of-band channel (QR code) for one-time setup, BLE for proximity, and HTTPS to a discoverable cloud tunnel relay for the actual ceremony bytes. The cryptographic binding is an ephemeral ECDH key exchanged through the QR code; the BLE proves proximity, not identity; the tunnel relay carries the encrypted ceremony [18].

The ceremony, simplified: the laptop's browser asks the user to use a phone, generates an ephemeral ECDH keypair, and renders a QR code containing the Tunnel Service URL the phone should connect to, the laptop's ephemeral public key, and a derived HMAC key. The phone's camera scans the QR code and derives a shared secret with the laptop via ECDH. The phone then advertises its presence over BLE, the laptop listens for the BLE beacon to confirm physical proximity, and both endpoints connect to the Tunnel Service URL over HTTPS. From that point on, the laptop and the phone exchange CTAP2 ceremony messages, encrypted under the ECDH-derived key, through the tunnel relay. The phone produces a WebAuthn assertion locally using whatever authenticator is on the phone (the Secure Enclave on iPhone, the Android Keystore on Android), encrypts it for the laptop, and the laptop forwards it to the relying party.

Ctrl + scroll to zoom
Hybrid transport (caBLE) at the message level

The criterion-table consequence is precise. Phishing resistance is preserved because the origin in clientDataJSON is the laptop's actual browser origin, which the phone signs over the same way it would for its own browser. The QR code is the cryptographic binding, not the BLE advertisement; the BLE advertisement is a proximity signal that proves the phone is physically near the laptop, but it does not authenticate the phone. The Tunnel Service is a relay, not a trust anchor; even if the tunnel were compromised, the encrypted ceremony bytes would be unreadable without the ECDH-derived key.

The design is attributed in the WebAuthn L3 spec to the W3C WebAuthn-3 editor masthead -- Jeff Hodges, J.C. Jones, Michael B. Jones, Akshay Kumar, and Emil Lundberg as current editors, with Dirk Balfanz as a previous editor [66]. The original caBLE design and the L3 §6.3.3 productisation were led by Google's Chrome security and Android Identity teams; the canonical reference is W3C WebAuthn Level 3 §6.3.3 itself.

Hybrid transport is the only competitor to the Windows platform authenticator that involves no Windows-side credential storage. The Windows laptop holds nothing -- no key, no recovery state, no cached credential. Every ceremony round-trips to the phone. This is the use case the bank-on-a-borrowed-laptop story illustrates: you can sign in to your accounts on a machine you do not own without leaving a credential behind.

How do other authentication approaches score on the criteria framework?

13. Competing approaches scored against the criteria

The criteria-framework table makes the competitive field legible. Five rows, six competing columns: password alone, password plus SMS-OTP, password plus TOTP, password plus push with number matching, smart card / PIV, and device-bound or synced passkey. The NIST SP 800-63B-4 AAL grading [4] and the NIST syncable-authenticator supplement [49] anchor the right edge of the table; Yubico's commentary corroborates the dichotomy between device-bound (AAL3) and synced (AAL2) passkeys [8].

CriterionPasswordPassword + SMS-OTPPassword + TOTPPassword + Push (number match)Smart Card / PIVDevice-bound passkeySynced passkey
Phishing resistanceNoneNone (AitM relays the OTP)None (AitM relays the TOTP)Partial (number match defeats most kits)Strong (origin-bound via TLS client auth)Strong (rpId binding)Strong
Verifier-compromise resistanceNoneNone (SMS infra leaks)Partial (TOTP seed on server)PartialStrong (public-key only)StrongStrong
Replay / relay resistanceNoneWeak (OTP relay in 30-60 s)Weak (TOTP relay in 30 s)Strong (number match per challenge)Strong (per-handshake nonce)Strong (challenge + counter)Strong
Step-up / continuityNoneNoneNonePartialStrong (PIN re-prompt)Strong (UV=1)Strong
Recovery floorReset via SMSSMS-OTP all the way downTOTP seed reset via SMSSMS / passwordAdmin re-issueRP-dependent backup keySync-fabric recovery (Recovery Key + Recovery Contact)
NIST AAL ceilingAAL1AAL2 nominal (SMS-OTP deprecated since 800-63-3 in 2017)AAL2AAL2AAL3AAL3AAL2

Push MFA needs a paragraph of nuance. Vanilla push -- "tap to approve" -- is phishable by default because the attacker can simply trigger the push at the moment they have the password, and a fatigued user taps. Number matching (the user types a code shown on the laptop into the phone, or vice versa) defeats most kits because it ties the push to a specific session. Location binding (the push is rejected unless the phone is geographically near the laptop) adds another layer. The net is "partial" phishing resistance -- much better than vanilla push, not as strong as origin binding.

Smart cards and PIV deserve their own paragraph because they are not historically associated with WebAuthn but score well on the criteria. A PIV card with a PIN provides strong phishing resistance via TLS client authentication (origin-bound at the TLS layer), strong verifier-compromise resistance via the public-key model, and strong replay resistance via per-handshake nonces. The weakness is recovery: a lost card requires an administrative reissue, which scales poorly for consumer flows. The companion App Identity in Windows article in this series walks the Windows smart-card stack end to end.

OATH-TOTP is interesting in the criteria table because it is phishing-vulnerable by construction. The TOTP code is the same on the legitimate origin and the look-alike; the AitM kit forwards the code through. Google Authenticator's cloud-sync feature additionally broke the verifier-compromise property in a subtle way: if the user's Google account is compromised, the synced TOTP seeds give the attacker a complete second-factor toolkit [67].

SAML and OIDC federation are not competitors to WebAuthn in the criteria table -- they are transport layers above WebAuthn. A SAML or OIDC identity provider does the WebAuthn ceremony for the user; the IdP then issues a SAML assertion or an OIDC ID token to the relying party. WebAuthn underneath is the strong primitive; SAML and OIDC are the enterprise transport for the resulting assertions.

WebAuthn wins decisively on four of five rows. What's left in row five? The recovery row.

14. Theoretical limits: the corners WebAuthn cannot reach

Even with everything from §§4-12 in place, WebAuthn has corners it cannot defend. The relevant impossibility results are well-known in the protocol literature; they are worth naming because they tell a practitioner where defence-in-depth has to come from.

Kernel-level malware on the client. Malware with kernel privilege on the user's device can race the legitimate user. If the malware can call into webauthn.dll and trigger a Hello UV prompt the user blindly approves, it can extract assertions. The mitigation is TPM-bound keys plus the Hello ESS trustlet (covered in the companion Windows Hello and Credential Guard articles), not WebAuthn itself. WebAuthn protects against network attackers; defending against a kernel-mode attacker on the same device requires the OS's secure-kernel architecture.

Sync-fabric compromise. Compromise of Apple iCloud, Google account recovery, or Microsoft's recovery-key service effectively compromises every passkey held there. Apple's Advanced Data Protection model [48] is the strongest currently-shipped consumer realisation of the end-to-end-encrypted sync invariant, and even it depends on the user retaining their Recovery Contact or Recovery Key in some form. The NIST April 2024 supplement classifies synced passkeys at AAL2 for exactly this reason: the private key leaves the original authenticator [49]. Yubico's commentary makes the practitioner consequence explicit: device-bound is AAL3, synced is AAL2 [8].

Username enumeration and discoverable-credential privacy. Discoverable credentials let an authenticator answer "do you have a credential for this rpId?" without further information. A relying party that asks the question maliciously can enumerate which of its users have set up a passkey. The credProtect extension introduced in CTAP 2.1 [39] requires UV=1 to even list the credential, which closes most of the leak; it is not universally deployed.

Counter-regression false positives on synced passkeys. The per-credential signature counter is per-authenticator. A passkey synced across two devices will see the counter desynchronise between them. WebAuthn L3 §6.1.1 explicitly permits a zero-counter for synced passkeys; relying parties that treat any counter regression as evidence of cloning will produce false positives. Treat counter regression as evidence of cloning only for BS=0 (device-bound) credentials. This is a deployment foot-gun, not a protocol flaw.

Ctrl + scroll to zoom
Which WebAuthn feature strengthens which criterion-table cell

These are the protocol limits. The biggest practical limit is one the protocol cannot fix at all -- recovery. The protocol can specify what factor produces the credential at sign-in; it cannot specify what factor produces the credential when the original one is lost. That is the application-layer question every relying party answers differently, and it is the question §17 will land on.

15. Open problems: what's still moving in late 2025 / early 2026

Standardisation is not done. Several major surfaces are still in active draft.

WebAuthn Level 3 is currently a W3C Candidate Recommendation [19]; the dated CR snapshot is 13 January 2026 [18]. The expected progression is Candidate Recommendation to Proposed Recommendation to Recommendation through 2026, with no major spec-breaking changes expected at this point in the process. The active editor masthead is Hodges, J.C. Jones, M.B. Jones, Kumar, and Lundberg [66].

CTAP 2.2 is a FIDO Proposed Standard as of 14 July 2025 [40]; CTAP 2.3 is also listed at FIDO's specifications download page [41]. The 2.2 and 2.3 revisions refine hybrid transport, credProtect, and PIN-protocol handling without breaking 2.1's command-byte table.

Cross-vendor passkey portability. The FIDO Alliance Credential Exchange Protocol (CXP) and Credential Exchange Format (CXF) Working Drafts, dated 3 October 2024 [68], are the standards effort. The draft text identifies the problem: "the transfer of credentials between two different providers has traditionally been an infrequent occurrence... As it becomes more common for users to have multiple credential providers that they use to create and manage credentials, it becomes important to address some of the security concerns with regard to migration" [68]. Apple has signalled CXP-based import for iOS; Bitwarden has signalled support. The likely 2026 trajectory is CXP becoming a Proposed Standard and Windows / Android / iOS implementing it as the OS-level import-export passkeys surface.

Transactional authorisation. The earliest WebAuthn drafts included txAuthSimple and txAuthGeneric extensions [17]; neither was ever implemented by browsers, and both are absent from L3. The productised path is Secure Payment Confirmation (a sibling spec to WebAuthn), but it covers only payment transactions. General "sign a description of this transaction" remains an open problem. Conjecture: payment-confirmation becomes the template that gets generalised in WebAuthn Level 4.

Quantum-safe attestation. The IANA COSE algorithm registry (last updated 2026-03-04) currently has no PQC algorithm in WebAuthn-recommended status [38]. ECDSA P-256, EdDSA Ed25519, RSA-PKCS1.5, and RSA-PSS are the registered options, all quantum-breakable in principle. A long-lived TPM AIK signed today is forgeable to a quantum-capable adversary at any future date. The companion Post-Quantum Cryptography on Windows article in this series walks the algorithm-side rollout; the WebAuthn deployment side is open. The most plausible trajectory is ML-DSA (FIPS 204) entering the WebAuthn COSE registry by 2027 and existing TPM AIKs receiving a parallel ML-DSA enrolment.

Standards are still moving. What should a practitioner do today?

16. Practical guide: what to do this week

Six pieces of operational advice, each tied to a primary source.

1. Windows developers: use webauthn.dll, do not roll your own. The Win32 reference at learn.microsoft.com/en-us/windows/win32/api/webauthn/ [52] is the only surface you should be calling. The OS handles USB-HID, NFC, BLE, hybrid transport, Conditional Mediation, plug-in dispatch, and Windows Hello UV in one call. The header is at github.com/microsoft/webauthn [51]; the Microsoft Learn overview is at learn.microsoft.com/.../hello-for-business/webauthn-apis [37].

2. Relying parties: default to attestation: "none", userVerification: "required", residentKey: "preferred". This is the 2024-2026 consumer-flow baseline. attestation: "none" preserves user privacy and interoperates with every authenticator type. userVerification: "required" forces UV=1 and the gesture acquisition. residentKey: "preferred" enables usernameless sign-in on platforms that support it without burning a credential slot on older authenticators that don't. The Microsoft Entra passwordless documentation [2] and the WebAuthn Level 3 spec [19] are the references.

3. Enterprise IT: device-bound FIDO2 keys for AAL3 (admin, finance, tier 0); synced passkeys for AAL2 workforce. NIST SP 800-63B-4 [4] formalises the dichotomy via the syncable-authenticator supplement [49]. Yubico's enterprise commentary makes the operational point: device-bound passkeys on dedicated hardware are AAL3; synced passkeys are AAL2 [8]. For admin accounts use FIDO Alliance L3-certified hardware [5] -- YubiKey Bio, Feitian BioPass, the Entra-listed vendors at learn.microsoft.com/.../concept-fido2-hardware-vendor [36].

4. Windows 11 24H2 end users: enable third-party passkey providers in Settings. Settings -> Accounts -> Passkeys -> Advanced options. Toggle the provider on for any vendor you trust (1Password, Bitwarden, Dashlane) [57]. The Microsoft Learn third-party tutorial walks the flow [61]. If you do not use a third-party vault, the Microsoft synced passkey provider is enabled by default on 24H2 systems signed in with a Microsoft Account.

5. Security architects: write down your recovery flow first. Score it against the five-axis criteria table from §2 before you design the authentication factors. The recovery row's strength is the system's ceiling, not the floor; the authentication ceremony cannot raise it. Microsoft Entra's own guidance flags account recovery as a deployment risk: FIDO2 keys "can increase costs for equipment, training, and helpdesk support -- especially when users lose their physical keys and need account recovery" [2]. §17 lands this argument.

6. Incident responders: collect ETW events from the WebAuthn provider. Plug-in authenticator registration events on managed devices are a high-signal indicator -- a newly enrolled IPluginAuthenticator on a privileged user's machine should be treated as a credential-store change requiring review. The companion ETW on Windows article in this series walks the WebAuthn provider events end to end.

A one-line PowerShell to enumerate Windows passkeys

Open PowerShell as the signed-in user (no admin needed for your own credentials) and call into the webauthn.dll WebAuthNGetPlatformCredentialList API via a managed wrapper, or use the Settings -> Accounts -> Passkeys page directly. There is no first-class Get-WebAuthnCredential cmdlet as of Windows 11 25H2; the Settings page is the supported management surface. The Microsoft Learn passkey overview is the canonical reference [53].

Most of this is engineering. One row of the table has resisted engineering for fifty years. That's where the article lands.

17. Recovery: your weakest factor is always your recovery flow

The thesis surfaced in §2 and deferred through twelve sections is the one the article lands on. The argument is direct, almost embarrassingly so: every authentication system that admits any external recovery primitive is, in the formal sense, at most as strong as that primitive. Strong authentication ceremonies coexist with weaker recovery ceremonies in every consumer platform in production, and the system's assurance level is the minimum of the two, not the maximum.

Your weakest factor is always your recovery flow.

To make the claim concrete, score every major platform's recovery flow against the same five-axis criteria table.

Apple iCloud Keychain (with Advanced Data Protection). Apple's published model has three recovery primitives [48]: (a) a trusted device the user previously signed into; (b) an iCloud Recovery Contact -- another Apple ID owner the user has nominated to attest their identity; and (c) an iCloud Recovery Key -- a 28-character string the user must retain [69]. Apple's published architecture is the strongest current consumer realisation of the end-to-end-encrypted invariant: the recovery primitives unlock an HSM-backed escrow cluster that holds the user's iCloud Keychain encryption material, but Apple itself does not hold the keys in plaintext. The fundamental dependency is the Apple ID password plus, originally, SMS-OTP at device-trust establishment.

Google Password Manager (with Google Account end-to-end encrypted passkey sync). Trusted-device fallback, security-key fallback, recovery code, recovery phone, recovery email. The recovery floor reduces, in the worst case, to SMS-OTP via the recovery phone. Google's architecture is end-to-end encrypted in the steady state but the trust establishment depends on Google account recovery, which depends on out-of-band verification primitives the user enrolled at account creation.

Microsoft Account. The October 2024 Windows Developer Blog states the recovery primitive verbatim: "you will be prompted to save a recovery key that will be used to verify your identity and protect your passkeys through end-to-end encryption" [57]. The recovery key is a high-entropy string the user retains; if they lose it, the recovery flow falls back to the secondary factors the user enrolled (alternate email or SMS-OTP via the recovery phone). As with Google, the worst-case recovery floor is the weakest of the secondary factors the user enrolled.

Microsoft Entra ID (enterprise). Entra's Temporary Access Pass (TAP) is the strongest enterprise recovery primitive currently shipped: an administrator issues a time-bound passwordless TAP that the user redeems to bootstrap a new authenticator. TAP is stronger than consumer flows because of accountability -- the admin's identity is on the issuance -- but weaker than the authentication ceremony itself because the admin is socially engineerable. Microsoft documents the TAP issuance and redemption flow in detail [70].

1Password, Bitwarden, Dashlane under the 24H2 plug-in model. Each vendor's master password and secondary recovery primitive becomes the de facto floor of the entire passkey ceremony when the plug-in is the credential store. 1Password's master password plus Secret Key, Bitwarden's master password plus 2FA recovery code, and Dashlane's device trust plus master password -- each is the recovery floor for every passkey the vault holds. The Microsoft Learn third-party tutorial reinforces the warning, in context: "Contoso Passkey Manager is designed for passkey creation and usage testing only. Don't use the app for production passkeys" [61].

Ctrl + scroll to zoom
Every major passkey platform's recovery flow ends at a weaker primitive

The diagram looks busy because it is. Every major platform's recovery flow is a different combination of trusted-device fallback, recovery code or key, recovery contact, and an out-of-band primitive (SMS-OTP, email, or admin attestation). Every one of those out-of-band primitives is weaker than origin-bound public-key cryptography. The cryptographic ceremony scores AAL3 phishing-resistant at the authentication moment; the recovery primitive scores AAL1 or AAL2 at the recovery moment. The system's AAL is the minimum.

Every passkey platform in production in 2026 -- Apple, Google, Microsoft, Entra, 1Password, Dashlane, Bitwarden -- bottoms out, in its recovery flow, in some combination of trusted-device fallback and SMS-OTP-equivalent shared knowledge. That floor is the AAL ceiling for the entire system.

The protocol literature has been clear about this for fifty years and the regulatory literature has been catching up since 2017. NIST SP 800-63-3 introduced "phishing-resistant authenticator" as a first-class term; SP 800-63-4 (2025) [3] makes verifier-impersonation resistance a normative criterion. Neither standard solves recovery; both standards explicitly enumerate what counts as a recovery primitive without specifying how to compose them into an AAL-graded flow. There is no IETF or FIDO Alliance standard that says "here is a recovery flow whose strength is AAL3." There may never be -- recovery is application-specific, and the only general protocol is "social attestation" (multiple human witnesses), which does not scale.

The same WebAuthn ceremony that scores AAL3 phishing-resistant at the authentication moment can be a single-factor SMS-OTP at the recovery moment. Your weakest factor is always your recovery flow. That is the line. It is the line every working security architect should write down, score against, and design recovery against -- before designing the authentication factors.

18. FAQ

Common questions about WebAuthn and passkeys on Windows

Are passkeys just passwords with a fancy name?

No. A password is a shared secret -- the user types a string, the server stores a hash of the same string, and an eavesdropper who captures the string in flight or compromises the server's database has a credential they can replay. A passkey is one half of an asymmetric keypair: the private key lives in the authenticator (TPM, secure enclave, hardware key, or end-to-end-encrypted sync fabric), and only its public key reaches the server. An eavesdropper who captures a passkey ceremony in flight has nothing they can replay; a server-database leak yields public keys that authenticate no one. WebAuthn Level 3 [19] and the Microsoft Entra "origin-bound public key cryptography" framing [2] are the references.

Are synced passkeys insecure?

Insecure relative to device-bound; secure relative to passwords. The NIST syncable-authenticator supplement (April 2024) [49] and SP 800-63B-4 (July 2025) [4] cap synced passkeys at AAL2, because the long-term private key has left the original authenticator. Device-bound passkeys on dedicated hardware -- "FIDO passkeys that are not synced ... and are properly stored in dedicated hardware have an AAL3 rating" [8] -- can reach AAL3. The right answer is to use device-bound keys for tier-zero accounts and synced passkeys for the bulk of consumer flows.

Is Windows Hello a biometric system?

Hello uses biometrics but provides the user-verification gesture for WebAuthn; the credential itself is asymmetric and lives in the TPM. Microsoft Learn states the property verbatim: "The private keys can only be used after they're unlocked by the user using the Windows Hello unlock factor (biometrics or PIN)" [53]. The biometric is one mode of the Hello UV gesture, not the credential. If you disable face or fingerprint, your PIN still unlocks the passkey.

Should relying parties always require attestation?

No. Attestation is privacy-leaking for synced passkeys; attestation: "none" is the 2024-2026 default for consumer flows. Use attestation: "direct" only when you have a documented anti-fraud requirement and can verify the chain against the FIDO Metadata Service. Use attestation: "enterprise" only inside a managed enterprise where the user's device is corporately enrolled. The relevant references are WebAuthn Level 2 §§8.2-8.8 [44] and the IANA WebAuthn registry [62].

Does hybrid transport work because of Bluetooth proximity?

No. The cryptographic binding is the QR-code-encoded ephemeral ECDH key. Bluetooth is a transport and a proximity signal; it is not a trust anchor. The QR code transfers the laptop's ephemeral public key plus a derived HMAC seed; the phone derives the shared secret via ECDH; the BLE advertisement merely proves the phone is physically close to the laptop. The encrypted CTAP2 ceremony bytes travel over HTTPS through a discoverable tunnel relay. WebAuthn Level 3 §6.3.3 is the normative description [19].

Does disabling Windows Hello disable passkeys?

No. A Windows passkey can be used with PIN-only user verification; the biometric is one mode of the Hello UV gesture, not the credential. The credential is in the TPM, indexed under your Microsoft Account container, and the PIN is one valid unlock factor. If you use a third-party passkey provider via the 24H2 plug-in model, that provider may use its own master password as the UV gesture; the OS still mediates the gesture acquisition through WebAuthNPluginPerformUserVerification [37].

Can Microsoft, Apple, or Google see my private keys?

Microsoft cannot see your TPM-sealed Windows Hello private key; the TPM does not expose the raw key material to the OS, let alone to Microsoft. Apple's iCloud Keychain with Advanced Data Protection [48] and Google's end-to-end-encrypted passkey sync mean the sync provider cannot see the plaintext keys either. But the recovery path can still expose them under specific conditions: an attacker who compromises your recovery contact, recovery key, or your account's out-of-band recovery primitives (SMS-OTP, recovery email) effectively defeats the end-to-end encryption invariant. The plaintext keys are not what gets exfiltrated; the recovery primitives are.

This article is one of a series on Windows authentication primitives. NTLMless: The Death of NTLM in Windows (2026-05-10) covers the legacy authentication protocol passkeys are displacing. Windows Hello, Demystified covers the user-verification gesture WebAuthn leans on. Adminless: Administrator Protection in Windows (2026-05-10) and App Identity in Windows (2026-05-08) cover the privilege-escalation and code-identity primitives that surround the authentication stack. The companion Kerberos on Windows (2026-05-11) covers the enterprise transport for the resulting assertions; ETW on Windows (2026-05-11) covers the telemetry surface for incident responders.

The Windows passkey stack is the productisation moment for a forty-year-old protocol-literature insight: authentication should be tied to something the network attacker cannot change. WebAuthn ties it to the origin in clientDataJSON, signed by a credential whose private key never reaches the wire. Windows 10 1903 made it a Win32 surface; Windows 11 24H2 made it a plug-in surface; Authenticate 2024 made it a default. The protocol bytes are FIDO2; the consumer experience is autofill. The Windows part is the dispatcher between them.

The criteria framework is the diagnostic kit. Use it on every authentication system you ship. Score it against five axes, not three. Write down the recovery flow first. Match the authentication ceremony to the recovery flow you can actually defend. And remember the line: your weakest factor is always your recovery flow.

Study guide

Key terms

Phishing-resistant authenticator
An authenticator whose protocol prevents a relying party impersonator from inducing the authenticator to release a usable credential value. NIST SP 800-63B-4 calls this verifier-impersonation resistance.
Origin binding
The mechanism by which WebAuthn enforces phishing resistance: the browser writes the origin into clientDataJSON; the authenticator signs over the SHA-256 hash of the canonical rpId; the RP rejects any signature whose rpIdHash does not match the registered rpId.
rpId
A string identifying the WebAuthn relying party for credential scoping. Must be a registrable suffix of the page's origin. All WebAuthn signatures are made over its SHA-256 hash.
CTAP 2.x
The Client-to-Authenticator Protocol: the wire format browser to roaming authenticator over USB-HID, NFC, or BLE. CTAP1 is APDU-based; CTAP2 is CBOR-based. Modern keys speak CTAP 2.1 (June 2021) or 2.2 (July 2025).
Discoverable credential (resident key, passkey)
A WebAuthn credential whose account metadata is stored on the authenticator, enabling usernameless sign-in. CTAP 2.0 called these resident keys; the May 2022 vendor commitment branded them passkeys.
Attestation conveyance
The mechanism by which a registration ceremony optionally produces a signature over the credential public key, chained to a vendor or platform root. Seven IANA-registered formats: packed, tpm, android-key, android-safetynet, fido-u2f, apple, none.
Hybrid transport (caBLE)
A WebAuthn transport in which a phone acts as a roaming authenticator for a nearby laptop. QR code carries an ephemeral ECDH key; BLE proves proximity; HTTPS tunnel relay carries encrypted CTAP2 bytes.
AAGUID
A 16-byte Authenticator Attestation GUID identifying the authenticator make and model. Some authenticators emit all-zeros for privacy; the FIDO Metadata Service is the authoritative directory.
Conditional UI / Conditional Mediation
A WebAuthn invocation mode in which the browser offers discoverable credentials inside the autofill UI rather than via a modal picker. RP calls navigator.credentials.get with mediation: 'conditional'.
BE / BS flags
Backup Eligible and Backup State bits in authenticatorData. BE=1 means the credential is in principle syncable; BS=1 means it is currently backed up. NIST SP 800-63B-4 caps BS=1 credentials at AAL2.
AAL1 / AAL2 / AAL3
NIST SP 800-63B-4 authentication assurance levels. AAL1 is single-factor; AAL2 is multi-factor or phishing-resistant; AAL3 is hardware-bound non-syncable authentication.

References

  1. (2024). Tycoon 2FA: an in-depth analysis of the latest version of the AiTM phishing kit. Sekoia.io. https://blog.sekoia.io/tycoon-2fa-an-in-depth-analysis-of-the-latest-version-of-the-aitm-phishing-kit/
  2. Passwordless authentication options for Microsoft Entra ID. Microsoft Learn. https://learn.microsoft.com/en-us/entra/identity/authentication/concept-authentication-passwordless
  3. Proud-Madruga, Choong, Galluzzo, Gupta, LaSalle, Lefkovitz, & Regenscheid (2025). NIST SP 800-63-4: Digital Identity Guidelines (final, July 2025). NIST. https://pages.nist.gov/800-63-4/ - Live canonical HTML landing page (the csrc.nist.gov/pubs/sp/800/63/4/final URL and the nvlpubs PDF mirror both return HTTP 404 as of 2026-05-12).
  4. (2025). NIST SP 800-63B-4: Authentication and Authenticator Management (HTML). NIST. https://pages.nist.gov/800-63-4/sp800-63b.html
  5. FIDO Authenticator Certification Levels (L1, L1+, L2, L3, L3+). FIDO Alliance. https://fidoalliance.org/certification/authenticator-certification-levels/
  6. Nicolas Williams (2007). RFC 5056: On the Use of Channel Bindings to Secure Channels. IETF. https://datatracker.ietf.org/doc/html/rfc5056
  7. Sam Whited (2022). RFC 9266: Channel Bindings for TLS 1.3. IETF. https://datatracker.ietf.org/doc/html/rfc9266
  8. New NIST Guidance on Passkeys: Key Takeaways for Enterprises. Yubico. https://www.yubico.com/blog/new-nist-guidance-on-passkeys-key-takeaways-for-enterprises/
  9. Robert Morris & Ken Thompson (1979). Password Security: A Case History. Communications of the ACM 22(11), 594-597. https://en.wikipedia.org/wiki/Robert_Morris_(cryptographer)
  10. M'Raihi, Bellare, Hoornaert, Naccache, & Ranen (2005). RFC 4226: HOTP -- An HMAC-Based One-Time Password Algorithm. IETF. https://datatracker.ietf.org/doc/html/rfc4226
  11. M'Raihi, Machani, Pei, & Rydell (2011). RFC 6238: TOTP -- Time-Based One-Time Password Algorithm. IETF. https://datatracker.ietf.org/doc/html/rfc6238
  12. Popov, Nystroem, Balfanz, & Hodges (2018). RFC 8471: The Token Binding Protocol Version 1.0. IETF. https://datatracker.ietf.org/doc/html/rfc8471
  13. Popov, Nystroem, Balfanz, Harper, & Hodges (2018). RFC 8473: Token Binding over HTTP. IETF. https://datatracker.ietf.org/doc/html/rfc8473
  14. RFC 8471 datatracker history page. IETF. https://datatracker.ietf.org/doc/rfc8471/history/ - History shows no Historic reclassification event; RFC remains Proposed Standard.
  15. RFC 8473 datatracker history page. IETF. https://auth.ietf.org/doc/rfc8473/history/
  16. Token Binding (Wikipedia). Wikipedia. https://en.wikipedia.org/wiki/Token_Binding
  17. (2016). Web Authentication: An API for accessing Scoped Credentials (W3C First Public Working Draft, 31 May 2016). W3C. https://www.w3.org/TR/2016/WD-webauthn-20160531/
  18. (2026). Web Authentication Level 3 (Candidate Recommendation dated snapshot, 13 January 2026). W3C. https://www.w3.org/TR/2026/CR-webauthn-3-20260113/
  19. Web Authentication: An API for accessing Public Key Credentials -- Level 3 (W3C Candidate Recommendation). W3C. https://www.w3.org/TR/webauthn-3/
  20. Trusted Computer System Evaluation Criteria (Orange Book, Wikipedia). Wikipedia. https://en.wikipedia.org/wiki/Trusted_Computer_System_Evaluation_Criteria
  21. William E. Burr, Donna Dodson, & W. Timothy Polk (2004). NIST Special Publication 800-63 (first edition): Electronic Authentication Guideline. NIST CSRC. https://csrc.nist.gov/pubs/sp/800/63/final
  22. (2004). NIST SP 800-63 version 1.0.2 (PDF). NIST. https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-63ver1.0.2.pdf
  23. RSA SecurID (Wikipedia). Wikipedia. https://en.wikipedia.org/wiki/RSA_SecurID
  24. (2017). NIST SP 800-63-3: Digital Identity Guidelines. NIST CSRC. https://csrc.nist.gov/pubs/sp/800/63/3/upd2/final
  25. Neil Haller (1995). RFC 1760: The S/KEY One-Time Password System. IETF. https://datatracker.ietf.org/doc/html/rfc1760
  26. Kim Cameron (2005). The Laws of Identity. identityblog.com. https://www.identityblog.com/?p=352
  27. (2013). FIDO Alliance Launch Announcement (PDF), 12 February 2013. FIDO Alliance. https://fidoalliance.org/assets/downloads/FIDO_Alliance_launch__FINAL__02_12_13docx.pdf
  28. FIDO Alliance (Wikipedia). Wikipedia. https://en.wikipedia.org/wiki/FIDO_Alliance
  29. Mozilla Persona (Wikipedia). Wikipedia. https://en.wikipedia.org/wiki/Mozilla_Persona
  30. FIDO U2F Overview (specs archive). FIDO Alliance. https://fidoalliance.org/specs/u2f-specs-master/fido-u2f-overview.html
  31. Universal 2nd Factor (Wikipedia). Wikipedia. https://en.wikipedia.org/wiki/Universal_2nd_Factor
  32. Juan Lang, Alexei Czeskis, Dirk Balfanz, Marius Schilder, & Sampath Srinivas (2016). Security Keys: Practical Cryptographic Second Factors for the Modern Web. Financial Cryptography 2016. https://fc16.ifca.ai/preproceedings/25_Lang.pdf
  33. (2019). W3C and FIDO Alliance Finalize Web Standard for Secure, Passwordless Logins. W3C. https://www.w3.org/press-releases/2019/webauthn/
  34. (2019). Web Authentication: An API for accessing Public Key Credentials -- Level 1 (W3C Recommendation, 4 March 2019). W3C. https://www.w3.org/TR/2019/REC-webauthn-1-20190304/
  35. (2019). FIDO Client to Authenticator Protocol (CTAP) 2.0 Proposed Standard, 30 January 2019. FIDO Alliance. https://fidoalliance.org/specs/fido-v2.0-ps-20190130/fido-client-to-authenticator-protocol-v2.0-ps-20190130.html
  36. FIDO2 security key hardware vendors for Microsoft Entra ID. Microsoft Learn. https://learn.microsoft.com/en-us/entra/identity/authentication/concept-fido2-hardware-vendor
  37. WebAuthn APIs for password-less authentication on Windows. Microsoft Learn. https://learn.microsoft.com/en-us/windows/security/identity-protection/hello-for-business/webauthn-apis
  38. CBOR Object Signing and Encryption (COSE) Algorithms (IANA registry). IANA. https://www.iana.org/assignments/cose/cose.xhtml
  39. (2021). FIDO Client to Authenticator Protocol (CTAP) 2.1 Proposed Standard, 15 June 2021. FIDO Alliance. https://fidoalliance.org/specs/fido-v2.1-ps-20210615/fido-client-to-authenticator-protocol-v2.1-ps-20210615.html
  40. (2025). FIDO CTAP 2.2 Proposed Standard, 14 July 2025. FIDO Alliance. https://fidoalliance.org/specs/fido-v2.2-ps-20250714/fido-client-to-authenticator-protocol-v2.2-ps-20250714.html
  41. FIDO Alliance Specifications Download Page. FIDO Alliance. https://fidoalliance.org/specifications/download/
  42. (2023). FIDO CTAP 2.2 Review Draft, 21 March 2023. FIDO Alliance. https://fidoalliance.org/specs/fido-v2.2-rd-20230321/fido-client-to-authenticator-protocol-v2.2-rd-20230321.html
  43. (2022). Apple, Google and Microsoft Commit to Expanded Support for FIDO Standard to Accelerate Availability of Passwordless Sign-Ins. FIDO Alliance. https://fidoalliance.org/apple-google-and-microsoft-commit-to-expanded-support-for-fido-standard-to-accelerate-availability-of-passwordless-sign-ins/
  44. Web Authentication: An API for accessing Public Key Credentials -- Level 2 (latest). W3C. https://www.w3.org/TR/webauthn-2/
  45. iCloud Keychain (Wikipedia). Wikipedia. https://en.wikipedia.org/wiki/ICloud_Keychain
  46. Microsoft Authenticator (Wikipedia). Wikipedia. https://en.wikipedia.org/wiki/Microsoft_Authenticator
  47. (2024). Microsoft Introduces Passkeys for Consumer Accounts. Microsoft Security Blog. https://www.microsoft.com/en-us/security/blog/2024/05/02/microsoft-introduces-passkeys-for-consumer-accounts/
  48. iCloud data security overview (Standard and Advanced Data Protection). Apple Support. https://support.apple.com/en-us/HT202303
  49. Temoshok, LaSalle, & Regenscheid (2024). NIST SP 800-63B Supplement 1: Incorporating Syncable Authenticators. NIST CSRC. https://csrc.nist.gov/pubs/sp/800/63/b/sup/final
  50. (2025). Pushing passkeys forward: Microsoft's latest updates for simpler, safer sign-ins. Microsoft Security Blog. https://www.microsoft.com/en-us/security/blog/2025/05/01/pushing-passkeys-forward-microsofts-latest-updates-for-simpler-safer-sign-ins/
  51. microsoft/webauthn: Win32 APIs and plugin header files. GitHub. https://github.com/microsoft/webauthn
  52. webauthn.h Win32 API reference. Microsoft Learn. https://learn.microsoft.com/en-us/windows/win32/api/webauthn/
  53. Passkeys (Windows identity protection). Microsoft Learn. https://learn.microsoft.com/en-us/windows/security/identity-protection/passkeys/
  54. YubiKey 5 Series Overview. Yubico. https://www.yubico.com/products/yubikey-5-overview/
  55. Adam Langley (2022). Passkeys. imperialviolet.org. https://www.imperialviolet.org/2022/09/22/passkeys.html
  56. passkeys.dev (FIDO Alliance / WebKit / Chrome team passkey resource). FIDO Alliance. https://passkeys.dev/
  57. (2024). Passkeys on Windows: authenticate seamlessly with passkey providers. Windows Developer Blog. https://blogs.windows.com/windowsdeveloper/2024/10/08/passkeys-on-windows-authenticate-seamlessly-with-passkey-providers/
  58. ASCredentialIdentityStore -- AuthenticationServices. Apple Developer. https://developer.apple.com/documentation/authenticationservices/ascredentialidentitystore
  59. Credential Manager (Android Developers). Android Developers. https://developer.android.com/identity/credential-manager - Canonical general Credential Manager API doc (Android 14+).
  60. Contoso Passkey Manager (Windows-classic-samples). GitHub. https://github.com/microsoft/Windows-classic-samples/tree/main/Samples/PasskeyManager
  61. Third-party passkey providers on Windows. Microsoft Learn. https://learn.microsoft.com/en-us/windows/apps/develop/security/third-party
  62. WebAuthn Attestation Statement Format Identifiers (IANA registry). IANA. https://www.iana.org/assignments/webauthn/webauthn.xhtml
  63. Hodges, Mandyam, & M.B. Jones (2020). RFC 8809: Registries for Web Authentication (WebAuthn). IETF. https://datatracker.ietf.org/doc/html/rfc8809
  64. (2021). Web Authentication: An API for accessing Public Key Credentials -- Level 2 (W3C Recommendation, 8 April 2021). W3C. https://www.w3.org/TR/2021/REC-webauthn-2-20210408/
  65. (2024). SafetyNet Attestation API deprecation timeline. Android Developers. https://developer.android.com/privacy-and-security/safetynet/attestation - Auto-redirects to the canonical .../deprecation-timeline page (the original android-developers.googleblog.com 2022 post body now returns a Blogger error template).
  66. WebAuthn (Wikipedia). Wikipedia. https://en.wikipedia.org/wiki/WebAuthn
  67. Google Authenticator (Wikipedia). Wikipedia. https://en.wikipedia.org/wiki/Google_Authenticator
  68. (2024). FIDO Credential Exchange Protocol (CXP) v1.0 Working Draft, 3 October 2024. FIDO Alliance. https://fidoalliance.org/specs/cx/cxp-v1.0-wd-20241003.html
  69. Use a recovery key for your Apple Account. Apple Support. https://support.apple.com/en-us/109345
  70. Configure Temporary Access Pass to register passwordless authentication methods. Microsoft Learn. https://learn.microsoft.com/en-us/entra/identity/authentication/howto-authentication-temporary-access-pass