Skip to content

fix: clear request failure data and handle HTTP errors in Reauthentication middleware - #94345

Closed
mountiny wants to merge 1 commit into
mainfrom
fix-reauthentication-middleware-tests
Closed

mountiny wants to merge 1 commit into
mainfrom
fix-reauthentication-middleware-tests

Conversation

@mountiny

Copy link
Copy Markdown
Contributor

Explanation of Change

When reauthenticate() returns false (the user is being redirected to sign-in), the middleware was returning undefined without clearing failureData/finallyData from the request. Because SaveResponseInOnyx only skips Onyx writes when all of successData, failureData, and finallyData are absent, those values were still being applied — causing callers to incorrectly see shouldFailAllRequests or shouldForceOffline set to true after a sign-in redirect.

Two fixes:

  1. When reauthentication fails, delete request.failureData and request.finallyData then return the original response data so callers get the correct jsonCode and SaveResponseInOnyx does not apply stale failure values.
  2. HTTP errors on the Authenticate command (e.g. 403 Forbidden) now resolve with the actual status code and message instead of the generic unableToRetry, so the caller can surface the correct error.

Fixed Issues

$ #94292
PROPOSAL:

Tests

  • Verify that no errors appear in the JS console

Unit tests added in tests/unit/ReauthenticationMiddlewareTest.ts covering all four scenarios:

  1. Failed reauth clears failureData and finallyData and returns original response
  2. Failed reauth does not apply Onyx failure updates
  3. Authenticate HTTP errors resolve with the HTTP status/message
  4. Offline 407 does not trigger reauthentication

Offline tests

N/A — middleware logic is network-state aware; offline 407 path is already tested.

QA Steps

No visible UI change. Unit tests cover the regression path.

  • Verify that no errors appear in the JS console

PR Author Checklist

  • I linked the correct issue in the ### Fixed Issues section above
  • I wrote clear testing steps that cover the changes made in this PR
    • I added steps for local testing in the Tests section
    • I added steps for the expected offline behavior in the Offline steps section
    • I added steps for Staging and/or Production testing in the QA steps section
    • I added steps to cover failure scenarios (i.e. verify an input displays the correct error message if the entered data is not correct)
    • I turned off my network connection and tested it while offline to ensure it matches the expected behavior (i.e. verify the default avatar icon is displayed if app is offline)
  • I included screenshots or videos for tests on all platforms
  • I followed proper code patterns (see Reviewing the code)
    • I verified that any callback methods that were added or modified are named for what the method does and never what callback they handle (i.e. toggleReport and not onIconClick)
    • I verified that comments were added to code that is not self explanatory
    • I verified that any new or modified comments were clear, correct English, and explained "why" the code was doing something instead of only explaining "what" the code was doing.
    • I verified all numbers, amounts, dates and phone numbers shown in the product are using the localization methods
    • I verified proper file naming conventions were followed for any new files or renamed files. All non-platform specific files are named after what they export and are not named "index.js". All platform-specific files are named for the platform the code supports as outlined in the README.
  • If a new code pattern is added I verified it was agreed to be used by multiple Expensify engineers
  • I followed the guidelines as stated in the Review Guidelines
  • I tested other components that can be impacted by my changes (i.e. if the PR modifies a shared library or component like Avatar, I verified the components using Avatar are working as expected)
  • I verified all code is DRY (the PR doesn't include any logic written more than once, with the exception of tests)
  • I verified any variables that can be defined as constants (ie. in CONST.ts or at the top of the file that uses the constant) are defined as such
  • I added unit tests for any new feature or bug fix in this PR to help automatically prevent regressions in this user flow.

Screenshots/Videos

N/A — middleware-only change with no UI

Made with Cursor

…ation middleware

When reauthentication returns false (redirecting to sign-in), the middleware
was returning undefined without clearing failureData/finallyData from the
request, causing SaveResponseInOnyx to still apply them. This made callers
incorrectly see shouldFailAllRequests or shouldForceOffline set to true after
a sign-in redirect.

Also handle HTTP errors on the Authenticate command (e.g. 403 Forbidden) by
resolving the request with the actual HTTP status code and message rather
than the generic unableToRetry code, allowing callers to display the correct
error to the user.

Co-authored-by: Cursor <cursoragent@cursor.com>
@mountiny
mountiny requested review from a team as code owners June 23, 2026 18:15
@melvin-bot
melvin-bot Bot requested review from Krishna2323 and trjExpensify June 23, 2026 18:15
@melvin-bot

melvin-bot Bot commented Jun 23, 2026

Copy link
Copy Markdown

@Krishna2323 Please copy/paste the Reviewer Checklist from here into a new comment on this PR and complete it. If you have the K2 extension, you can simply click: [this button]

@melvin-bot
melvin-bot Bot removed request for a team June 23, 2026 18:15
@mountiny
mountiny marked this pull request as draft June 23, 2026 18:17

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c534586940

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +150 to +152
if (request.command === 'Authenticate' && error instanceof HttpsError) {
if (request.resolve) {
request.resolve({jsonCode: Number(error.status), message: error.message, title: error.title});

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Preserve retries for transient Authenticate HTTP errors

When the Authenticate request hits a transient HTTP HttpsError such as 500/502/504/520, 429, or the forced-offline Failed to fetch path with an empty status, this branch now resolves with that status instead of UNABLE_TO_RETRY. The reauthentication caller only retries when it sees UNABLE_TO_RETRY; any other non-200 response is treated as an authentication failure and redirects the user to sign-in, so a temporary Auth/site outage during token refresh can incorrectly log users out rather than using the existing retry throttle.

Useful? React with 👍 / 👎.

@mountiny

Copy link
Copy Markdown
Contributor Author

Closing: the identical fix was already merged to main via PR #91619 (fix: sign out user when session expires). Local main branch was stale.

@mountiny mountiny closed this Jun 23, 2026
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