Add WebAuthn passkey login alongside email OTP#712
Merged
Conversation
Adds passkeys as a second, faster sign-in mechanism while OTP remains the baseline and recovery path. Registered passkeys live in Realtime Database; the server mints a Firebase custom token via the same single line the OTP flow uses, so no new Firebase Auth surface is introduced. - Cloud Functions: generate/verify registration and authentication options, remove-credential, expired-challenge cleanup. - Client util src/util/webauthn.ts does not import firebase/auth; saga reuses the existing requestFirebaseAuthentication action. - Login page gains a passkey button; profile page gains a passkey manager; post-login banner prompts first-time setup. - Gated behind a passkeysEnabled flag, default false.
c477813 to
9859a1e
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds passkeys (WebAuthn) as an optional, faster sign-in mechanism alongside the existing email OTP flow. OTP remains the baseline and recovery path; passkeys are purely additive and feature-flagged per-environment.
Server (Cloud Functions,
functions/auth/)generateRegistrationOptions/verifyRegistration— passkey enrolmentgenerateAuthenticationOptions/verifyAuthentication— passkey sign-in, mints a Firebase custom token on success (same mechanism the OTP flow uses)removePasskey— user-initiated removalcleanupExpiredWebauthnChallenges— scheduled (hourly) cleanupwebauthnHelpers— atomic challenge consume via RTDBtransaction(), AuthError, RP config, ID-token verificationClient
src/util/webauthn.ts— thin wrapper around@simplewebauthn/browser; does NOT importfirebase/auth(saga reuses the existingrequestFirebaseAuthenticationflow)StyledOrContainerseparator), conditionally rendered when__CONF__.passkeysEnabled && isPasskeySupported()PasskeyManagersection — list with device name, created date, last used date; remove via styled modal confirmation (matchesMovementDeleteConfirmationDialogpattern)PostLoginPasskeyPrompt— post-login card shown to users without any passkey, styled identically toInstallCard; two-strike dismiss with "Später" → "Nicht mehr anzeigen" pattern; auto-labels from user agent (iPhone / iPad / Mac / Windows / Android / Linux)authmodule slice handlesREGISTER_PASSKEY,LOGIN_WITH_PASSKEY,LOAD_PASSKEYS,REMOVE_PASSKEYwith success/failure actionsInfra
webauthnCredentials(read self/admin, writes server-only),webauthnChallenges(server-only),webauthnCredentialOwners(server-only index)@simplewebauthn/browserv13 added to root;@simplewebauthn/serverv10 added to functionspasskeysEnabled: falseinprojects/default.json; enabled viaenvironments.<env>.passkeysEnabled: true(uses the env-merge capability from Merge selected environment config into __CONF__ #710)firebase functions:config:set webauthn.rpid=... webauthn.origins=...Security posture
.transaction()(prevents concurrent re-use)generateAuthenticationOptionsreturns plausible empty-allowList options for unknown emailsTest plan
npm test— 1915 tests pass (includes new specs forwebauthn.ts,PasskeyLoginButton,PasskeyManager,PostLoginPasskeyPrompt, all auth module additions)cd functions && npm test— 278 tests pass (6 new spec files for the webauthn functions)npm run typecheckcleanlszm-test: enable passkey login via profile, sign out, sign back in with passkey, remove passkey, verify OTP still workspasskeysEnabled: falsethat the UI remains unchanged