Concurrent calls to getTokenSilently fail with invalid_grant sporadically

We’ve recently migrated all our applications to use RRTs and started receiving reports of users having to authenticate again. After digging through the Auth0 logs, we found patterns where there would be a successful exchange > failed exchange: refresh reuse > failed exchange: refresh invalid within milliseconds. While comparing two of the applications, there was a disproportion number of these types of occurrences for one of the applications which we narrowed down to the difference in concurrent API calls performed. The error pattern doesn’t always trigger strictly due to a large number of calls, but it seemed to factor in the volume of occurrences; I spent about 5 minutes refreshing the site while seeing successful exchanges then there seemed to be a point where I hit a spot where an older token was sent and the breach detection triggered.

So, at this point, I’m not exactly sure if this is an implementation issue on our end or an issue with concurrent calls to getTokenSilently. I was able to reproduce this using the Auth0 SPA JS Playground by wrapping the getTokenSilently call in a loop to call it 15 times and hitting the “Get Access Token” button. Like I said, it’s sporadic, so it took me a few minutes to get it error.

Here’s the configuration:

Auth0 API
Access Token Expiration: 70s

** Application **
Refresh Token Behavior - Rotating
Refresh Token Lifetime - 36000
Refresh Token Reuse Interval - 30

** Playground **
Audience - Auth0 API we created
Use local storage - true
Use refresh tokens - true
Use token cache when fetching new tokens - true
Use Auth0Client constructor - false

I went back and added a few console logs; it looks like the browser-tabs-lock dependency can allow multiple locks to be acquired under race conditions.