Skip to content

fix(settings,auth): Fix sumo login issue#20601

Open
dschom wants to merge 4 commits into
mainfrom
worktree-FXA-12972
Open

fix(settings,auth): Fix sumo login issue#20601
dschom wants to merge 4 commits into
mainfrom
worktree-FXA-12972

Conversation

@dschom
Copy link
Copy Markdown
Contributor

@dschom dschom commented May 14, 2026

Because

  • Users of non-Sync OAuth RPs (e.g. SUMO) were receiving verifyLoginCode emails on signin even though the auth-server had correctly decided the session did not need verification (mustVerify=false).
  • We ultimately traced this back to cachedSignIn in fxa-settings firing POST /session/resend_code based solely on sessionVerified=false flag and ignoring the mustVerify flag.
  • The React rewrite dropped a mustVerify guard that fxa-content-server still had at views/base.js#checkAuthorization.

This pull request

  • Exposes mustVerify on the GET /session/status response (auth-server Joi schema + handler return; auth-client SessionStatus type).
  • Gates the unverified-session branch of cachedSignIn (packages/fxa-settings/src/pages/Signin/utils.ts) on mustVerify=true, restoring parity with the legacy content-server guard. When mustVerify=false, no resend fires and verificationReason/verificationMethod stay undefined so the user routes past the verification page instead of being stranded on it.
  • Adds unit tests for cachedSignIn (none existed): both branches, TOTP active, OAuth prompt=none, already-verified sessions, and the SESSION_EXPIRED error path.
  • Extends packages/fxa-auth-server/test/remote/session_tests.in.spec.ts to round-trip mustVerify for keys=true and keys=false, and configures that suite to start the auth-server with signinConfirmation.skipForNewAccounts.enabled=false so the new assertions are deterministic.

Issue that this pull request solves

Closes: FXA-12972

Checklist

Put an x in the boxes that apply

  • 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.

How to review (Optional)

  • Key files/areas to focus on:
    • packages/fxa-settings/src/pages/Signin/utils.ts — the front end fix (one new && mustVerify guard).
    • packages/fxa-auth-server/lib/routes/session.js — the new field on /session/status.
  • Suggested review order: auth-server route change → auth-client type → fxa-settings gate → unit tests → remote tests.
  • Risky/complex parts: no end-to-end functional smoke test was added. See comments below...

Other information

Tracking this bug down was a little twisty, so a full diagnosis of problem is attached to FXA-12972

Also worth noting, that we tried to create a smoke-test to cover this edge case but could not, since the state hinged on the signinConfirmation.skipForNewAccounts option which is set to 48 hours currently. Becuase this time lapse is quite large, there's no really a good way to trip this state in a functional test. The interactions between these flags and options (mustVerify, sessionVerified, accountVerified, lockedAt, skipForNewAccounts, etc...) is pretty complex, so it'd be worth while clearly demarcating these states.

The unit-level coverage proves the fix; however, in order to get functional test coverage we need either a pre-provisioned long-lived fixture account on each environment or an admin-API path to alter an existing account state. A follow spike was added to look into how to make get better test coverage around this.

} else if (!sessionVerified) {
// we are inferring verification method and verification reason here
// ideally we would check the server directly to allow for more verification reasons
} else if (!sessionVerified && mustVerify) {
Copy link
Copy Markdown
Contributor Author

@dschom dschom May 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@LZoog All the other changes, support this small update to the front end logic... I'm still pondering if there's a simpler way to achieve this, but basically we should invoking line 176, if the session doesn't actually require verification...

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Smells a bit to me that we are handling these checks client-side. Perhaps we could update /session/resend_code to confirm whether the session still needs verification and return if a code was sent or not, to inform client-side navigation?

Copy link
Copy Markdown
Contributor Author

@dschom dschom May 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also considered this and I mostly agree with what you are saying. However, this was deemed a riskier option and it still doesn't entirely clean this up...

The two issues with that approach seem to be:

  1. In this case, we would make the call, and then fail. The reality is that we do not need the extra call. So the client side is still do something unnecessary / wrong.

  2. The other, probably bigger, concern is that this could lead to scenarios where a user is being prompted by the UI for a code, the do something to invoke session.resendCode. We then start erroring on the server side, and the user is now stuck.

I guess we've had enough issues around verified session states, that I'm a little hesitant to do something that might result in other issue. In someways, I think exposing the account model state to the front end more fully is better than making unnecessary calls and then seeing waiting for errors. It's possible that by exposing this flag to the front end, we can actually make better decisions about what to do. This scenario is actually a good example of that.

The other thing I don't quite get, and maybe this yet another way to address the problem. Why are we invoking resendCode here? Shouldn't that send happen on the page that is asking for the code?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The server generally handles sending the code. It's not usually triggered by the frontend except here. There must be something else funky that's leading to the exception.

dschom and others added 3 commits May 14, 2026 17:16
Because:
- Adding `mustVerify` to `/session/status` and gating
  `cachedSignIn` on it broke existing tests that didn't yet
  know about the new field.

This commit:
- Adds `mustVerify: false` to the seven `/session/status`
  assertions in session.spec.ts so they match the handler's
  new response shape.
- Adds `mustVerify: true` to the two `cachedSigninHandler`
  mocks in container.test.tsx that expect the unverified
  branch to fire.
- Drops the `signinConfirmation.skipForNewAccounts.enabled=false`
  configOverrides from the remote session_tests suite — under
  defaults, mustVerify cleanly tracks `wantsKeys`, which is what
  the keys=true/keys=false round-trip tests are checking.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Because:
- The whole point of FXA-12972 is to stop sending verifyLoginCode
  emails to non-Sync OAuth RPs (e.g. SUMO) when the auth-server
  has decided the session does not need verification. Without a
  test pinning this behavior, a future regression would be silent.

This commit:
- Adds a cachedSigninHandler test asserting that with
  mustVerify=false and sessionVerified=false, no verification
  code is sent and verificationMethod/verificationReason stay
  undefined.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…fy expectations

Because:
- The previous attempt removed the configOverrides block to make
  the keys=true/keys=false round-trip tests deterministic under
  defaults. That broke the existing 'reauth has sane
  session-verification behaviour' tests (which depend on the
  forced-confirmation behaviour to keep new-account sessions in
  the 'unverified' state) and the keys=true case (which under
  defaults gets pre-verified and never sets mustVerify=true).
- The keys=false test as authored is unworkable under either
  config: with the override, every new login sets mustVerify=true
  regardless of the keys argument; without it, new accounts skip
  signin confirmation entirely and mustVerify stays false but the
  session is also auto-verified.

This commit:
- Restores the signinConfirmation.skipForNewAccounts.enabled=false
  configOverrides block, with a comment explaining why.
- Updates 'succeeds with valid token' to expect mustVerify=true
  (which is what the server actually returns when signin
  confirmation is forced).
- Replaces the keys=true/keys=false pair with a single test that
  exposes the mustVerify field for a session that requires
  verification. The falsy case is already covered by the unit
  tests in lib/routes/session.spec.ts.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@dschom dschom marked this pull request as ready for review May 15, 2026 01:03
@dschom dschom requested a review from a team as a code owner May 15, 2026 01:03
@dschom dschom changed the title WIP - Fix sumo login issue fix(settings,auth): Fix sumo login issue May 15, 2026
@vpomerleau vpomerleau requested a review from Copilot May 15, 2026 17:41
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes an FxA Settings sign-in regression where cachedSignIn would resend verification codes (and strand users on the verification page) whenever sessionVerified=false, even when the auth-server had determined the session did not require verification (mustVerify=false, e.g., SUMO-style OAuth RPs). It does this by exposing mustVerify via /session/status and gating the resend/verification routing behavior on that flag, with accompanying unit + remote integration tests.

Changes:

  • Expose mustVerify on GET /session/status (auth-server response schema + handler return) and add it to the auth-client SessionStatus type.
  • Update fxa-settings cachedSignIn to only route/send verification codes for unverified sessions when mustVerify=true.
  • Add/extend tests in fxa-settings and fxa-auth-server to cover the new behavior and ensure deterministic auth-server session-state behavior.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated no comments.

Show a summary per file
File Description
packages/fxa-settings/src/pages/Signin/utils.ts Gate the unverified-session verification flow on mustVerify to prevent unnecessary resend + verification routing.
packages/fxa-settings/src/pages/Signin/utils.test.ts Add unit coverage for cachedSignIn, including mustVerify branches and error handling.
packages/fxa-settings/src/pages/Signin/container.test.tsx Add a regression test ensuring unverified + mustVerify=false skips verification/resend.
packages/fxa-settings/src/models/mocks.tsx Update auth client mock sessionStatus details to include mustVerify.
packages/fxa-auth-server/test/remote/session_tests.in.spec.ts Make session-state deterministic via config override and assert mustVerify is exposed as expected.
packages/fxa-auth-server/lib/routes/session.spec.ts Update /session/status route unit test expectations to include mustVerify.
packages/fxa-auth-server/lib/routes/session.js Add mustVerify to /session/status response schema and handler output.
packages/fxa-auth-client/lib/client.ts Extend SessionStatus type with mustVerify.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

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.

3 participants