Auth0-react won't refresh access tokens in mobile Safari with refresh tokens enabled

Please include the following information in your post:

  • Which SDK this is regarding: e.g. auth0-node
    auth0-react
  • SDK Version: e.g. 2.29.0
    1.2.0
  • Platform Version: e.g. Node 12.19.0
    Browser (Mobile Safari, iOS 14)
  • Code Snippets/Error Messages/Supporting Details/Screenshots:

Is this a feature request or bug report? question
I’m using auth0-react to authenticate user and then call backend API.
It’s initialized like this
<Auth0Provider
useRefreshTokens={true}
cacheLocation=“localstorage”
audience={audience from backend API} …/>

On every page load, I get access token like this:
getAccessTokenSilently()
.catch(async (e) => {
if (e.message === ‘Consent required’ || e.message === ‘Login required’) {
return await getAccessTokenWithPopup({
display: ‘page’
});
} else {
throw e;
}
});

It works fine in chrome, both if I keep the page open for days and let computer sleep most of the day, or if I close and reopen the page. But in mobile Safari, it seems like token is never refreshed. It works fine for about 24 hours, then both getAccessTokenSilently and getAccessTokenWithPopup throw errors (‘Login required’, then “cannot open a popup”). The last one is understood, since it’s not triggered by user click. But I expect Auth0 to refresh token in the background and getAccessTokenSilently to succeed. I open the page roughly every 12 hours.

I use default values for TTL for both client app and API. Refresh tokens are enabled.

Is there anything I’m missing?

Hi @bayuser,

Welcome to the Community!

For the API that you registered with Auth0 and that you’re using as the audience, do you have the “Allow Offline Access” setting enabled?

And just to be certain, in the network requests in dev tools in the browser, are you seeing a Refresh Token received from the /token endpoint after login?

Thanks for quick reply @stephanie.chamblee !
Yes enabling offline access in the API seems to help with this issue.
But now after waiting for roughly 2.5 days, I’m getting a new error: “Unknown or invalid refresh token”. This seems to be related to the newly enabled refresh tokens.
I have 2 questions here:

  1. why 2.5 days, what setting or behavior triggered it? in the API, token expiration is set to 1 day. In SPA, refresh token rotation is enabled, and refresh absolute lifetime is 1 month.
  2. what should I do when I encounter this error? call getAccessTokenWithPopup or log user out?
1 Like

Happy to help, @bayuser!

I’m not sure why this happened after 2.5 days specifically. Were any other sessions created/ended with the user you are testing with? For example, if you log in with a user in Firefox and then log in with the same user in Chrome and log out of the session in Firefox, then the Refresh Token would become invalid for the session in Chrome.

Are you able to find the error in the tenant logs when this happened?

You can handle Refresh Token exchange errors by initiating an interactive login flow with either loginWithRedirect or loginWithPopup. That is the only way to get a new Refresh Token.

I see “Unsuccessful Refresh Token exchange, reused refresh token detected” seconds after “Successful Refresh Token exchange” and “Update a user” event.
I indeed logged in with multiple devices. The thing is that I never logged out.

It sounds like multiple token requests were made within seconds. SPAs must use Refresh Token Rotation, which means if a Refresh Token is used more than once, it is invalidated which would cause this error.

There is an option to configure a leeway time to account for network concurrency issues, but I’m curious why the tokens were requested multiple times. If you are able to reproduce the error, would you mind capturing it in a HAR file and private messaging it to me? I can see if I’m able to reproduce the error in my own application.

well, it happened only once in my days of active testing, and it coincides with the time when I had internet issues. It’s possible that first successful request to refresh token failed to get back to the client, and it issued another one.
I will look into Leeway option, thanks! I want to point out that in Auth0-react comments, it says that leeway “Defaults to 60s”, but it seems that in practice it’s disabled by default

1 Like

You’re right, I see the leeway in the docs (auth0-react is built on top of auth0-spa-js): https://auth0.github.io/auth0-spa-js/interfaces/auth0clientoptions.html#leeway

I believe that setting refers to evaluating JWT expirations in the application, not the Refresh Token reuse leeway. The Refresh Token leeway seems to need to be configured in the application settings via the Management API so that your Auth0 tenant can determine if a Refresh Token should be accepted or not.

oh I see, thanks for clarifying. it should be “Reuse Interval” in the SPA settings

1 Like

This topic was automatically closed 15 days after the last reply. New replies are no longer allowed.