Passkeys in production: what the spec actually requires, and what breaks anyway
Passkeys are the first authentication change in twenty years that makes a system both easier to use and harder to attack at the same time. That is unusual enough to be worth the migration.
It is also the reason the failure modes are subtle: the ceremony works on the first try, in a demo, on your own laptop. What follows is the part that is not in the quickstart — the decisions you cannot reverse later, and the cases that only appear once real people with real devices arrive.
What a passkey actually is
“A passkey is a FIDO authentication credential based on FIDO standards, that allows a user to sign in to apps and websites with the same process that they use to unlock their device (biometrics, PIN, or pattern).”
Underneath that, the mechanism is a key pair. The authenticator — a phone’s secure enclave, a laptop’s TPM, a hardware key — generates a private key it will never release, and hands your server the public half. Authentication is the server issuing a random challenge and the authenticator returning a signature over it.
Two properties fall out of that design, and they are the entire reason to adopt it. There is no shared secret — your database holds public keys, so a database breach yields nothing an attacker can replay. And the signature covers the origin, not just the challenge, which is what makes the credential phishing-resistant rather than merely passwordless.
Why phishing stops working, precisely
This is the part worth understanding rather than repeating. The W3C specification describes credentials as scoped:
“one or more public key credentials, each scoped to a given WebAuthn Relying Party, are created by and bound to authenticators as requested by the web application”
A credential created for example.com cannot be exercised by exarnple.com. The browser will not even offer it, because the Relying Party ID does not match — and the user is never asked to make that judgement. Compare a one-time code: a convincing enough page gets the user to read a six-digit number aloud to an attacker, and no amount of user education reliably fixes that. Passkeys move the decision from the human to the browser.
The decisions you cannot take back
1. Relying Party ID
Pick the highest domain you will plausibly authenticate from. A credential bound to app.example.com does not work on example.com; one bound to example.com works on both. For a multi-tenant product with customer-specific domains, this is not a detail — it decides whether a passkey follows the user across your surfaces or is trapped on one of them.
2. User verification: required, preferred, or discouraged
userVerification: "required" means the authenticator must check that the human is present and verified — biometric or PIN — not merely that a key is plugged in. That is what turns a single passkey ceremony into two factors: something you have (the authenticator) and something you are or know (the local verification).
Set it to "preferred" and you have a system whose assurance level varies silently per user and per device. If you intend to treat a passkey login as multi-factor — and most products should — require it, and be prepared for the small population whose authenticator cannot comply.
3. Discoverable credentials
A discoverable credential (formerly “resident key”) is stored on the authenticator with enough metadata that the user can be identified from it alone — that is what makes a truly usernameless sign-in possible. The trade-off is real: hardware authenticators have finite slots for them, and older keys can fill up. Non-discoverable credentials cost the user one extra step, identifying themselves first, and place no storage burden on the device.
What breaks once real users arrive
- The lost-device path is your real security boundary. A passkey removes the password as an attack surface and concentrates risk in account recovery. If recovery is “email a magic link”, you have rebuilt a phishable single factor and put it behind the strong one. Recovery deserves as much design attention as the ceremony itself.
- Synced passkeys change the threat model. FIDO’s own description is that a passkey created on one device gets synced to all the user’s other devices, end-to-end encrypted. Excellent for usability; it also means the credential’s security now partly rests on the user’s platform account. For most products that is a good trade. For a regulated one it may not be, which is why device-bound authenticators still exist.
- Cross-device sign-in is a different flow. Authenticating on a desktop with a phone uses a QR code and a proximity check. It works well and it looks nothing like the same-device path, so it needs its own copy, its own error states and its own testing.
- Enumeration leaks through the ceremony. A naive implementation returns a different response for “no such user” than for “user exists but has no passkey”. That is an account-enumeration oracle in a login form. The fix is that both paths must be indistinguishable — same shape, same timing envelope, no exceptions.
- One passkey is a lockout waiting to happen. Prompt for a second authenticator, or issue recovery codes at enrolment. Users who lose their only credential become support tickets that only a human identity check can close.
Where passwords still sit, and what the guidance actually says
Most products will run passkeys and passwords side by side for years. That is fine, provided the password path is not quietly weaker than the one you are proud of — an account with a passkey and a resettable password is only as strong as the reset flow.
Worth knowing while you are in this code: NIST’s digital identity guidelines dropped the advice most password policies are still built on. Composition rules and mandatory periodic rotation are no longer recommended; checking new passwords against known-breached lists is. If you are touching authentication anyway, that is a cheap upgrade to make in the same pass.
A shipping checklist
- Fix the Relying Party ID before the first production registration. It is not changeable afterwards.
- Decide user verification explicitly, and record why, because it determines whether you may call the result multi-factor.
- Make the “no such user” and “no passkey” responses indistinguishable, and test that with a timer, not by eye.
- Design account recovery first. It is the weakest link by construction, and it is where attacks will go.
- Prompt for a second authenticator or recovery codes at enrolment.
- Test the cross-device flow on a real phone and a real desktop, not in an emulator.
- Keep the password path as strong as the passkey path, or remove it deliberately rather than by neglect.
Adetio ships passkeys as a first-class factor rather than an add-on, on every tier including the free one, with user verification required and the enumeration case closed by default — because these are the settings most implementations get wrong on the way to production, and a default that is safe is worth more than a documentation page that explains the danger. The authentication product page covers what is available today.
Sources
- FIDO Alliance — Passkeys — https://fidoalliance.org/passkeys/ · verified 2026-07-30
- W3C — Web Authentication Level 3, Candidate Recommendation Snapshot, 26 May 2026 — https://www.w3.org/TR/webauthn-3/ · verified 2026-07-30
- NIST SP 800-63B — Digital Identity Guidelines, Authentication and Lifecycle Management — https://pages.nist.gov/800-63-3/sp800-63b.html · verified 2026-07-30