Skip to content

feat(auth-machine): auth state machine for sign-in, sign-up and reset with feature flag#20775

Draft
vbudhram wants to merge 1 commit into
mainfrom
state-machine
Draft

feat(auth-machine): auth state machine for sign-in, sign-up and reset with feature flag#20775
vbudhram wants to merge 1 commit into
mainfrom
state-machine

Conversation

@vbudhram

Copy link
Copy Markdown
Contributor

Because

  • Post-authentication navigation was scattered across handlers and behaved inconsistently across integration types (plain web, Sync, Firefox-non-sync, OAuth web, OAuth native), making routing hard to reason about and risky to change.
  • No single, testable place owned the "where does the user go next" decision after authentication.

This pull request

  • Adds a hand-rolled funnel state machine (funnelReducer + pure routing functions under lib/auth-machine/) that owns the post-auth destination; legacy leaf handlers keep performing side effects, so nothing double-executes.
  • Gates all behavior behind a tri-state authStateMachine override via flag.ts (?authStateMachine=true|false forces on/off; otherwise the config flag decides).
  • Routes sign-in, post-signup-confirmation (ConfirmSignupCode), reset-password, the Settings AAL2 access guard, and InlineTotpSetup through the machine in Signin/utils.ts (handleNavigation).
  • Wires the live-TOTP safety net on the password path in Signin/index.tsx (flag- and verify-gated, with a fallback so it never blocks sign-in).
  • Adds exhaustive Playwright E2E under tests/authMachine/ (sign-in/up across every integration type, reset, TOTP, unblock/FXA-12084, AAL2 guard, off-switch) plus unit coverage of every routing rule.
flowchart TD
    A[Auth result: sign-in / sign-up / reset] --> B{authStateMachine enabled?}
    B -- "off / ?authStateMachine=false" --> L[Legacy leaf handlers - unchanged]
    B -- "on / config / ?authStateMachine=true" --> M[funnelReducer - routing brain]
    M --> R{routeAfterVerify}
    R -- "emailVerified AND sessionVerified" --> H[finalizing.handoff: /settings, Sync CAD, OAuth RP redirect]
    R -- "accountHasTotp OR method=totp-2fa" --> T[verifying.totp: /signin_totp_code]
    R -- "!emailVerified OR reason=SIGN_UP" --> D[delegated.legacy: /confirm_signup_code]
    R -- "session unverified" --> E[verifying.emailTokenCode: /signin_token_code]
    M -. "side effects unchanged" .-> S[sendFxaLogin · finishOAuthFlow · fxaOAuthLogin]
Loading

Issue that this pull request solves

Closes:

Checklist

  • My commit is GPG signed.
  • If applicable, I have modified or added tests which pass locally.
  • I have added necessary documentation (if appropriate).
  • I have verified that my changes render correctly in RTL (if appropriate).
  • I have manually reviewed all AI generated code.

Other information

How to test:

  1. Append ?authStateMachine=true to any sign-in URL (e.g. /signin?authStateMachine=true).
  2. Run through sign-in, sign-up, and reset for web, Sync, and OAuth.
  3. Each flow reaches the same destination as flag-off; ?authStateMachine=false forces legacy.

@vbudhram vbudhram self-assigned this Jun 22, 2026
…p and reset

Because:
 - Post-authentication navigation was scattered across leaf handlers, making
   routing hard to reason about and inconsistent across integration types
   (plain web, Sync, Firefox-non-sync, OAuth web, OAuth native).

This commit:
 - Adds a hand-rolled funnel state machine (funnelReducer) plus pure routing
   functions that own the post-auth destination decision, while legacy leaf
   handlers keep performing the side effects (no double execution).
 - Gates all behavior behind a tri-state authStateMachine override
   (?authStateMachine=true|false forces on/off, absent falls back to config).
 - Routes sign-in, post-signup-confirmation, reset-password (post-OTP decision,
   recovery-choice, completion handoff), the Settings AAL2 access guard and the
   InlineTotpSetup post-setup redirect through the machine.
 - Adds exhaustive Playwright E2E coverage under tests/authMachine/ spanning all
   integration types for sign-in, sign-up, reset, TOTP, unblock (FXA-12084),
   the AAL2 guard and the off-switch, plus unit coverage of the routing rules.
 - Makes the TOTP-setup page-object helper recovery-phone-availability aware so
   the recovery-method chooser is skipped when it is unavailable.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant