Getting "Unsuccessful Refresh Token exchange, reused refresh token detected"

We have some users seeing this, even though this is their only refresh attempt in surrounding couple of hours.

We use the auth0 hook without any surrounding logic or caching on our end:

const token = await useAuth0().getCredentials()

react-native-auth0 version: 5.0.1, iOS

Log id: 90020251031003016555919000000000000001223372092434150111 for one such instance

Hi @johan.lindell

Welcome back to the Community!

Just to double check, are you passing in the proper scopes (offline_access) in the authorize request?

Do you have Refresh Token Rotation enabled for your application?

Also, what are you current Refresh Token Maximum Lifetime settings? Could it be possible that the refresh token expired?

You mentioned that you have no caching on your application and that you are only calling the Auth0 hook, meaning that there are no refresh tokens stored inside the application or web cookies, right?

Looking forward to your reply!

Kind Regards,
Nik

We are currently not passing any scope, can you give me some pointers for the offline_access you mentioned?

We have refresh token rotation enabled with a 20 second overlap. It’s not possible that the token is expired, because we have an expiry time on the order of months and this happens several times a day for the same user.

Correct, we are not caching it anywhere.

Hi again!

We are currently not passing any scope, can you give me some pointers for the offline_access you mentioned?

Whenever you start authorization for your users, do you pass in the these additional authorization parameters as such:

await authorize(
        {
          scope: 'openid profile email offline_access',
          audience: 'YOUR_API_IDENTIFIER',
        },
      );

I would recommend to check inside the Auth0 Dashboard if you have the following:

  • Allow Offline Access enabled under your application’s API
  • The Refresh Token Grant is enabled for your application under → Advanced Settings → Grant Types

Have you tried by any chance to store the token using the credentials manager to see if there are any differences in the behaviour?

Kind Regards,
Nik

Oh I see what you mean, yes, we pass offline_access in our authorize call:

```
const credentials = await authorize({
audience,
scope: “openid profile email offline_access”,
additionalParameters,
})
```

We have those settings enabled. I’m not sure what you mean by credentials manager, I prefer to just use the standard react-native hooks provided by the sdk.

Hello @johan.lindell,

Could you please tell us if this issue is happening to an isolated user or multiples users and if you are able to reproduce this on your end ?

One possibility is that the refresh token was rotated but the new refresh token was not successfully stored. This could happen if the user closes the application during the transaction, there was a network issue or something similar.

Another reason could be that you are creating multiple versions of the CredentialsManager
( this would be the default example presented in the SDK as well - const credentials = await auth0.credentialsManager.getCredentials();), like from a computed property. The use of multiple instances is mentioned in the context of iOS as a potential cause of refresh token reuse.

This KB article - Refresh Token Rotation: Automatic Reuse Detection Issue in iOS App is the most appropriate in this case, so I would recommend checking this out.

Thank you,
Remus