Skip to content

Passkeys / WebAuthn

Native browser WebAuthn APIs for phishing-resistant, passwordless authentication. No client-side wrapper libraries — server-side verification libraries are listed in the overview.

Polyfill requirement: Install webauthn-polyfills in every project. The JSON helpers and getClientCapabilities() are Baseline Newly Available (2025); the polyfill backfills during the browser adoption window.

I need to...

I need to... Guide Summary
Verify HTTPS, RP ID, and server library before writing passkey code Passkeys Prerequisites & Overview Verify HTTPS context, consistent RP ID, and residentKey:required before writing passkey code. Use getClientCapabilities() to gate UI. Server-side: pick a vetted library (SimpleWebAuthn for JS/TS); never hand-roll WebAuthn crypto.
Register a new passkey from a button or settings panel Passkey Registration Use residentKey:required for discoverable credentials. Segregate try/catch into two blocks — inner wraps credentials.create() (abort on catch, never signal), outer wraps the server fetch (signal signalUnknownCredential on rejection).
Silently register a passkey right after a successful password login Conditional Create Trigger immediately after a complete password-based sign-in. Abort any active autofill controller first. Pass mediation:'conditional' to suppress the blocking modal. Never render error UI for InvalidStateError or NotAllowedError.
Implement passkey sign-in (autofill suggestions or button) Passkey Authentication Run initConditionalAutofill() on DOMContentLoaded with mediation:'conditional'. Button flow must abort the autofill controller first, then re-arm autofill after exiting. Signal signalUnknownCredential only on HTTP 404.
Show users their saved passkeys and allow rename or delete Passkey Management Call signalAllAcceptedCredentials on page load and after every delete. All Signal API calls require Base64URL strings — never ArrayBuffer rawId. Gate every call with feature detection; Firefox does not support it.
Re-verify a signed-in user before a sensitive action Passkey Reauthentication Populate allowCredentials with the current user's credential IDs — never leave it empty. After signature verification, assert the credential belongs to req.user.id. Button-only trigger — never autofill.