Passkeys
A second factor a convincing copy of your sign-in page cannot capture.
Why this is different from TOTP
A six-digit code can be typed into a fake page and replayed within its window. A passkey cannot: the browser binds the credential to the origin it was created for and refuses to sign for a different one. The user does not have to notice the phishing, because the credential does.
Two practical consequences beyond security:
No mail sending required. A deployment can demand a second factor without an SMTP configuration, which removes the most common reason a small project ships without one.
No password at all, optionally. An authenticator that verifies its user by biometric or PIN replaces the password rather than supplementing it, which removes the entire class of problems that starts with somebody reusing one.
Enabling it
Passkeys are on for every account. A user adds one from their account page and can register several: a phone and a hardware key, so losing one is not losing access.
To require one, set the policy on the role rather than per user. Any role that can change content or credentials should have it.
What we store
| Value | Why |
|---|---|
| Credential id | Identifies which key is being used |
| Public key | Verifies the signature |
| Sign count | Detects a cloned authenticator |
| Transports | Lets the browser prompt for the right thing |
| AAGUID | Names the model, so the list reads "YubiKey 5" not a hex string |
There is no private key here and never can be. It stays in the authenticator, which is what makes a database dump useless against a passkey.
The counter check
An authenticator increments a counter on every use. A value that fails to advance is the documented signal that the credential has been copied.
We do not merely refuse that sign-in: the credential is removed. If it has been cloned, the clone works too, so leaving it registered would leave the account open to whoever holds the copy.
Some authenticators, notably those syncing through a platform keychain, do not implement a counter and always report zero. That is expected and is not treated as a clone.
Losing your only key
Deleting the last passkey is refused when the account has no password, because a single click would otherwise lock somebody out with no way back. Set a password first, or register a second key.
If both are gone, an administrator resets the account so the user can enrol again. They never learn a credential in the process, and the reset is recorded.