Expand description
Passkey (WebAuthn) sign-in — the relying-party instance built from config
(docs/archive/WEBAUTHN_DESIGN.md). This is the foundation: the configured
[webauthn_rs::prelude::Webauthn] relying party as Rocket managed state. The
registration/authentication ceremonies and the sign-in UI build on this in the following
increments.
The relying party is the CorTeX server itself — no external IdP, no per-deployment app
registration. Passkeys are the convenient day-to-day human sign-in; the admin token
(frontend::actor) remains the bootstrap / break-glass / agent credential. Passkeys never block
the token path: a disabled or misconfigured relying party degrades to None (logged), and
sign-in still works via the token.
Structs§
- Ceremony
Store - A short-lived, process-local store of in-flight ceremonies. Ceremonies live seconds, so an
in-memory map (pruned on insert, capacity-bounded by the TTL) is sufficient and needs no
danger-allow-state-serialisation. Mutex poisoning is recovered from, never panicked on (this is a request path —docs/DESIGN_PRINCIPLES.md). - Passkey
Dto - A passkey as shown on the management page.
- Webauthn
State - The configured WebAuthn relying-party instance, shared as Rocket managed state. Present only when passkeys are enabled and the relying party built successfully; absent ⇒ token sign-in only.
Enums§
- Ceremony
- In-flight WebAuthn ceremony state, kept server-side between the begin and finish requests
(never serialized to the client) and keyed by a random id in the [
CEREMONY_COOKIE].
Functions§
- auth_
begin - Sign in, step 1 (
POST /admin/passkeys/auth/begin?owner=): begins a passkey authentication for the named owner, seeded by that owner’s enrolled passkeys. Returns the WebAuthnRequestChallengeResponsefornavigator.credentials.get()and stashes the ceremony state.404if the owner has no enrolled passkeys (admin identities are not treated as secret — the public deployment sits behind an Anubis proxy and the admin set is small),503if disabled. - auth_
finish - Sign in, step 2 (
POST /admin/passkeys/auth/finish): completes the assertion. On success opens apasskeysession (the unified session model), sets theADMIN_COOKIE, advances the matching credential’s signature counter (clone detection), and returns200— the browser then navigates to/admin.400on a missing/expired ceremony,401if the assertion doesn’t verify. - build_
state - Builds the relying-party [
Webauthn] from config, or returnsNone(logged, never panics) when passkeys are disabled or therp_id/rp_originare invalid — token sign-in keeps working either way (graceful degradation, the robustness mandate). - passkey_
delete - Removes one of the signed-in admin’s passkeys (
POST /admin/passkeys/<id>/delete); theownerfilter means a session can only remove its own. Redirects back to the management page. - passkeys_
page - The “Your passkeys” management screen (
GET /admin/passkeys): the signed-in admin’s enrolled passkeys, with enroll + remove actions. Signed-in admins only (unauthenticated → sign-in page). - register_
begin - Enroll, step 1 (
POST /admin/passkeys/register/begin): a signed-in admin starts registering a new passkey for their own identity. Returns the WebAuthnCreationChallengeResponseJSON fornavigator.credentials.create()and stashes the ceremony state server-side (cookie-keyed).401if not signed in,503if passkeys are disabled. Already-enrolled credentials are excluded so the same authenticator isn’t registered twice. - register_
finish - Enroll, step 2 (
POST /admin/passkeys/register/finish?label=): finishes registration with the authenticator’s response, persisting the new passkey (public key only) under an optionallabel.400if the ceremony cookie/state is missing or the attestation doesn’t verify. - routes
- The passkey routes (the management page + the enrollment ceremony).