Conversation
ba74b4a to
72a9f2d
Compare
There was a problem hiding this comment.
Pull request overview
Enforces “passkey required” sign-in policy for accounts that have enrolled a passkey by blocking passwordless OTP endpoints server-side and teaching the Settings content-server UI (and tests) to redirect/show appropriate banners and routing for passkey-only scenarios (including AAL2/TOTP routing for certain OAuth RPs).
Changes:
- Auth server: gate
/account/passwordless/send_codeand/confirm_codebehind a “no passkey enrolled” check and introducePASSKEY_AUTHENTICATION_REQUIRED(errno 233). - Settings UI: add
mustUsePasskeyredirect/banner handling; hide unsupported passkey UI on browsers lacking WebAuthn L3; add AAL2→TOTP enrollment diversion for passkey sessions. - Tests: add/expand unit + functional passkey test coverage and extend the passkey polyfill with a corruption/tampering mode.
Reviewed changes
Copilot reviewed 27 out of 27 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/fxa-settings/src/pages/Signin/utils.ts | Diverts AAL2-requiring OAuth web flows to inline TOTP setup for passkey sessions lacking TOTP. |
| packages/fxa-settings/src/pages/Signin/utils.test.ts | Adds unit coverage for the new passkey-session AAL2/TOTP diversion logic. |
| packages/fxa-settings/src/pages/Signin/SigninPasswordlessCode/index.stories.tsx | Updates/expands Storybook variants for passkey-enabled passwordless code page. |
| packages/fxa-settings/src/pages/Signin/SigninPasswordlessCode/container.tsx | Redirects to /signin with mustUsePasskey when errno 233 is returned by OTP send. |
| packages/fxa-settings/src/pages/Signin/SigninPasswordlessCode/container.test.tsx | Adds test coverage for the errno 233 redirect behavior. |
| packages/fxa-settings/src/pages/Signin/interfaces.ts | Adds mustUsePasskey, plus navigation fields for passkey-session + TOTP status. |
| packages/fxa-settings/src/pages/Signin/index.tsx | Adds mustUsePasskey banners, hides password form when required, gates passkey button on WebAuthn L3. |
| packages/fxa-settings/src/pages/Signin/index.test.tsx | Adds banner tests for mustUsePasskey supported/unsupported browser scenarios. |
| packages/fxa-settings/src/pages/Signin/index.stories.tsx | Updates passkey-related Signin story variants (including Sync/cached paths). |
| packages/fxa-settings/src/pages/Signin/container.tsx | Wires mustUsePasskey from location state into the Signin decider flow. |
| packages/fxa-settings/src/pages/Signin/components/SigninDecider/index.tsx | Plumbs mustUsePasskey into Signin and SigninAlternativeAuthOptions. |
| packages/fxa-settings/src/pages/Signin/components/SigninAlternativeAuthOptions/index.tsx | Adds mustUsePasskey banners and gates passkey button on WebAuthn L3 support. |
| packages/fxa-settings/src/pages/Signin/components/SigninAlternativeAuthOptions/index.test.tsx | Adds tests for mustUsePasskey banners and WebAuthn L3 support conditions. |
| packages/fxa-settings/src/pages/Signin/components/SigninAlternativeAuthOptions/index.stories.tsx | New Storybook file for linked-passwordless alternative auth options (with passkey variants). |
| packages/fxa-settings/src/pages/Index/index.tsx | Gates Index page passkey sign-in button on WebAuthn Level 3 support. |
| packages/fxa-settings/src/lib/passkeys/signin-flow.ts | Surfaces account TOTP status for AAL2 OAuth web RPs to support TOTP setup diversion. |
| packages/fxa-settings/src/lib/passkeys/signin-flow.test.tsx | Adds unit tests covering accountHasTotp propagation behavior. |
| packages/fxa-settings/src/lib/auth-errors/auth-errors.ts | Adds UI mapping for PASSKEY_AUTHENTICATION_REQUIRED (errno 233). |
| packages/fxa-auth-server/lib/routes/passwordless.ts | Adds passkey enrollment gate to passwordless OTP endpoints; fail-closed on lookup errors. |
| packages/fxa-auth-server/lib/routes/passwordless.spec.ts | Adds tests for passkey gate ordering and fail-closed behavior. |
| packages/functional-tests/tests/passkeyAuth/passkeySetPassword.spec.ts | New E2E for passwordless+passkey → Sync routing to set-password. |
| packages/functional-tests/tests/passkeyAuth/passkeyPasswordFallback.spec.ts | Refactors E2E to drive Sync passkey fallback via real UI flow; adds TOTP variant. |
| packages/functional-tests/tests/passkeyAuth/passkeyEnforcement.spec.ts | New E2E for OTP enforcement redirect + passkey sign-in success path. |
| packages/functional-tests/tests/passkeyAuth/passkey-signin.spec.ts | Expands E2E coverage for AAL2/TOTP combinations and unsupported-browser behavior. |
| packages/functional-tests/lib/passkeyPolyfill.ts | Adds corrupt mode to simulate invalid-signature assertions. |
| libs/accounts/errors/src/constants.ts | Adds errno 233 constant. |
| libs/accounts/errors/src/app-error.ts | Adds passkeyAuthenticationRequired() AppError factory. |
Comments suppressed due to low confidence (2)
packages/fxa-settings/src/pages/Signin/index.tsx:329
- The new FTL id
signin-passkey-unsupported-browser-banneris referenced here but does not appear to be defined inpackages/fxa-settings/src/pages/Signin/en.ftl, so it will fall back to the hardcoded English string and won’t be localizable. Please add the string to the Signin FTL file (and other locales via l10n pipeline as appropriate).
: ftlMsgResolver.getMsg(
'signin-passkey-unsupported-browser-banner',
'Sign-in is not supported on this browser. Use a browser that supports passkeys to continue.'
),
}}
packages/fxa-settings/src/pages/Signin/components/SigninAlternativeAuthOptions/index.tsx:113
- The new FTL id
signin-passkey-unsupported-browser-banneris referenced here but does not appear to be defined inpackages/fxa-settings/src/pages/Signin/en.ftl, so it will fall back to the hardcoded English string and won’t be localizable. Please add the string to the Signin FTL file (and other locales via l10n pipeline as appropriate).
: ftlMsgResolver.getMsg(
'signin-passkey-unsupported-browser-banner',
'Sign-in is not supported on this browser. Use a browser that supports passkeys to continue.'
),
}}
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
d35b453 to
a9022c5
Compare
| } from '../../../mocks'; | ||
| import { MozServices } from '../../../../lib/types'; | ||
|
|
||
| // Renders for linked-passwordless users: only path forward is alt auth. |
There was a problem hiding this comment.
Thanks for adding these missing stories
| </div> | ||
| </form> | ||
|
|
||
| <AlternativeAuthOptions |
Adds a "Continue with passkey" button to the email-first signin flow, gated by the passkeyAuthenticationEnabled feature flag. The button is shown unconditionally to preserve the privacy invariant that /account/status does not signal passkey enrolment. Routes passkey-authenticated sessions through handleNavigation with an isPasskeySession flag so the OAuth signin path can divert AAL2-requiring RPs (AMO-style) to /inline_totp_setup when the account has no TOTP. This matches AMO's profile-based AMR check, which excludes webauthn from availableAuthenticationMethods even though the passkey session itself satisfies session-level AAL2.
vpomerleau
left a comment
There was a problem hiding this comment.
Thanks for the edits, LGTM.
PR description/title doesn't quite align and mentions changes that aren't in this diff, would be good to update for posterity. 🙏
Because
availableAuthenticationMethods, so a passkey-only user satisfied session AAL2 yet was bounced back to FxA in a redirect loop instead of being prompted to enrol TOTPThis pull request
Signin/index.tsx(password-entry page) andSigninAlternativeAuthOptions(email-first), gated by thepasskeyAuthenticationEnabledfeature flag/account/statusdoes not leak passkey enrolmentsignin-flow.test.tsxandutils.test.ts(passkey-session AAL2 gate cases) plus stories for the new alternative-auth UIIssue that this pull request solves
Closes: https://mozilla-hub.atlassian.net/browse/FXA-13101
Checklist
Other information
Companion PR: FXA-13103 adds the Playwright coverage for these flows (passkey signin paths + AMO profile-AAL2 divert) and a 123done toggle that mirrors AMO's profile-based enforcement. It should land after this one.
How to test
passkeysEnabled,passkeyRegistrationEnabled,passkeyAuthenticationEnabled/, then click "Continue with passkey" from email-first or after submitting an emailacr_values=AAL2flow on a passkey-only account, sign in with passkey, should land on/inline_totp_setup, not the RP