Security model
Why passkeys stop phishing, what Gatekeep stores and how, and the protections around codes, sessions, refresh tokens and recovery.
Phishing resistance
A passkey is a key pair. The private key stays on the user’s device or in their synced keychain; Gatekeep keeps only the public key. Each passkey is bound to your Gatekeep domain. The browser won’t use it anywhere else, so a lookalike site can’t get a signature, however convincing it looks. There’s no password or one-time code for anyone to type into the wrong page.
What we store, and how
| Thing | Stored as |
|---|---|
| Passkey | Public key and a signature counter only |
| Sessions, authorization codes, refresh tokens, magic links | SHA-256 hashes |
| Signing keys | Encrypted at rest with AES-GCM |
| Email address | Plain, so we can send links. Lowercased for matching |
Because every bearer secret is stored hashed, a copy of the database contains nothing an attacker can use to sign in or call an API.
Protections, flow by flow
- Authorization: the client ID and redirect URI are checked before anything else. A bad redirect URI gets an error page, never a redirect.
- Code exchange: PKCE with S256 is required. Codes last 60 seconds and work once.
- Passkey sign-in: every challenge is single-use and expires after 5 minutes. Authenticator sign counts must increase; a passkey whose count goes backwards looks cloned, and is revoked.
- Refresh tokens: rotated on every use. Reusing an old one revokes the whole chain. See Refresh tokens.
- Sessions:
HttpOnly,Secure,SameSite=Laxcookies that last 30 days and slide forward while in use. - Recovery: completing it revokes every existing passkey on the account.
- Account enumeration: signup and recovery give the same response whether or not an address has an account.
Token signing
Tokens are signed with Ed25519 (EdDSA). Keys rotate on a schedule. The old key stays in your JWKS for 35 days after it stops signing, so no valid token stops verifying mid-rotation.
Reporting a vulnerability
Found something? Contact us and choose Security report. Please give us a chance to fix it before you publish.