#14941·amplify-js

Auth: fetchAuthSession()/getCurrentUser() hang indefinitely after a cross-tab or abandoned OAuth (signInWithRedirect) flow

Author: osama-rizkCreated Sep 7, 2026Updated Sep 7, 2026

Before creating a new issue, please confirm:

  • I have searched for duplicate or closed issues and couldn't find a duplicate matching my use-case and specifications.

Note: This is a follow-up to the closed issue #14344 ("Calling getCurrentSession promise hangs after signing out in a different tab"). That issue was closed as a question, but the underlying library bug is real and reproducible on the latest aws-amplify. Opening this to track the fix.

Which UI component?

N/A (core aws-amplify/auth)

Gathering environment information is required for the timely resolution of issues.

[email protected] (also reported on 6.14.x)

Describe the bug

fetchAuthSession() (and getCurrentUser()) can hang forever — never resolving and never rejecting — after a cross-tab OAuth interaction.

signInWithRedirect() sets an inflightOAuth=true flag in localStorage, which is shared across all tabs of the origin. However, the mechanism that unblocks fetchAuthSession()/getCurrentUser() once OAuth completes (resolveAndClearInflightPromises) is an in-memory, per-tab array of resolvers that only runs in the tab that actually processes the OAuth redirect response — completeOAuthFlow on success, handleFailure on error.

As a result, any tab that only observes the shared flag but never runs the redirect callback blocks forever in TokenOrchestrator.waitForInflightOAuth():

  • Cross-tab: Tab B calls signInWithRedirect() and stays on the Cognito Hosted UI without finishing. Tab A then calls fetchAuthSession() → reads the shared inflightOAuth=true → registers an in-memory promise its own runtime will never resolve → hangs.
  • Abandoned flow: any flow that sets inflightOAuth=true and is never completed leaves the flag in localStorage permanently, so later fetchAuthSession() calls hang.

Expected behavior

fetchAuthSession() should resolve (returning the current tokens, or null/no tokens) rather than hang indefinitely when another tab started or abandoned an OAuth flow. A tab that did not itself initiate the redirect should not be blocked by shared cross-tab OAuth state.

Reproduction steps

  1. Open the app in Tab A and Tab B (SPA using aws-amplify v6 + Cognito Hosted UI / Managed Login, response_type=code).
  2. In Tab B, call signInWithRedirect() and stay on the Hosted UI without completing sign-in (this writes inflightOAuth=true to shared localStorage).
  3. In Tab A, call fetchAuthSession().
  4. Observe that the promise in Tab A never resolves or rejects. inflightOAuth remains true in shared localStorage and waitForInflightOAuth() keeps waiting.

Reproduced deterministically with a minimal two-tab app; fetchAuthSession() in Tab A never settles.

Code Snippet

javascript
// Tab A
import { fetchAuthSession } from 'aws-amplify/auth';

window.onfocus = async () => {
  console.log('will fetch session');
  const session = await fetchAuthSession(); // never resolves/rejects
  console.log('got session', session);       // never reached
};

Log output

will fetch session
(no further output — promise never settles)

aws-exports.js

No response

Manual configuration

No response

Additional configuration

No response

Mobile Device

No response

Desktop OS

macOS

Browser

Chrome, Safari

Additional information and screenshots

Root cause is the mismatch between the cross-tab shared inflightOAuth flag (localStorage) and the per-tab in-memory resolver array in packages/auth/src/providers/cognito/utils/oauth/inflightPromise.ts, consumed by TokenOrchestrator.waitForInflightOAuth().

Related: closed issue #14344.

A fix is proposed in PR #14940, which bounds the wait so a tab that did not initiate the flow can never hang (resolves when another tab clears the shared flag, with a bounded-timeout safety net for abandoned flows), without disturbing an OAuth flow genuinely in progress in another tab.