redirect 2FA in incognito while 2FA is enabled - #93656
Conversation
|
@mkhutornyi 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] |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 049d508b5d
ℹ️ 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".
Codecov Report✅ Changes either increased or maintained existing code coverage, great job!
|
Reviewer Checklist
Screenshots/VideosAndroid: HybridAppAndroid: mWeb ChromeiOS: HybridAppiOS: mWeb SafariMacOS: Chrome / Safariweb.mov |
|
Codex Review: Didn't find any major issues. Nice work! Reviewed commit: ℹ️ About Codex in GitHubCodex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
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". |
Code ReviewReviewed the rewrite of the redirect 1.
|
|
I think neither needs a fix here @mkhutornyi
The second handleExitToNavigation can’t happen. The re-run it describes requires ValidateLoginPage to still be mounted when isSignedIn flips — but it isn’t. The moment canCompleteTwoFactorOnSignIn becomes true, isNavigationReady().then(...) resets the stack to SCREENS.HOME, and SCREENS.HOME (SignInPage) and SCREENS.VALIDATE_LOGIN are sibling routes in the same public RootStack, so the reset removes VALIDATE_LOGIN and unmounts this page — within a microtask of canComplete becoming true. |
navigationRef.isReady() re-check. Agreed this is informational. reset() no-ops gracefully if the container is mid-remount, the “2FA required” modal stays rendered as the fallback, and not re-checking after isNavigationReady() matches the existing convention in Navigation.ts. Combined with the !isSignedIn gate and the unmount above, I’ll leave it as-is to match convention . |
| // page above (the token lands and resolves the shared sign-in promise) — landing them on their | ||
| // destination instead of Home. For a non-2FA account it's the normal post-sign-in handoff. | ||
| if (exitTo) { | ||
| handleExitToNavigation(exitTo); |
There was a problem hiding this comment.
This is now also called when canCompleteTwoFactorOnSignIn = true. Is it safe?
There was a problem hiding this comment.
Good question — it's safe (the reset unmounts this page before 2FA completes, and the only double-call is at mount where both share the single authPromiseResolver, so one navigate fires). But I'll make it explicit by guarding the registration with !isSignedIn so it can never re-register post-sign-in — no reliance on timing.
| // Bail if the effect re-ran (e.g. `isSignedIn` flipped true) before this resolved, so a | ||
| // stale callback can't reset the stack out from under the new state. | ||
| if (ignore) { | ||
| return; | ||
| } |
There was a problem hiding this comment.
I think ignore will be reset to false when this effect re-runs. Am I wrong?
There was a problem hiding this comment.
Each effect run closes over its own ignore. On re-run, React runs the previous run's cleanup (ignore = true on the binding the pending .then captured) before the new body runs with a fresh ignore = false and a new .then — so the stale callback bails and the new one proceeds. It's the standard React "ignore" cleanup pattern; the stale-callback guard test exercises exactly this.
Regression reviewNo code-level regressions found. The diff is scoped to What I verified
Worth confirming before merge (coverage gap, not a code bug)
Next Steps: Reply with |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b6cc47cbba
ℹ️ 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".
|
@mkhutornyi ready to proceed |
|
✋ This PR was not deployed to staging yet because QA is ongoing. It will be automatically deployed to staging after the next production release. |
|
🚧 @blimpich has triggered a test Expensify/App build. You can view the workflow run here. |
|
🧪🧪 Use the links below to test this adhoc build on Android, iOS, and Web. Happy testing! 🧪🧪
|
|
🚀 Deployed to staging by https://github.com/blimpich in version: 9.4.17-0 🚀
Bundle Size Analysis (Sentry): |
|
🤖 No help site changes required. This PR is an internal fix to the sign-in navigation logic in This is a behavior/UX fix with no new user-facing feature, setting, tab, or button to document. The existing help articles already describe the correct expected behavior, and this change brings the product in line with what they say:
Both articles already state that a 2FA prompt follows the magic code, which is exactly the flow this PR now delivers in a separate session. No draft docs PR was created. @mukhrr, no help site PR was needed for this change — the existing articles already reflect the current behavior. If you believe a docs update is warranted, let me know and I'll open a draft PR. |
|
🚀 Deployed to production by https://github.com/blimpich in version: 9.4.17-3 🚀
|
1 similar comment
|
🚀 Deployed to production by https://github.com/blimpich in version: 9.4.17-3 🚀
|
Explanation of Change
Follow-up of #90488
Fixed Issues
$ #93753
PROPOSAL: #90488 (comment)
Tests
Verify you are in 2FA code inserting page
Verify that no errors appear in the JS console
Offline tests
QA Steps
// TODO: These must be filled out, or the issue title must include "[No QA]."
PR Author Checklist
### Fixed Issuessection aboveTestssectionOffline stepssectionQA stepssectioncanBeMissingparam foruseOnyxtoggleReportand notonIconClick)src/languages/*files and using the translation methodSTYLE.md) were followedAvatar, I verified the components usingAvatarare working as expected)StyleUtils.getBackgroundAndBorderStyle(theme.componentBG))npm run compress-svg)Avataris modified, I verified thatAvataris working as expected in all cases)Designlabel and/or tagged@Expensify/designso the design team can review the changes.ScrollViewcomponent to make it scrollable when more elements are added to the page.mainbranch was merged into this PR after a review, I tested again and verified the outcome was still expected according to theTeststeps.Screenshots/Videos
Android: Native
Android: mWeb Chrome
iOS: Native
iOS: mWeb Safari
MacOS: Chrome / Safari
REC-20260616091050.mp4