`signInWithRedirect` cancelled on iOS Safari leaves `inflightOAuth` set — then `signIn()` hangs forever
Before opening, please confirm:
- I have searched for duplicate or closed issues and discussions.
- I have read the guide for submitting bug reports.
- I have done my best to include a minimal, self-contained set of instructions for consistently reproducing the issue.
JavaScript Framework
Next.js
Amplify APIs
Authentication
Amplify Version
v6
Amplify Categories
auth
Backend
Amplify Gen 2
Environment information
- `aws-amplify` `^6.18.0`
- **Mobile Safari on iOS** (plain web page)
- social provider (Apple), `signInWithRedirect({ provider: 'Apple', options: { prompt: 'SELECT_ACCOUNT' } })`
Describe the bug
Summary
On iOS, tapping "Sign in with Apple" presents the native iOS authorization sheet (Face ID / Touch ID) as an overlay — the page does not navigate or reload, so the JS context survives. When the user cancels that native sheet, Amplify never clears the inflightOAuth flag for this path. Every subsequent call that fetches tokens (signIn, getCurrentUser, fetchAuthSession) then stays pending forever — no resolve, no reject, no timeout. In our site the user switches to email login, presses submit, and the button spins indefinitely; only a full page reload recovers.
Root cause (from reading the bundled source)
signInWithRedirect→oauthSignIn()callsoAuthStore.storeOAuthInFlight(true)+storeOAuthState+storePKCE, writinginflightOAuth/oauthState/oauthPKCEto storage.- The web
openAuthSessionjust setswindow.location.hrefand returns nothing, so thecanceled/errorhandling inoauthSignInis (by its own comment) "effective only in react-native" — it never runs on web. inflightOAuthis only cleared byresolveAndClearInflightPromises(), called fromcompleteOAuthFlow(success, URL hascode+state) orhandleFailure(which also dispatchessignInWithRedirect_failure).- The only "user cancelled" recovery on web is
cancelOAuthFlow.mjs'slistenForOAuthFlowCancellation, which only fires on bfcache back-navigation (pageshowwithevent.persisted === true). A cancelled native sheet is neither a bfcache restore nor a navigation, so nothing clears the flag. - With the flag still set,
TokenOrchestrator.waitForInflightOAuth()returns an inflightPromisethat has no reject branch and no timeout;getTokens()awaits it first.signIn()→assertUserNotAuthenticated()→getCurrentUser()→getTokens()→ hangs.assertUserNotAuthenticated's try/catch cannot rescue a promise that never settles.
Expected behavior
- Give the
waitForInflightOAuthinflight promise a timeout and/or a reject path, so an interrupted OAuth flow can never become a permanent, unrecoverable hang. - Expose a public API to clear inflight OAuth state (equivalent to
DefaultOAuthStore.clearOAuthInflightData()), so apps can recover without reaching intoCognitoIdentityServiceProvider.*localStorage keys directly. - Broaden the web cancel-recovery beyond bfcache
pageshow(e.g. detect return viavisibilitychange/focuswheninflightOAuthis set and the URL has nocode).
Current workaround (for others hitting this)
Before calling signIn()/signUp(), remove inflightOAuth / oauthPKCE / oauthState for the client from localStorage (only those three keys — not the token keys, so signed-in users aren't logged out).
Reproduction steps
- On an iPhone, open the login page in mobile Safari and tap the Apple login button →
signInWithRedirect(...)(non-custom provider). - The native iOS biometric / Apple sign-in sheet appears as an overlay. Cancel / dismiss it.
- The page is still there — no navigation, no reload, not a bfcache restore.
- Call any token-requiring API — e.g.
signIn({ username, options: { authFlowType: 'USER_AUTH' } }). - The promise never settles.
Verify: after step 2, all three of
CognitoIdentityServiceProvider.<clientId>.oauthState,
CognitoIdentityServiceProvider.<clientId>.oauthPKCE, and
CognitoIdentityServiceProvider.<clientId>.inflightOAuth (= 'true')
remain in localStorage, and no signInWithRedirect_failure Hub event is dispatched.
Code Snippet
No response
Log output
No response
aws-exports.js
No response
Manual configuration
No response
Additional configuration
No response
Mobile Device
No response
Mobile Operating System
No response
Mobile Browser
No response
Mobile Browser Version
Safari 17.6
Additional information and screenshots
No response
Source: aws-amplify/amplify-js