auth0 / auth0-react

Auth0 SDK for React Single Page Applications (SPA)
MIT License
866 stars 252 forks source link

intermittent "Invalid state" missing_transaction error from loginWithRedirect() #785

Open yellowtailfan opened 2 months ago

yellowtailfan commented 2 months ago

Checklist

Description

Our production app using auth0-react intermittently produces an "Invalid state" error on our callback page, with error missing_transaction.

Reproduction

The error is intermittent. I have made many attempts to reproduce it but so far none succeeded.

It happens mostly to myself, several times a day if I am actively using the app on multiple tabs in production on Chrome. It rarely happens for our users. It rarely or never happens on our development server or in local testing. It doesn't seem to affect our other developers using Firefox.

It tends to happen when I have multiple tabs open with our app running, and I switch back to one of those tabs.

Additional context

Our app had 3 authentication triggers:

  1. withAuthenticationRequired wrapping multiple page components
  2. loginWithRedirect() on our index page (not generally open in normal use, as our home screen is on /home)
  3. getAccessTokenSilently() before each call to our own API

We are using Nextjs with static export. We are using auth0-react because that was available when we started writing the app several years ago. We are using refresh tokens and the useCookiesForTransactions is unset which I believe means loginWithRedirect() is using single-tab session storage.

My current guesses as to the cause:

  1. Chrome is loading the page multiple times from within a single tab triggering multiple overlapping calls to loginWithRedirect() via withAuthenticationRequired
  2. Chrome possibly discards tabs when I switch away from them, then restarts them in some odd way that interferes with the session storage (although I tried manually discarding tabs and rapidly switching tabs but could not reproduce the error)
  3. Chrome deletes the session storage at an inconvenient time (I have seen some reports that Chrome sometimes deletes session storage after a short timeout)

I considered whether loginWithRedirect() on our index page was causing a race condition, but I can't see how that would happen as the index page is never visited after login during normal use.

I have made some changes and will keep an eye out to see if the bug has gone:

  1. Removed loginWithRedirect() from our index page (just rely on withAuthenticationRequired that is on our other pages instead)
  2. Added logging via the withAuthenticationRequired option onBeforeAuthentication to console and Sentry
  3. Added a check on isAuthenticated before allowing calls to getAccessTokenSilently()

I have also had a detailed discussion with one of your support team on a support ticket.

auth0-react version

2.2.4

React version

17.0.2

Which browsers have you tested in?

Chrome

yellowtailfan commented 2 months ago

One suggestion I have seen in your support forms and your GitHub issues is to recover gracefully when receiving an "Invalid state" error by retrying. For example calling getAccessTokenSilently() with a local storage counter to avoid infinite loops.

I considered trying that, but because I can't reproduce the bug it's hard for me to test the fix. I suppose I could modify my local copy of auth0-react to randomly create the error then check my handling of it that way. But I haven't tried that yet.

It would be great if there was a working and tested example of this kind of retry mechanism. Even better of course would be if the auth0-react library could be made more resilient to transient failures in session storage or overlapping calls to loginWithRedirect().