# Passkey integration `authwebauthn` is a passkey ceremony service, not a login page or account policy. An application supplies its exact relying-party identity, routes, authorization decisions, session cookie, HTML, and local recovery command. ## Fixed security policy - Use an exact HTTPS origin whose hostname equals the relying-party ID. - Reject cross-origin ceremonies. - Require discoverable credentials and user verification. - Request no attestation conveyance. - Permit ES256 only until another algorithm has explicit interoperability and security evidence. - Store random challenges and verifier session data only behind opaque, single-use ceremony tokens. - Treat clone warnings as audit signals rather than automatic lockout for synchronized passkeys. The service uses a random WebAuthn challenge for every ceremony. A sensitive application operation is bound separately by storing the SHA-256 digest of its canonical payload with that ceremony. Never substitute an operation hash, timestamp, UUID, or counter for the random challenge. ## Application flow 1. A local command calls `Bootstrap` or `Recover` and writes the returned enrollment token once to a newly created mode-`0600` file. 2. A server-rendered enrollment page calls `BeginEnrollment`; the browser uses `navigator.credentials.create` with the returned `public_key` value. 3. The browser posts the credential and opaque ceremony token to a bounded JSON endpoint; `FinishRegistration` verifies and stores the public credential. 4. Login uses `BeginLogin`, `navigator.credentials.get`, and `FinishLogin`. The successful result contains an ordinary opaque `auth` session token. 5. Sensitive operations call `BeginApproval` with a canonical application payload and `FinishApproval` with those exact same bytes. Any drift fails. `authhttp.WritePasskeyBegin` and `authhttp.ReadPasskeyFinish` provide bounded JSON framing only. They do not register routes, authorize requests, serve JavaScript, or set sessions automatically. ## Recovery and credential lifecycle Recovery is deliberately host-local and should never be reachable through an HTTP handler. It revokes all user sessions and pending ceremonies, replaces prior enrollment tokens, appends a secret-free audit event, and returns one 15-minute token. It does not delete existing passkeys. After enrolling a replacement, the operator reviews credential labels and removes lost keys with a fresh passkey-bound removal ceremony. The final passkey cannot be removed remotely. Before enabling production mutations, applications should require at least two independent passkeys and complete a local recovery drill.