From e41d224ccd073d2a640c7df9378fc281caf0017c Mon Sep 17 00:00:00 2001
From: allgandaf <whogandalf@gmail.com>
Date: Mon, 25 May 2026 21:53:37 +0530
Subject: [PATCH 1/7] Add RAM-only key for isAuthenticatingWithShortLivedToken

---
 src/ONYXKEYS.ts | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/src/ONYXKEYS.ts b/src/ONYXKEYS.ts
index 8e30de4e3f7b..2992b26e6c19 100755
--- a/src/ONYXKEYS.ts
+++ b/src/ONYXKEYS.ts
@@ -36,6 +36,9 @@ const ONYXKEYS = {
     /** Boolean flag set whenever we are searching for reports in the server */
     RAM_ONLY_IS_SEARCHING_FOR_REPORTS: 'isSearchingForReports',
 
+    /** Boolean flag indicating a SignInWithShortLivedAuthToken request is in flight. RAM-only so an interrupted request never persists a stuck `true` to IndexedDB and blocks future reauth attempts. */
+    RAM_ONLY_IS_AUTHENTICATING_WITH_SHORT_LIVED_TOKEN: 'isAuthenticatingWithShortLivedToken',
+
     /** Note: These are Persisted Requests - not all requests in the main queue as the key name might lead one to believe */
     PERSISTED_REQUESTS: 'networkRequestQueue',
     PERSISTED_ONGOING_REQUESTS: 'networkOngoingRequestQueue',
@@ -1530,6 +1533,7 @@ type OnyxValuesMapping = {
     [ONYXKEYS.ONBOARDING_ADMINS_CHAT_REPORT_ID]: string;
     [ONYXKEYS.ONBOARDING_LAST_VISITED_PATH]: string;
     [ONYXKEYS.RAM_ONLY_IS_SEARCHING_FOR_REPORTS]: boolean;
+    [ONYXKEYS.RAM_ONLY_IS_AUTHENTICATING_WITH_SHORT_LIVED_TOKEN]: boolean;
     [ONYXKEYS.LAST_VISITED_PATH]: string | undefined;
     [ONYXKEYS.REPORT_LAST_VISIT_TIMES]: OnyxTypes.ReportLastVisitTimes;
     [ONYXKEYS.RECENTLY_USED_REPORT_FIELDS]: OnyxTypes.RecentlyUsedReportFields;

From 702fb89daa52fde2d796d71107c6d84e6d516198 Mon Sep 17 00:00:00 2001
From: allgandaf <whogandalf@gmail.com>
Date: Mon, 25 May 2026 21:54:05 +0530
Subject: [PATCH 2/7] Register RAM-only auth flag in Onyx.init

---
 src/setup/index.ts | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/setup/index.ts b/src/setup/index.ts
index 7ee6c5dad5a3..1340ef9db9f5 100644
--- a/src/setup/index.ts
+++ b/src/setup/index.ts
@@ -65,6 +65,7 @@ export default function () {
             ONYXKEYS.RAM_ONLY_UPDATE_AVAILABLE,
             ONYXKEYS.RAM_ONLY_UPDATE_REQUIRED,
             ONYXKEYS.RAM_ONLY_IS_SEARCHING_FOR_REPORTS,
+            ONYXKEYS.RAM_ONLY_IS_AUTHENTICATING_WITH_SHORT_LIVED_TOKEN,
             ONYXKEYS.RAM_ONLY_WALLET_ONFIDO,
             ONYXKEYS.COLLECTION.RAM_ONLY_REPORT_LOADING_STATE,
             ONYXKEYS.RAM_ONLY_PLAID_LINK_TOKEN,

From e3691ba8bf05d42fc2fec71c305aceb121c4d418 Mon Sep 17 00:00:00 2001
From: allgandaf <whogandalf@gmail.com>
Date: Mon, 25 May 2026 21:55:06 +0530
Subject: [PATCH 3/7] Move isAuthenticatingWithShortLivedToken to RAM-only key
 in getShortLivedLoginParams

---
 src/libs/actions/Session/index.ts | 19 +++++++++++++++----
 1 file changed, 15 insertions(+), 4 deletions(-)

diff --git a/src/libs/actions/Session/index.ts b/src/libs/actions/Session/index.ts
index 93b3f7f0352c..bb31cf2556e1 100644
--- a/src/libs/actions/Session/index.ts
+++ b/src/libs/actions/Session/index.ts
@@ -154,7 +154,9 @@ function setSupportAuthToken(supportAuthToken: string, email: string, accountID:
 }
 
 function getShortLivedLoginParams(isSupportAuthTokenUsed = false, isSAML = false) {
-    const optimisticData: Array<OnyxUpdate<typeof ONYXKEYS.ACCOUNT | typeof ONYXKEYS.SESSION | typeof ONYXKEYS.HYBRID_APP>> = [
+    const optimisticData: Array<
+        OnyxUpdate<typeof ONYXKEYS.ACCOUNT | typeof ONYXKEYS.SESSION | typeof ONYXKEYS.HYBRID_APP | typeof ONYXKEYS.RAM_ONLY_IS_AUTHENTICATING_WITH_SHORT_LIVED_TOKEN>
+    > = [
         {
             onyxMethod: Onyx.METHOD.MERGE,
             key: ONYXKEYS.ACCOUNT,
@@ -170,14 +172,19 @@ function getShortLivedLoginParams(isSupportAuthTokenUsed = false, isSAML = false
             value: {
                 signedInWithShortLivedAuthToken: true,
                 signedInWithSAML: isSAML,
-                isAuthenticatingWithShortLivedToken: true,
                 isSupportAuthTokenUsed,
             },
         },
+        // Kept on a RAM-only key so an interrupted SignIn cannot persist a stuck `true` to IndexedDB and block all future reauth attempts.
+        {
+            onyxMethod: Onyx.METHOD.SET,
+            key: ONYXKEYS.RAM_ONLY_IS_AUTHENTICATING_WITH_SHORT_LIVED_TOKEN,
+            value: true,
+        },
     ];
 
     // Subsequently, we revert it back to the default value of 'signedInWithShortLivedAuthToken' in 'finallyData' to ensure the user is logged out on refresh
-    const finallyData: Array<OnyxUpdate<typeof ONYXKEYS.ACCOUNT | typeof ONYXKEYS.SESSION>> = [
+    const finallyData: Array<OnyxUpdate<typeof ONYXKEYS.ACCOUNT | typeof ONYXKEYS.SESSION | typeof ONYXKEYS.RAM_ONLY_IS_AUTHENTICATING_WITH_SHORT_LIVED_TOKEN>> = [
         {
             onyxMethod: Onyx.METHOD.MERGE,
             key: ONYXKEYS.ACCOUNT,
@@ -192,9 +199,13 @@ function getShortLivedLoginParams(isSupportAuthTokenUsed = false, isSAML = false
                 signedInWithShortLivedAuthToken: null,
                 signedInWithSAML: isSAML,
                 isSupportAuthTokenUsed: null,
-                isAuthenticatingWithShortLivedToken: false,
             },
         },
+        {
+            onyxMethod: Onyx.METHOD.SET,
+            key: ONYXKEYS.RAM_ONLY_IS_AUTHENTICATING_WITH_SHORT_LIVED_TOKEN,
+            value: false,
+        },
     ];
 
     const failureData: Array<OnyxUpdate<typeof ONYXKEYS.HYBRID_APP>> = [];

From 1fb603a202e7a3a5c4a67c131d800a6de712f88a Mon Sep 17 00:00:00 2001
From: allgandaf <whogandalf@gmail.com>
Date: Mon, 25 May 2026 21:55:37 +0530
Subject: [PATCH 4/7] Read isAuthenticatingWithShortLivedToken from RAM-only
 key in Reauthentication

---
 src/libs/Reauthentication.ts | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/src/libs/Reauthentication.ts b/src/libs/Reauthentication.ts
index 3a4fffbeb27f..6cedba8598e5 100644
--- a/src/libs/Reauthentication.ts
+++ b/src/libs/Reauthentication.ts
@@ -36,7 +36,6 @@ let isSupportAuthTokenUsed = false;
 Onyx.connectWithoutView({
     key: ONYXKEYS.SESSION,
     callback: (value) => {
-        isAuthenticatingWithShortLivedToken = !!value?.isAuthenticatingWithShortLivedToken;
         isSupportAuthTokenUsed = !!value?.isSupportAuthTokenUsed;
 
         Sentry.setUser({
@@ -46,6 +45,14 @@ Onyx.connectWithoutView({
     },
 });
 
+// Kept on a RAM-only key so an interrupted SignIn cannot persist a stuck `true` to IndexedDB and block all future reauth attempts.
+Onyx.connectWithoutView({
+    key: ONYXKEYS.RAM_ONLY_IS_AUTHENTICATING_WITH_SHORT_LIVED_TOKEN,
+    callback: (value) => {
+        isAuthenticatingWithShortLivedToken = !!value;
+    },
+});
+
 let account: OnyxEntry<Account>;
 // Authentication lib is not connected to any changes on the UI
 // So it is okay to use connectWithoutView here.

From bed65d5b3a4adbeedcb5025806e6b8a8d19a2ab9 Mon Sep 17 00:00:00 2001
From: allgandaf <whogandalf@gmail.com>
Date: Mon, 25 May 2026 21:55:48 +0530
Subject: [PATCH 5/7] Remove isAuthenticatingWithShortLivedToken from Session
 type

---
 src/types/onyx/Session.ts | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/src/types/onyx/Session.ts b/src/types/onyx/Session.ts
index ecc004f56f57..2709fc56bf2e 100644
--- a/src/types/onyx/Session.ts
+++ b/src/types/onyx/Session.ts
@@ -37,9 +37,6 @@ type Session = {
     /** User signed in with short lived token */
     signedInWithShortLivedAuthToken?: boolean;
 
-    /** Indicates whether the user is re-authenticating with shortLivedToken */
-    isAuthenticatingWithShortLivedToken?: boolean;
-
     /** User signed in with SAML */
     signedInWithSAML?: boolean;
 

From 990c3fc1667767f03eae28859e66bba3b9f52263 Mon Sep 17 00:00:00 2001
From: allgandaf <whogandalf@gmail.com>
Date: Mon, 25 May 2026 21:56:22 +0530
Subject: [PATCH 6/7] Read isAuthenticatingWithShortLivedToken from RAM-only
 key in AppState

---
 src/libs/AppState/index.ts | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/src/libs/AppState/index.ts b/src/libs/AppState/index.ts
index cd12ce459b15..613e90e25d9e 100644
--- a/src/libs/AppState/index.ts
+++ b/src/libs/AppState/index.ts
@@ -12,6 +12,7 @@ import type {ExtraLoadingContext, GlobalStateSnapshot, NavigationStateInfo, Netw
 
 let currentSession: OnyxEntry<Session>;
 let currentNetwork: OnyxEntry<Network>;
+let currentIsAuthenticatingWithShortLivedToken = false;
 
 // We have opted for connectWithoutView here as this is strictly non-UI and only for logging.
 Onyx.connectWithoutView({
@@ -29,6 +30,14 @@ Onyx.connectWithoutView({
     },
 });
 
+// We have opted for connectWithoutView here as this is strictly non-UI and only for logging.
+Onyx.connectWithoutView({
+    key: ONYXKEYS.RAM_ONLY_IS_AUTHENTICATING_WITH_SHORT_LIVED_TOKEN,
+    callback: (value) => {
+        currentIsAuthenticatingWithShortLivedToken = !!value;
+    },
+});
+
 /**
  * Captures current navigation state.
  */
@@ -54,12 +63,11 @@ function captureNavigationState(): NavigationStateInfo {
 function captureSessionState(): SessionStateInfo {
     // Check multiple authentication states to get complete picture
     const isSessionLoading = !!currentSession?.loading;
-    const isAuthenticatingWithShortLivedToken = !!currentSession?.isAuthenticatingWithShortLivedToken;
     const isAuthenticatingFromNetworkStore = isAuthenticatingNetworkStore();
 
     return {
         isSessionLoading,
-        isAuthenticatingWithShortLivedToken,
+        isAuthenticatingWithShortLivedToken: currentIsAuthenticatingWithShortLivedToken,
         isAuthenticatingFromNetworkStore,
     };
 }

From 64a2f010670d394acb3772e61e1a4beb2285e97e Mon Sep 17 00:00:00 2001
From: allgandaf <whogandalf@gmail.com>
Date: Mon, 25 May 2026 22:02:24 +0530
Subject: [PATCH 7/7] Add unit tests for RAM-only auth flag and legacy session
 recovery

---
 tests/actions/SessionTest.ts | 37 ++++++++++++++++++++++++++++++++++++
 1 file changed, 37 insertions(+)

diff --git a/tests/actions/SessionTest.ts b/tests/actions/SessionTest.ts
index fac013420337..1792d690ca3d 100644
--- a/tests/actions/SessionTest.ts
+++ b/tests/actions/SessionTest.ts
@@ -81,6 +81,43 @@ describe('Session', () => {
         redirectToSignInSpy.mockRestore();
     });
 
+    test('reauthenticate aborts when RAM_ONLY_IS_AUTHENTICATING_WITH_SHORT_LIVED_TOKEN is true', async () => {
+        // Given a SignIn with short lived token is currently in flight
+        await Onyx.set(ONYXKEYS.RAM_ONLY_IS_AUTHENTICATING_WITH_SHORT_LIVED_TOKEN, true);
+        await waitForBatchedUpdates();
+
+        const redirectToSignInSpy = jest.spyOn(SignInRedirect, 'default').mockImplementation(() => Promise.resolve());
+
+        // When reauthenticate is called
+        const result = await reauthenticate('TestCommand');
+        await waitForBatchedUpdates();
+
+        // Then it aborts cleanly without redirecting to sign in
+        expect(result).toBe(false);
+        expect(redirectToSignInSpy).not.toHaveBeenCalled();
+
+        redirectToSignInSpy.mockRestore();
+    });
+
+    test('reauthenticate proceeds even when a legacy session.isAuthenticatingWithShortLivedToken=true is persisted (recovers stuck users)', async () => {
+        // Given a session in Onyx that still carries the legacy stuck flag from before the RAM-only migration.
+        // The Session type no longer declares the field, so cast to write the legacy shape.
+        await Onyx.merge(ONYXKEYS.SESSION, {isAuthenticatingWithShortLivedToken: true} as unknown as Session);
+        await waitForBatchedUpdates();
+
+        const redirectToSignInSpy = jest.spyOn(SignInRedirect, 'default').mockImplementation(() => Promise.resolve());
+
+        // When reauthenticate is called with no credentials stored
+        const result = await reauthenticate('TestCommand');
+        await waitForBatchedUpdates();
+
+        // Then the legacy persisted flag does NOT block reauth. Reauth proceeds, finds no credentials, and redirects to sign in.
+        expect(result).toBe(false);
+        expect(redirectToSignInSpy).toHaveBeenCalledWith('No credentials available');
+
+        redirectToSignInSpy.mockRestore();
+    });
+
     test('Authenticate is called with saved credentials when a session expires', async () => {
         // Given a test user and set of authToken with subscriptions to session and credentials
         const TEST_USER_LOGIN = 'test@testguy.com';
