DEV Community

vdelitz
vdelitz

Posted on Originally published at corbado.com

Passkeys Explained Clearly for Developers

What a passkey actually is

Vincent Delitz’s 2026 guide on passkeys is a practical explanation of the parts teams still mix up: what a passkey is, why it is phishing-resistant, and why shipping it does not guarantee anyone will use it.

The simplest mental model is this: a passkey is a cryptographic key pair for signing a user in to a service. It is not the same thing as Face ID, a fingerprint sensor, an OTP, or a hardware key, even if those often appear in the same conversation.

That distinction matters because the user gesture looks familiar while the security model is completely different. Local biometrics unlock something on one device. A passkey uses that same gesture to authorize the use of a private key, and the server verifies the result with a public key it already has.

So if someone asks what is a passkey, the short answer is: a passkey is a FIDO2/WebAuthn credential backed by a key pair, where the private key stays with the user and the server stores only a public key.

Why passkeys are not just biometrics

A lot of passkeys vs biometrics confusion comes from the UX. Users see a face scan or fingerprint prompt in both cases, so teams assume they are interchangeable. They are not.

  • Local biometric auth: proves the user can unlock the current device.
  • Passkey auth: proves the user controls a private key registered to a service.
  • Server visibility: local biometrics tell the server nothing; passkeys produce a verifiable signature.
  • Portability: passkeys can work across devices through synced providers or cross-device flows.

That is also why passkeys are often described as phishing-resistant MFA WebAuthn FIDO2 in one package. The device is one factor. The local unlock method is the second factor, whether that is biometrics or a PIN.

Where phishing resistance really comes from

The core security property is not “users are smarter” or “the prompt is harder to fake”. It is origin binding.

Passkeys are bound to a Relying Party ID, often shortened to rpID. At login, the browser checks whether the current site belongs to that rpID. If it does not, the passkey is not offered.

Passkey created for: example.com
Valid on: example.com, login.example.com
Invalid on: example-login.com, example.co, com
Enter fullscreen mode Exit fullscreen mode

This is the key point behind RP ID relying party ID passkeys: the browser enforces the relationship between the credential and the real domain. On a fake site, there is no warning for the user to ignore because the passkey prompt never appears.

That is a fundamentally different security story from SMS OTP, TOTP, or push. Those methods can still be relayed through a phishing proxy. Passkeys cannot, because the credential is scoped to the legitimate domain from the start.

Synced vs device-bound passkeys

The synced vs device-bound passkeys split is where architecture decisions get real.

Type Best for Main advantage Main tradeoff
Synced passkeys Consumer apps and broad reach Recovery and cross-device availability Less strict device control
Device-bound passkeys Regulated access and admin accounts Sole control and attestation No sync, so recovery is harder

This maps directly to NIST SP 800-63B AAL2 AAL3 passkeys discussions. Syncable passkeys top out at AAL2. Device-bound authenticators with attestation are what fit AAL3 requirements.

In practice, that usually means consumer services start with synced passkeys, while high-assurance or privileged accounts add device-bound options.

Why adoption fails after launch

The most useful product insight in the guide is that passkey adoption is not one number. It is creation times usage.

If users create passkeys but keep logging in with password plus OTP, adoption is weak. If the passkey option is buried in settings, creation is weak. A zero on either side kills the result.

Two implementation patterns matter a lot here:

  • conditional create passkeys: prompt right after a successful login, inside a trusted session
  • conditional UI: surface saved passkeys directly in the login field so they become the default path

And there is a strong production signal behind this work. The FIDO Passkey Index reports 93% login success for passkeys versus 63% for other methods.

The main engineering lesson is simple: WebAuthn correctness is not enough. You also need rollout logic, feature detection, and fallback paths, especially where conditional create support is uneven.

Read the full breakdown.

Top comments (0)