Why Are Passkeys Secure? — An Illustrated Guide to Authentication That Never Sends a Secret
· Go Komura · Passkeys, WebAuthn, FIDO2, Security, Authentication, Phishing Prevention, Information Systems
News that “passwords have leaked from another major service” no longer surprises anyone. Run phishing drills every year, and the number of people who fall for it never reaches zero. “Don’t reuse passwords, make them long, and periodic changes… you don’t need those any more” — even the advice has flip-flopped.
Passkeys, which have spread rapidly over the past few years, are an authentication method that Apple, Google, and Microsoft are jointly promoting as the answer to this situation.1 They’re often introduced as “convenient — you can log in with your fingerprint or face” — but that’s not really the point. The real value of a passkey is that it moves the basis for security from “human vigilance” to “the structure of the protocol”.
- Passwords leak because users are careless, so let’s train them → humans always make mistakes
- Let’s train people to spot fake sites → you can build a fake site that’s impossible to spot
- With a passkey → there’s no secret to send in the first place, and no signature can be produced on a fake site
This article works through, with diagrams, why passkeys are secure, starting from what’s broken about passwords. It then answers head-on the obvious questions — “are synced passkeys really safe?” and “do they have weaknesses?” — and finishes by laying out the practical essentials of rolling passkeys out to web apps and Windows environments.
1. The Bottom Line First
The reasons passkeys are secure come down to three points.
- No secret exists on the server. All the server stores is the public key, which is information that’s safe to leak. Even if the entire database is exfiltrated, there’s no “material for impersonation” for an attacker to take home.2
- The secret never travels the network. All that’s sent at login is a signature over a one-time random value (the challenge). Because the private key never leaves the device’s authenticator, eavesdropping or relaying anywhere along the path yields no secret.2
- No signature can be produced on a fake site. A passkey is bound to a site’s domain, and the browser enforces the domain match. Even if a user is fooled by a fake site, the passkey for the genuine site simply never appears as a candidate, and even if a signature were somehow relayed, verification would reject it.3
These aren’t three independent tricks — they’re all consequences that follow from a single design shift: the move from authentication that shares and sends a secret, to authentication that proves possession of a secret through a signature. Let’s take them in order.
How the Terms Relate — Passkeys, WebAuthn, FIDO2, and CTAP
This field has a lot of terminology, and different articles use it to mean different scopes, so let’s pin down the relationships first. A passkey isn’t a new protocol — it’s a “name” attached to a combination of existing standards.21
| Term | Full name | What it refers to |
|---|---|---|
| WebAuthn | Web Authentication API (a W3C Recommendation) | The standard between the browser and the website. The API that uses navigator.credentials to request key-pair creation and signing |
| CTAP | Client to Authenticator Protocol (FIDO Alliance) | The standard between the browser and an external authenticator. The part that talks to security keys and phones over USB, NFC, or Bluetooth |
| FIDO2 | — | The umbrella term for the framework combining the two above. FIDO2 = WebAuthn + CTAP |
| Passkey | — | The name given to the subset of FIDO2 credentials that let you log in standalone in place of a password (discoverable credentials) |
Table 1: A passkey is a name given atop the FIDO2 foundation — it isn’t the name of a standard itself
In other words, “supporting passkeys” translates, in implementation terms, to “implementing WebAuthn”. CTAP is a layer the browser and OS handle on your behalf when an external authenticator is used, so those building web apps never touch it directly.
2. What’s Broken About Password Authentication
The shortcut to understanding why passkeys are secure is to think about a password’s weaknesses in terms of “location”. With password authentication, the secret itself travels the entire path every single time you authenticate.
sequenceDiagram
participant U as User
participant B as Browser
participant S as Server
Note over U: Holds the secret (password) in their head<br/>[Weakness 1] Guessable, reused across sites
U->>B: Enters the password
Note over B: [Weakness 2] Can be entered into a fake<br/>site just as easily (visually indistinguishable)
B->>S: Sends the password itself
Note over B,S: [Weakness 3] The secret travels the wire<br/>Protected by TLS, but reverts to plaintext at the endpoint
S->>S: Checks it against the stored hash
Note over S: [Weakness 4] Every user's secret (hash) accumulates<br/>here — a leak becomes a target for offline brute force
Figure 1: With password authentication, the secret itself exists across the entire path
From an attacker’s point of view, this is a structure with a lot of easy targets.
- Weakness 1 (the user): The password is only as strong as something memorable, and gets reused across multiple sites. A leak in one place spreads to every account (credential-stuffing attacks).
- Weakness 2 (the moment of entry): Prepare a fake site indistinguishable from the real one, and the user will hand over the secret voluntarily (phishing).
- Weakness 3 (the path): TLS makes eavesdropping the path itself difficult, but that’s meaningless once a “legitimate-looking relay point” is inserted (AiTM, discussed below).
- Weakness 4 (the server): Even stored as hashes, once the database leaks it can be brute-forced offline. The weakest passwords fall first.
The traditional answer, multi-factor authentication, says “then let’s add a one-time code — SMS or TOTP” — but this still doesn’t change the structure of sending a shared secret. TOTP has the server and the authenticator app sharing the same seed (a secret), and the generated six-digit code can, in the end, still be typed into a fake site by the user. In fact, AiTM (Adversary-in-the-Middle) phishing, where a fake site relays in real time to the real server, defeats this by simply passing the password-plus-one-time-code pair straight through. This is exactly why CISA (the US Cybersecurity and Infrastructure Security Agency) lists only two methods as “phishing-resistant MFA” — FIDO/WebAuthn and PKI-based authentication such as smart cards (PIV/CAC) — and positions FIDO among them as the gold standard.4
In other words, the problem isn’t a password’s “strength” — it’s the very structure of sharing a secret and sending it every time you authenticate.
3. What a Passkey Really Is — Proving Possession Without Sending the Secret
A passkey is a public-key-cryptography-based credential built on two standards — the W3C’s WebAuthn and the FIDO Alliance’s CTAP (together, FIDO2).21 That may sound complicated, but the structure is simple.
flowchart LR
subgraph DEV["User's device"]
AUTH["Authenticator - the vault<br/>Windows Hello / Face ID /<br/>Android screen lock / security key"]
SK["Private key<br/>Never leaves this vault"]
BIO["Fingerprint, face, PIN<br/>Only opens the vault door<br/>This also never leaves the device"]
AUTH --- SK
BIO -->|"Verifies locally"| AUTH
end
subgraph SRV["Server"]
PK["Public key<br/>Safe to leak - a verification-only<br/>credential"]
end
SK -.->|"Mathematical pair - signing side"| PK
Figure 2: A passkey is really a per-site key pair. The private side never leaves the device, and the server holds only a public key for verification
- The private key is the key that can produce a signature. It’s held in an authenticator on the device — Windows Hello, an iPhone’s Face ID/Touch ID, an Android screen lock, or a security key such as a YubiKey — and never leaves it.
- The public key is the key that can only verify a signature, and this is what gets entrusted to the server. Computing the private key back from the public key is computationally infeasible, so it’s information that’s fine to leak.
- Biometric data such as a fingerprint or face is used only to open the vault door locally, and this too never leaves the device. Biometric data is never sent to the server.1
Registration: Handing Over the Public Key — And Nothing Else
This is the flow when you register a passkey with a site.
sequenceDiagram
participant S as Server (example.com)
participant B as Browser
participant A as Authenticator
S->>B: Registration request (random challenge + site info)
B->>A: Create a key for this site (example.com)
A->>A: Confirms identity locally with fingerprint, face, or PIN
A->>A: Generates a new key pair<br/>Private key stored internally
A->>B: Public key + credential ID (the key's nameplate)
B->>S: Sends the public key + credential ID
S->>S: Stores it as the public key for this account
Note over S: All the server received was<br/>"information that's safe even if it leaks"
Figure 3: At registration, only the public key crosses the network and gets stored on the server
What matters is that the key pair is created bound to the site’s domain (its RP ID) at this point. A passkey created for example.com can only be used on the example.com site (since the RP ID is domain-scoped, it can be used from a page on a subdomain under the same domain, such as login.example.com, but not from an unrelated domain). This binding is the foundation of the phishing resistance discussed below.3
Also, a key pair is freshly created for every single site. Since the passkey for site A and the passkey for site B are mathematically unrelated, the very concept of “reuse” doesn’t exist, nor can they be used as material to correlate a user across sites.
Authentication: Returning a One-Time Signature
This is the flow at login time. Compare it against password authentication (Figure 1).
sequenceDiagram
participant S as Server (example.com)
participant B as Browser
participant A as Authenticator
S->>B: Login request (one-time random challenge)
B->>A: Requests a signature for example.com
A->>A: Confirms identity locally with fingerprint, face, or PIN
A->>A: Creates a signature with the private key<br/>Bakes in the challenge + origin + RP ID hash
A->>B: Signature (not the private key itself)
B->>S: Sends the signature
S->>S: Verifies the signature with the stored public key<br/>Also checks the challenge, origin, and RP ID
Note over B,S: Only a disposable signature crosses the wire<br/>Even if stolen, it's useless for the next challenge
Figure 4: The secret doesn’t move at authentication time either. All that crosses is a “one-time proof document”
The server issues a fresh random value (the challenge) every time, and the authenticator signs “that challenge, plus the origin the browser is currently viewing, plus a hash of the RP ID”. The server verifies the signature with the stored public key, confirming that the challenge is one it issued itself, and that the origin and RP ID belong to its own site.5
As a consequence of this design, two of the three reasons stated at the outset already hold true.
- No secret on the server: All that’s stored is the public key. Even if it leaks, an attacker can’t produce a signature from it, so unlike a password hash, there’s nothing to “take home and crack”.
- No secret travels the wire: Even if a signature on the path is stolen, the challenge is disposable, so it can’t be reused (replayed).
The remaining one — “no signature can be produced on a fake site” — is a passkey’s biggest selling point. We’ll look at it in its own section.
4. Why Phishing Cannot Succeed “By Design”
Phishing succeeds against passwords because you can enter the genuine secret into a fake site. Humans can’t tell example.com and examp1e.com apart — especially when tired — but the password field works identically on either site.
With passkeys, this matching is done mechanically by the browser, not by a human. Under the WebAuthn specification, the browser can only invoke the authenticator when “the domain of the currently displayed origin” corresponds to “the passkey’s RP ID”.3 Here’s a diagram of what happens the moment you visit a fake site.
sequenceDiagram
participant U as User
participant B as Browser
participant P as Fake site (examp1e.com)<br/>An AiTM proxy relaying to the real site
participant S as Real server (example.com)
U->>P: Visits a login page that looks identical
P->>S: Starts the real login process behind the scenes
S->>P: Challenge
P->>B: Forwards the challenge and requests a signature
B->>B: The current origin is examp1e.com<br/>The example.com passkey cannot be offered as a candidate
B--xP: No signature is created (the user has no way to be fooled)
Note over B,S: Even if a signature were somehow created,<br/>it would have examp1e.com baked in,<br/>so the real server's verification would always reject it
Figure 5: AiTM-style phishing defeats passwords plus one-time codes, but with passkeys it fails at the signature stage
Notice that the defence is doubled up.
- It never appears as a candidate: the browser only enumerates passkeys whose RP ID matches the origin. On the fake domain, the passkey for the real site never appears as an option, so the user can’t even use it “by accident”.
- The signature doesn’t pass: what’s signed includes the origin the browser confirmed and a hash of the RP ID. Because the real server checks this at verification time, a signature produced under a different origin is always rejected.5
Phishing countermeasures for passwords relied on human effort — “the user carefully checks the URL”. With passkeys, the user doesn’t need to spot the fake site in the first place. That is the precise meaning of the term “phishing-resistant”, and it’s why CISA and NIST (the US National Institute of Standards and Technology) single out FIDO/WebAuthn for special treatment.46
Let’s organise everything so far by attack technique.
| Attack | Password | Password + TOTP | Passkey |
|---|---|---|---|
| Guessing / brute force | ✗ Weak | △ The code protects it, but the underlying password stays weak | ○ Nothing exists to guess |
| Reuse (credential stuffing) | ✗ A leak in one place spreads everywhere | △ Falls apart at sites without code support | ○ An independent key per site |
| Server DB breach | ✗ Hashes brute-forced offline | ✗ The TOTP seed (a shared secret) also leaks | ○ Only a public key exists |
| Classic phishing (typed into a fake site) | ✗ Can be entered | ✗ The code can be entered too | ○ Never a candidate, and the signature never passes |
| AiTM (real-time relay) | ✗ Passed straight through | ✗ The code is passed straight through too | ○ Origin checking means no signature can be produced |
| Replay (reusing traffic) | ✗ The same password stays valid indefinitely | △ A code intercepted before the legitimate user uses it remains valid (a correct implementation rejects re-acceptance of a used code) | ○ The challenge is disposable every time |
Table 2: Resistance compared by attack technique. Every “circle” for passkeys comes from structure, not operational discipline or vigilance
5. Are “Synced Passkeys” Safe?
Reading the explanation so far naturally raises a question. “You said the private key never leaves the device — so why can a passkey created on an iPhone also be used on an iPad?” — a good question, and the answer is: “there are two kinds of passkey.”
Let’s put the conclusion in a quick-reference table first. Read this section and the next as an explanation of why each row of this table is the way it is.
| Aspect | Synced passkey | Device-bound passkey |
|---|---|---|
| Typical examples | iCloud Keychain, Google Password Manager, password managers such as 1Password | Security keys (YubiKey and similar), Windows Hello, passkeys inside Microsoft Authenticator |
| Where the private key is kept | In the platform’s credential vault. Replicated between devices on the same account in end-to-end encrypted form | Inside the authenticator’s hardware. Never leaves the TPM or secure element |
| On loss or device change | Restorable to a new device by signing in to the same Apple ID or Google account | That authenticator’s passkey is lost. Registering spare authenticators is a prerequisite |
| Single point of failure | The platform’s cloud account | The physical device itself |
| Fit for corporate management | Because the key sits in a personal cloud account, it’s hard for an organisation to track its whereabouts or revoke it in bulk. Suits BYOD and small scale | An administrator can distribute and revoke it, and the key’s location is clear. Suits environments with strict policy |
| NIST AAL conformance | AAL2 if the requirements are met. Cannot be used for AAL3 because the private key is exportable6 | Hardware-protected authenticators that can’t export the key can meet the requirements AAL3 demands6 |
Table 3: A quick-reference table for synced vs. device-bound passkeys. Which to choose comes down to trading off “resilience to loss” against “being able to manage where the key is”
flowchart TB
subgraph SYNC["Synced passkeys - the consumer default"]
S1["iCloud Keychain /<br/>Google Password Manager /<br/>password managers such as 1Password"]
S2["Synced end-to-end encrypted<br/>between devices on the same account<br/>Even the provider can't read the contents"]
S3["Benefit: resilient to device changes and loss<br/>Caveat: the cloud account itself must be hardened"]
S1 --> S2 --> S3
end
subgraph BOUND["Device-bound passkeys"]
B1["Security keys - YubiKey and similar /<br/>Windows Hello /<br/>Microsoft Authenticator - Entra ID"]
B2["The private key never physically leaves<br/>that hardware - protected by a TPM or similar"]
B3["Benefit: the key's location is clear and singular<br/>Caveat: registering multiple keys is essential against loss"]
B1 --> B2 --> B3
end
SYNC ~~~ BOUND
Figure 6: Synced vs. device-bound. Both share the same “never send the private key to the server” property; only where the defensive weight falls differs
A synced passkey is one where iCloud Keychain or Google Password Manager syncs the private key across devices on the same account. What matters here is that the sync is end-to-end encrypted. Both Apple and Google state explicitly that a passkey is encrypted on the device before it’s synced, and that the provider itself can’t read the contents.78 In other words, the principle “the private key never leaves the device” is relaxed, precisely, to “the private key never leaves the device in plaintext”, and in exchange it gains resilience to device changes and loss.
It’s worth being explicit about how this relaxation changes the threat model. The place you have to defend consolidates from “each site’s server” into “a single cloud account”. It stays just as resistant to each site’s DB leaks and phishing as before, but now takeover of the Apple ID or Google account itself becomes the single point of failure. That’s exactly why putting the strongest possible protection on the platform account holding your passkeys — a strong screen lock, tidied-up recovery options, and a physical security key where possible — is a baseline requirement. In April 2024, NIST also issued a supplement to NIST SP 800-63B (Supplement 1: Incorporating Syncable Authenticators Into NIST SP 800-63B), formally establishing that this kind of synced passkey (a syncable authenticator) can meet the government standard AAL2 (Authenticator Assurance Level 2) if the requirements are satisfied. However, because the private key can be exported, synced authenticators are not to be used for AAL3, which requires a hardware-isolated environment.6
A device-bound passkey is the type where the private key never leaves the hardware. Security keys such as YubiKey are the typical example, and on the enterprise side, Microsoft Entra ID passkeys (the ones created inside Microsoft Authenticator) are device-bound too.9 Windows Hello on Windows also protects the private key under the TPM whenever one is available. This “hardware vault that never lets the key out” mechanism itself is the same foundation covered in detail in the TPM article.
You may also have wondered, when “logging in to a browser on a PC using a phone’s passkey”, why you’re made to scan a QR code. That’s not just a screen transition — it’s a hybrid method (FIDO’s cross-device authentication) that confirms the physical proximity of the phone and the PC over Bluetooth. This proximity check shuts down an attack in which a remote attacker gets someone else to approve a login to the attacker’s own PC via a QR code.1
6. Not a Silver Bullet — Weaknesses Don’t “Disappear,” They “Move”
We’ve explained the strengths of passkeys so far, but in all honesty, passkeys don’t eliminate attacks — they’re a technology that pushes attackers toward weaker spots. Here’s a diagram of where attackers go once the front door of authentication hardens.
flowchart LR
A["Attacker"]
G["Authentication itself<br/>Challenge signature<br/>Hardened"]
R["Account recovery flow<br/>Claim you lost your passkey,<br/>get reset via SMS or email,<br/>and register the attacker's passkey"]
F["Fallback methods left in place<br/>If password or SMS login<br/>still work, that's the weakest link"]
C["Cloud account<br/>For synced passkeys, the Apple ID /<br/>Google account is the single point of failure"]
SS["Session<br/>Steal the post-login cookie<br/>and the auth method is irrelevant"]
A --x G
A --> R
A --> F
A --> C
A --> SS
Figure 7: Once the front door (authentication) hardens, attacks shift to the recovery flow, surviving fallback methods, the cloud account, and the session
There are four residual risks worth keeping in mind in practice.
- Surviving fallback methods become the weakest link. Merely making passkeys “also” usable, while passwords or SMS login remain in place, just gives attackers those to use instead. Looking at the account as a whole, phishing resistance is rate-limited by the level of the weakest login method available. The real work of rollout isn’t adding passkeys — it’s the planned reduction and eventual retirement of fallbacks.
- The recovery flow becomes a new attack surface. This is the trick of falsely claiming “I lost my device” to get a support desk or an email-based reset process to register the attacker’s own passkey. In practice, social engineering that bypasses strong authentication by tricking a help desk has become a routine tool for large-scale breaches. Precisely because authentication has been hardened, how you design identity verification in the recovery flow is what gets tested.
- For synced passkeys, the cloud account is the single point of failure. As covered in the previous section. What’s needed is defence of the account holding your passkeys, and, for organisational use, a policy decision on “which platforms are allowed to sync”.
- Session theft isn’t prevented. A passkey only protects the moment of login; if the post-login session cookie is stolen via malware or XSS, the authentication method is irrelevant. The separate-layer work of managing token lifetime, binding, and device health remains.
None of this is an argument for “let’s skip passkeys”. It’s the obvious point that upgrading the front door lock doesn’t take care of locking the windows. If anything, because the location of the weakness becomes clear, you can concentrate defensive resources on the recovery flow and session management.
7. Rolling It Out in Practice — the WebAuthn API and Windows Environments
Finally, let’s cover the essentials from the perspective of the side rolling this out.
Adding Passkey Login to Your Own Web Service
On the browser side, it’s just two functions of the WebAuthn API. Registration calls navigator.credentials.create(), and authentication calls navigator.credentials.get().
// Registration (browser side)
const credential = await navigator.credentials.create({
publicKey: {
challenge: challengeFromServer, // A one-time random value generated by the server
rp: { id: "example.com", name: "Example" },
user: { id: userIdBytes, name: "taro@example.com", displayName: "Taro" },
pubKeyCredParams: [{ type: "public-key", alg: -7 }], // ES256
authenticatorSelection: {
residentKey: "required", // Makes it a discoverable credential (i.e., a passkey)
userVerification: "required", // Requires identity verification via biometrics/PIN
},
},
});
// The public key comes from credential.response; the credential ID comes
// from the top-level credential.id / credential.rawId. As with
// authentication, verify the challenge, origin, and RP ID on the server
// before storing the registration response.
The meaning of the main parameters is as follows.
| Parameter | Role | Implementation notes |
|---|---|---|
challenge |
A one-time random value the server generates each time | Use unguessable cryptographic randomness. On the server, verify it’s an unused value you issued yourself, then consume it |
rp.id |
The domain the credential is bound to (the RP ID) | If omitted, it becomes the effective domain of the calling origin. It can only be set within the range of registrable domains, e.g. specifying example.com from login.example.com |
user.id |
The server’s internal user identifier (the user handle) | An opaque value of at most 64 bytes. Don’t put personally identifying information such as an email address or user name into it directly2 |
user.name / user.displayName |
Strings shown in the authenticator’s or browser’s UI so the user can choose an account | Display-only. The server must never trust this value to identify an account |
pubKeyCredParams |
Lists the accepted public-key algorithms in order of preference | Listing -257 (RS256) alongside -7 (ES256) widens the range of authenticators that will be accepted |
authenticatorSelection |
The properties required of the authenticator | residentKey: "required" makes it a passkey (a discoverable credential); userVerification: "required" makes biometric or PIN identity verification mandatory |
Table 4: The main parameters of navigator.credentials.create()
A note on test environments: because the WebAuthn API is only exposed in a secure context, calling navigator.credentials fails on a page served over plain http://. The exception is http://localhost (and 127.0.0.1), which are treated as trustworthy origins, so you can try it out on a dev machine as-is without going to HTTPS. However, the RP ID must be the origin’s effective domain (or a parent of it), so a passkey created on localhost can’t be used on your production domain. Even without an authenticator on hand, enabling the virtual authenticator under the “WebAuthn” tab of Chrome’s DevTools lets you run through everything from registration to authentication.
// Authentication (browser side)
const assertion = await navigator.credentials.get({
publicKey: {
challenge: challengeFromServer,
rpId: "example.com",
userVerification: "required",
},
// Offers the passkey as an autofill suggestion in the login field. Check
// support beforehand with PublicKeyCredential.isConditionalMediationAvailable(),
// and fall back to a normal call without mediation on unsupported browsers.
mediation: "conditional",
// (Requires autocomplete="username webauthn" on the target <input>)
});
// Verify the signature in assertion.response on the server
The main event is verification on the server side. At minimum, always do the following.5
- Verify the challenge: is it an unused challenge you issued yourself? Is it treated as disposable (replay protection)? Also, store it bound to the browser session (the login attempt) at the time of issuance, and allow it to be consumed only by a response from that same session. If this is lax, it opens room for an attacker to push a signature over a challenge addressed to them through the victim’s browser, logging the victim into the attacker’s own account (login CSRF).
- Verify the origin: is
origininclientDataJSONyour site’s legitimate origin (the linchpin of phishing resistance)? - Verify the RP ID hash: does
rpIdHashinauthenticatorDatamatch the SHA-256 of your site’s RP ID? - Confirm the ceremony type and flags: is
typeinclientDataJSONequal towebauthn.getfor authentication, orwebauthn.createfor registration? Is the UP (user present) flag set inauthenticatorData? If you required user verification (UV), is the UV flag set too? - Verify the signature: does the signature correctly verify against the public key stored at registration?
- Bind it to the account: look up the presented credential ID (and userHandle) in your own database, and issue the session to that credential’s actual owner. Unconditionally trusting a separately entered user name creates a hole that lets a correct signature log a user in as someone else.
- Store and compare the signature counter: store
signCountfromauthenticatorDataper credential, and check that the next value is greater than the previous one. Treat a value at or below the previous one (including equal) as a sign of a cloned authenticator. That said, since many synced-passkey implementations always return 0, allow zero-to-zero as an exception.
Writing this verification by hand is a recipe for accidents, so use a proven library — fido2-net-lib for .NET, SimpleWebAuthn for Node.js, and so on. Leave the details of the specification (CBOR parsing, algorithm negotiation, challenge management) to the library, and focus your own effort on storing and revoking challenges, the multi-passkey management UI, and designing the recovery flow — that’s the right allocation of effort.
Windows Environments and In-House Systems
For this site’s readers — those responsible for Windows business systems — the following three points are enough to keep in mind.
- Windows clients already support it. Windows 11 supports creating, using, and managing passkeys via Windows Hello as the authenticator (Settings > Accounts > Passkeys), and the private key gets hardware protection when a TPM is present.10 WebAuthn via the browser (Edge/Chrome) also works on Windows 10.
- In an Entra ID environment, enable the “passkey = FIDO2 authentication method”. Microsoft Entra ID supports security keys and passkeys within the Microsoft Authenticator app (device-bound), and requiring “phishing-resistant MFA” via a Conditional Access authentication strength lets you restrict access to target resources to passkeys and the like.9 Migrating away from a world of NTLM and password expiry policies doesn’t happen overnight, so the standard practice is to mandate phishing-resistant MFA for administrator accounts first, in parallel with the authentication-infrastructure inventory covered in the NTLM and Kerberos article.
- The benefit is the same for in-house web apps — but HTTPS is a prerequisite. Because the WebAuthn API only works in a secure context, intranet apps too need HTTPS (except for
localhostduring development) and proper internal domain names usable as an RP ID as prerequisites. Once those are in place, the RP ID works against internal domains just as well. In the sense of finally getting rid of the password sticky note, it’s not unusual for internal rollouts to show results faster than customer-facing services.
8. Summary
- A password’s weakness isn’t its strength — it’s the structure of sharing a secret and sending it every time you authenticate. Because the secret exists at the user, the input field, the path, and the server all at once, there are many attack targets. Adding a one-time code doesn’t help either — AiTM-style phishing defeats it by relaying it through.
- A passkey is a per-site public-key-cryptography key pair: it hands the server only a public key that’s safe to leak, and at login it sends only a signature over a disposable challenge. There’s no secret on the server, and no secret travels the wire either.
- Because the origin and RP ID the browser confirmed are baked into the signature, the genuine passkey never appears as a candidate on a fake site, and even a relayed signature fails verification. That the user never needs to spot the fake site is the real substance of “phishing resistance” — the basis of defence has moved from human vigilance to the structure of the protocol.
- Synced passkeys are synced with end-to-end encryption and are resilient to device changes and loss. In exchange, the place you need to defend consolidates onto the cloud account, so defending the Apple ID or Google account itself becomes a baseline requirement. Organisations can also choose device-bound passkeys (security keys, Entra ID’s Authenticator passkeys).
- Passkeys don’t eliminate attacks — they push them toward weaker spots. Surviving passwords, the account recovery flow, and session theft remain as attack surfaces, and the real work of rollout is the planned reduction of fallbacks and hardening of the recovery flow.
- Implementation is just the WebAuthn API’s two functions,
createandget, plus server-side verification. Don’t build the verification yourself — leave it to a proven library, and put your effort into challenge management, the multi-passkey UI, and recovery design.
Related Articles
- What Is the TPM in Windows? — An Illustrated Guide to the “Safe That Never Lets Keys Out” and Measured Boot
- NTLM and Kerberos Explained with Diagrams — Why Authentication Falls Back to NTLM
- Integrating Entra ID Authentication into WinForms/WPF Apps — A Practical Architecture with MSAL.NET and the WAM Broker
- Handling Credentials Safely in PowerShell — Banishing Plaintext Passwords from Your Scripts
- A Minimum Security Checklist for Windows App Development
- Where Should SMEs Start on Security? — A Walkthrough of IPA’s ‘Information Security Guidelines for SMEs,’ 4th Edition
Related Consulting Areas
KomuraSoft LLC handles contracted development including support for implementing passkey login/WebAuthn in in-house web systems, designing phishing-resistant MFA rollouts in Entra ID environments, and building authentication into Windows business apps such as WinForms/WPF.
-
FIDO Alliance, Passkeys and How FIDO Works. On passkeys being FIDO credentials that replace the password; on biometric data never being transmitted from the device and being used only for local matching; on Apple, Google, and Microsoft jointly announcing in May 2022 their expanded commitment to passwordless support based on FIDO standards; and on cross-device use employing a hybrid method that uses a QR code together with Bluetooth proximity confirmation. ↩ ↩2 ↩3 ↩4 ↩5
-
W3C, Web Authentication: An API for accessing Public Key Credentials Level 2 (a W3C Recommendation). On WebAuthn being an API for creating and using public-key-cryptography-based credentials; on a credential’s private key being held by the authenticator, with only the public key and the credential ID registered on the server (the Relying Party); on authentication being carried out via a signature (an assertion) over a challenge the server sends; and on the design goals for credential scoping and protection. The body text also references the API being exposed only in a secure context, the RP ID defaulting to the calling origin’s effective domain when omitted, and the user handle (
user.id) being an opaque value of at most 64 bytes that should not include personally identifying information such as a user name or email address (§14.6.1 User Handle Contents). ↩ ↩2 ↩3 ↩4 ↩5 -
W3C, Web Authentication Level 2 — §5.1.3 Create / RP ID validation, §13.4.9 Regarding phishing. On public-key credentials being scoped to the RP ID (the Relying Party identifier, i.e. the domain); on the browser (client) verifying that the calling origin’s registrable domain corresponds to the RP ID, and refusing to create or use the credential when it does not; and on this meaning that a fake origin cannot access another site’s credential, giving WebAuthn resistance to phishing attacks including man-in-the-middle variants. ↩ ↩2 ↩3
-
CISA, Implementing Phishing-Resistant MFA (an October 2022 fact sheet). On MFA using SMS, voice, push notifications, or OTP being vulnerable to phishing, AiTM (relay) attacks, and MFA fatigue attacks; on FIDO/WebAuthn authentication and PKI-based authentication (smart cards and the like) being listed as phishing-resistant methods, with FIDO/WebAuthn authentication positioned as the gold standard; and on organisations being advised to migrate high-risk accounts to phishing-resistant MFA first. ↩ ↩2
-
W3C, Web Authentication Level 2 — §7.2 Verifying an Authentication Assertion. On the server-side verification procedure specifying checks of clientDataJSON’s type, challenge (matching what was issued), and origin; verification that rpIdHash in authenticatorData matches the SHA-256 hash of the expected RP ID; confirmation of the User Present / User Verified flags; and signature verification against the stored public key. ↩ ↩2 ↩3
-
NIST, Incorporating Syncable Authenticators Into NIST SP 800-63B (an April 2024 supplement, incorporated into SP 800-63B revision 4). On a syncable authenticator’s (a synced passkey’s) private key being able to satisfy AAL2 when it’s stored and replicated across a synchronisation fabric in a manner meeting the requirements; on AAL3 cryptographic authenticators requiring a hardware-protected, isolated environment, and syncable authenticators whose private key can be exported therefore not being used for AAL3; and on methods that perform origin verification, such as WebAuthn, being classified as having verifier impersonation resistance (phishing resistance). The original PDF is NIST SP 800-63B Supplement 1. ↩ ↩2 ↩3 ↩4
-
Apple Support, About the security of passkeys. On passkeys being synced through iCloud Keychain; on iCloud Keychain being end-to-end encrypted such that even Apple can’t read it; and on syncing being protected by a key on the user’s device, with rate-limited, escrow-based recovery provided. ↩
-
Google, Security of Passkeys in the Google Password Manager. On a passkey’s private key being encrypted on the device before it’s synced; on end-to-end encryption meaning Google itself cannot access the private key’s contents; and on restoration requiring protection based on the device’s screen lock and similar factors. ↩
-
Microsoft Learn, Enable passkey (FIDO2) authentication in Microsoft Entra ID. On Entra ID supporting phishing-resistant passwordless authentication via FIDO2 security keys and Microsoft Authenticator passkeys (device-bound); and on being able to enable it through the authentication methods policy and require it via a Conditional Access authentication strength (phishing-resistant MFA). ↩ ↩2
-
Microsoft Learn, Passkey support on Windows. On Windows 11 supporting the creation and use of passkeys via Windows Hello; on saved passkeys being manageable from Settings > Accounts > Passkeys; on Windows Hello credentials being hardware-protected in environments where a TPM is available; and on passkeys on a mobile device being usable via a QR code. ↩
Related Articles
Recent articles sharing the same tags. Deepen your understanding with closely related topics.
NTLM and Kerberos Explained with Diagrams — Why Authentication Falls Back to NTLM
An illustrated comparison of NTLM and Kerberos: challenge/response, TGTs and service tickets, the conditions under which Negotiate falls ...
Windows Security Audit Policy and Event Log Investigation in Practice — Becoming an IT Team That Can Read Event 4625
A practical guide for answering "please look into the failed sign-in logs." It covers the relationship between basic and advanced audit p...
A Practical Guide to Windows LAPS — Retiring the Shared Local Administrator Password Across All PCs
A shared local administrator password across every PC is fertile ground for Pass-the-Hash attacks, where the compromise of one machine sp...
The Windows Certificate Store in Practice — User or Computer, Which Should You Use?
Should a client certificate go in the user store or the computer store? This practical guide works systematically through the classic cer...
The Windows Firewall and Business Applications — Register Inbound Rules From the Installer
"It works on the dev machine but the client can't connect" almost always traces back to the Windows Firewall. This article covers the def...
Related Topics
These topic pages place the article in a broader service and decision context.
Windows Technical Topics
Topic hub for KomuraSoft LLC's Windows development, investigation, and legacy-asset articles.
Frequently Asked Questions
Common questions about the topic of this article.
- What is the fundamental difference between passkeys and passwords?
- A password is a mechanism in which the user and the server share the same secret and send that secret every time you log in. Because the secret exists everywhere — in the user's head, in the input field, on the wire, and in the server's database — every one of those places becomes an attack target. A passkey uses a public-key cryptography key pair, and the private key is never sent to the server. With a device-bound passkey, the private key never leaves the authenticator at all; even with a synced passkey it only ever leaves the device in end-to-end encrypted form. All the server stores is the public key — information that's safe to leak — and all that's sent at login time is a signature over a one-time challenge. In other words, the shared secret that was the password's fundamental weakness simply doesn't exist. On top of that, since a key pair is created separately for each site, the very idea of reuse doesn't apply.
- Is biometric data (fingerprint, face) sent to the server?
- No. Fingerprint or face data is used only for local matching inside the device — to open the door of the vault holding the private key — and by FIDO's design, biometric data is never transmitted outside the device. All the server receives is a signature with the flag set that identity verification (user verification) took place; it contains nothing of the fingerprint itself, nor even any biometric feature vector derived from it. Where biometrics can't be used, a PIN can substitute, and just like a Windows Hello PIN, this PIN too is matched only locally on the device — the decisive difference from a password is that it never travels over the network.
- Why are passkeys resistant to phishing?
- Because, by design, the user never has to spot a fake site in the first place. A passkey is created bound to a site's domain (its RP ID), and the browser will only offer passkeys matching the domain of the site currently being displayed. Even if you visit a fake domain that looks identical to the real one, the passkey for the genuine site simply doesn't appear as an option, so the user has no way to be fooled. On top of that, the signature has the origin the browser confirmed and a hash of the RP ID baked into it, so even if the signature were relayed, verification on the real server would reject it. The structural impossibility of the accident that plagues passwords and SMS codes — entering genuine credentials into a fake site — is the fundamental difference from countermeasures that rely on training and vigilance.
- If I lose my phone, will I be locked out of my accounts?
- If it's a synced passkey — one stored in iCloud Keychain or Google Password Manager — you can restore it to a new device signed in to the same Apple ID or Google account. That said, restoring the end-to-end encrypted vault requires not just the account password but additional identity verification, such as entering the previous device's screen lock (passcode), so if you also lose those recovery means, restoration may not be possible. It matters not to entrust everything to a single phone. Device-bound passkeys (security keys, Windows Hello, and the like) share the device's fate, so the standard practice for important accounts is to register more than one passkey. Most services let you register multiple passkeys on a single account. Note that how you invalidate a lost passkey differs by type. For a synced passkey, since the copies on every device are the same single credential, first remove the lost device or perform a remote wipe on the platform account side to disable the copy on that device (deleting the passkey in the service's own account settings invalidates the copies on all devices at once). For a device-bound passkey, deleting that authenticator's passkey on the service side invalidates only the lost key. For organisational use, it's important to design both "redundancy so users can recover on their own" and "a procedure for administrators to revoke it on loss" together.
- Does a passkey have weaknesses too?
- Yes. Though it's more accurate to say the location of the weakness moves. Because authentication itself is hardened by public-key cryptography, attackers aim at the weaker surrounding areas instead. Concretely: if legacy methods like passwords or SMS still coexist, that remains the weakest link; there's the trick of abusing the account recovery flow to get an attacker's own passkey registered; and for synced passkeys, takeover of the cloud account itself becomes a new single point of failure. Also, an attack that steals the post-login session cookie isn't stopped by a passkey, so unrelated threats don't simply vanish either. Rolling this out needs to cover not just "adding passkeys" but also hardening the recovery flow and a planned reduction of fallback methods.