Description 🐜
Took me a bit of time but I think I finally understood why we were seeing so many errors related to refreshing the token in our app.
I'm following the suggested setup to refresh tokens https://next-auth.js.org/tutorials/refresh-token-rotation which works fine.
The issue is the broadcasting that if you have more than 1 tab open with your web app, it will trigger a session check for EVERY tab and then you end up triggering the refreshAccessToken() function multiple times simultaneously with the same set of parameters (same refresh_token)
This creates an issue because the first request will be successful and obtain a new access_token paired with a refresh_token while all the other calls that were made will get a 400 since the old refresh_token has just been invalidated by the first successful call.
Simplest way to fix this would be to have the option to disable broadcasting and let each tab try to refresh the session only when focused.
EDIT: 3 scenarios where this is a problem
- broadcasting
getSession event when a session refresh is already in flight
- opening a new page when a session refresh is already in flight
- focusing a different tab when a session refresh is already in flight
Check here for a lock mechanism proposed solution:
#2071 (comment)
How to reproduce ☕️
In the app try to set a clientMaxAge of 10 seconds
<AuthProvider
session={pageProps.session}
options={{
clientMaxAge: 10,
}}
>
Then add a log in [...nextauth].js jwt callback
async jwt(token, user, account, profile) {
console.log('JWT')
Open 2 tabs and move between them, you will notice that every 10 seconds there are 2 calls being made to refresh the session and 2 console logs
I can create a codesandbox later after I finish work if needed but it's pretty simple to verify I believe 😄
I'm using "next-auth": "3.23.3"
Description 🐜
Took me a bit of time but I think I finally understood why we were seeing so many errors related to refreshing the token in our app.
I'm following the suggested setup to refresh tokens https://next-auth.js.org/tutorials/refresh-token-rotation which works fine.
The issue is the broadcasting that if you have more than 1 tab open with your web app, it will trigger a session check for EVERY tab and then you end up triggering the
refreshAccessToken()function multiple times simultaneously with the same set of parameters (samerefresh_token)This creates an issue because the first request will be successful and obtain a new
access_tokenpaired with arefresh_tokenwhile all the other calls that were made will get a 400 since the oldrefresh_tokenhas just been invalidated by the first successful call.Simplest way to fix this would be to have the option to disable broadcasting and let each tab try to refresh the session only when focused.
EDIT: 3 scenarios where this is a problem
getSessionevent when a session refresh is already in flightCheck here for a lock mechanism proposed solution:
#2071 (comment)
How to reproduce ☕️
In the app try to set a
clientMaxAgeof 10 secondsThen add a log in
[...nextauth].jsjwtcallbackOpen 2 tabs and move between them, you will notice that every 10 seconds there are 2 calls being made to refresh the session and 2 console logs
I can create a codesandbox later after I finish work if needed but it's pretty simple to verify I believe 😄
I'm using
"next-auth": "3.23.3"