WebAuthn is a W3C standard that lets a browser authenticate a user with public-key cryptography instead of a password. Instead of a server storing a password, or its hash, that can be stolen and cracked or phished, the user's device holds a private key that never leaves it, and the server holds only the corresponding public key. Logging in means proving possession of the private key by signing a server-issued challenge, not typing a secret that could be intercepted, guessed, or reused across sites.
What changed in 2026
- Passkeys reached mainstream default status on most major consumer platforms — large tech platforms and most large banks now offer passkey sign-in as a primary option, not a beta feature.
- Cross-ecosystem passkey portability improved. FIDO Alliance work on credential exchange protocols made moving passkeys between major platform password managers realistic, reducing the original platform lock-in complaint.
- Hybrid, cross-device sign-in matured. Scanning a QR code to use a phone as a roaming authenticator for a desktop browser login is now a smooth, common flow rather than an awkward fallback.
- Enterprise adoption grew around workforce SSO, pairing hardware security keys for high-assurance roles with platform passkeys for general staff, phasing out SMS and TOTP-based two-factor where compliance allows.
- Account recovery remains the unsolved operational edge, pushing more relying parties toward multiple registered authenticators per user as the default guidance, not a single passkey.
How the registration and login ceremonies work
Registration:
- The site, the relying party, calls
navigator.credentials.create() with a challenge and its relying party ID (its domain).
- The browser prompts the authenticator — a platform authenticator like Touch ID or Windows Hello, or a roaming security key — to generate a new public/private key pair scoped to that domain.
- The user verifies presence, and often identity, via biometric or PIN; the private key is generated and stored on the authenticator, never transmitted.
- The public key, a credential ID, and optional attestation data are sent to the server and stored against the user's account.
Authentication:
- The server sends a fresh, random challenge to the browser.
navigator.credentials.get() asks the authenticator to sign the challenge using the private key matching the stored credential ID for that domain.
- The user verifies presence or identity again; the signature is returned to the server.
- The server verifies the signature against the stored public key. No secret ever crossed the network.
// Simplified registration call (browser side)
const credential = await navigator.credentials.create({
publicKey: {
challenge: challengeBytes,
rp: { name: "Example Corp", id: "example.com" },
user: { id: userIdBytes, name: "user@example.com", displayName: "User" },
pubKeyCredParams: [{ type: "public-key", alg: -7 }], // ES256
authenticatorSelection: { residentKey: "required", userVerification: "required" },
},
});
Why it resists phishing where passwords and OTPs do not
| Method |
Vulnerable to phishing? |
Why |
| Password |
Yes |
User can be tricked into typing it on a lookalike domain |
| SMS/TOTP one-time code |
Yes |
Code can be relayed or typed into a phishing site in real time |
| WebAuthn / passkey |
No |
Browser cryptographically binds the credential to the exact origin; a lookalike domain cannot trigger a valid signature |
The origin binding is enforced by the browser itself, not by user vigilance — the user cannot accidentally authenticate to the wrong site with a WebAuthn credential the way they can type a password into the wrong form.
Common mistakes
Registering only one authenticator per account. If it is lost, stolen, or replaced with no backup credential and no recovery path, the user is locked out entirely — always register at least two authenticators or provide a documented recovery flow.
Confusing user presence with user verification. Presence, a tap, confirms someone is there; verification, a biometric or PIN, confirms it is the enrolled user. High-assurance flows need to explicitly require userVerification: "required", not just presence.
Skipping attestation checks where they actually matter. Most consumer apps do not need to validate authenticator attestation, but regulated environments, like banking or enterprise access, that need to know which hardware is being used should not skip it.
Assuming passkeys eliminate the need for account recovery design. Device loss, factory resets, and platform migrations still happen — plan a secondary verification path before launch, not after the first support ticket.
FAQ
Are passkeys the same thing as WebAuthn?
Passkeys are WebAuthn, and the broader FIDO2, credentials with an added property: they are discoverable and synced across a user's devices via a platform account, removing the need to register separately on each device.
Can a WebAuthn credential be phished?
Not in the traditional sense. Because the browser binds the credential to the exact origin during signing, a convincing fake domain cannot obtain a valid signature even if the user is fully fooled visually.
What happens if a user loses their only authenticator?
They need a recovery path: a backup authenticator, a recovery code issued at registration, or an identity-verification fallback. This is the main design gap teams need to solve explicitly; WebAuthn itself has no built-in recovery mechanism.
Does WebAuthn require special hardware?
No. Platform authenticators built into phones and laptops, such as Touch ID, Windows Hello, and Android biometrics, satisfy WebAuthn without any separate hardware; external security keys are optional, typically used for higher-assurance scenarios.
Where to go next