Added a new task markdown file `2026-0824.01.jul.feat.webauthn.prf-extension-1200.md` detailing the plan for integrating the WebAuthn PRF extension. It outlines the schema updates, client and server flow implementations, and progressive fallback logic as per Kanban guidelines. Co-authored-by: mrteye <1945243+mrteye@users.noreply.github.com>
4.0 KiB
4.0 KiB
TASK METADATA
- Target Files:
server/main.ts,server/db.ts,ui/public/auth-client.js,ui/components/RegisterPage.tsx,ui/components/LoginPage.tsx - Core Objective: Implement WebAuthn PRF extension support for progressive feature detection and Key Encryption Key (KEK) derivation during registration and login, with graceful fallback.
- Dependencies: WebCrypto API natively in Deno/browser, SimpleWebAuthn v13 for passing PRF extension options.
- Additional Important Notes: This task establishes the PRF derivation pipeline. SSS multi-share reconstruction will integrate in a future story (3.3). If PRF is unsupported, registration/login must proceed normally without breaking standard WebAuthn flows.
Architectural Considerations & Risks
- Risks:
- Authenticator Compatibility: Not all authenticators support the WebAuthn PRF extension. A hard failure when PRF is missing would lock users out. The progressive fallback design is critical to prevent regressions in standard authentication.
- Extension Types & SDK Mapping: Passing the exact extension payloads for PRF (
eval.first,eval.second) ingenerateRegistrationOptionsandgenerateAuthenticationOptionsmight require careful type mapping ifSimpleWebAuthntypes are strict. - Database Migrations: Modifying the
passkeystable to includeprf_enabledandprf_saltmust maintain compatibility with existing passkey rows (which will default to false/null).
- Alternatives:
- Traditional server-side wrapping (HSM/KMS) or user passwords could be used for key derivation. However, the WebAuthn PRF extension natively binds the encryption key material to the hardware authenticator itself, preserving Auth-Yes's passwordless UX and zero-trust properties without transmitting raw secrets.
Proposed Implementation
1. Database Schema Updates (server/db.ts)
- Modify the
passkeystable schema to include aprf_enabled BOOLEAN DEFAULT FALSEcolumn. - Add a
prf_saltcolumn (binary or hex string) to store the 32-byte cryptographic salt generated during registration.
2. Registration Flow (Server & Client)
- Server (
server/main.ts): In the/api/register/challengeendpoint, ensure theprf: {}extension is requested viagenerateRegistrationOptions. - Client (
ui/public/auth-client.js): Executenavigator.credentials.create()through the client SDK. ExtractgetClientExtensionResults()?.prf. - Server (
server/main.ts): In the/api/register/verifyendpoint, inspect the extension results to check if PRF is enabled (prf.enabled === true). If supported, generate a 32-byte secure random salt (prf_salt). Storeprf_enabled: trueand theprf_saltalongside the new passkey record.
3. Login Flow (Server & Client)
- Server (
server/main.ts): In the/api/login/challengeendpoint, retrieve the user'sprf_saltif their passkey hasprf_enabled. Include theprf: { eval: { first: <prf_salt> } }extension payload ingenerateAuthenticationOptions. - Client (
ui/public/auth-client.js):- Execute
navigator.credentials.get()with the provided PRF evaluation salt. - Check
getClientExtensionResults()?.prf?.results?.firstfor the PRF output.
- Execute
- Client-Side KEK Derivation:
- If PRF output exists, use it as Input Keying Material (IKM) for WebCrypto HKDF to derive a 256-bit AES-GCM Key Encryption Key (KEK).
- HKDF Parameters:
- Hash:
SHA-256(RFC 5869) - Salt: 32-byte cryptographic salt (stored with passkey record)
- Info:
new TextEncoder().encode("auth-yes:prf:device-share:v1")
- Hash:
- Progressive Fallback:
- If
getClientExtensionResults()?.prfis missing or fails, gracefully bypass the KEK derivation step and continue standard signature-only WebAuthn login.
- If
4. UI Integration (ui/components/RegisterPage.tsx, ui/components/LoginPage.tsx)
- (Optional but recommended) Include minor, non-blocking UI indicators or debug logs to signify when advanced hardware encryption (PRF) is successfully negotiated, aiding in development and progressive feature adoption.