Invalid Refresh Token: Already Used: SSR NextJS
I have used the SSR Auth Guide for setting up auth with NextJS. https://supabase.com/docs/guides/auth/server-side/nextjs?queryGroups=router&router=app
I am seeing that inconsistently my token (set in the browser as a cookie) is becoming invalid. Sometimes I am even seeing the
Invalid Refresh Token: Already Used
message. I don't have anything custom or different about my flow for auth. I have done everything in the guide to a T. Based on searching around I believe that there is a potential problem with the browser client in that it's trying to potentially refresh the token even though the server and middleware already achieve that. I am still testing out a few things.
A weird anecdote is that it only happens on one page/component and I am making probably 10 requests to supabase back to back. My thoughts are it's one of two things:
1. I am calling the DB too much that it's freaking out the auth system because a token is out of date or in a weird state when I call (and I need to optimize this...)
2. Something is happening with the token being set in the cookies that isn't playing nicely with browser side code.
Thoughts? Happy to share some code if it helps but likely it's just gonna be the guide code.9 Replies
Are you using Next 15?
No not yet. 14.2.7
Ok, just checking. I've heard that Next middleware has to be done precisely with supabase auth or things go haywire.
How often are you calling the db?
Regarding your 2nd point: Depending on timing, it's possible that the middleware client might refresh the access token during the getUser call, but even if the client-side also refreshes with the same refresh token, things are typically ok. The same refresh token can be used within 10 seconds of it being used the first time, to allow for timing issues here.
How often are you calling the db?I just make like 4 or 5 calls back to back to load various data. Nothing I would consider too much. And yeah that makes sense. I have noticed in a fair bit examples people setting autoRefresh on browserside clients to false. I am going to give that a try but it doesn't make sense that, that would be what is causing it. And interesting observation. Before the user is force logged out (because it doesn't refresh) it allows me to move around to a few different pages. And most of the data with the exception of one set of calls succeed. A major difference in that code is that I am calling the db using an async useEffect and not a server action... Maybe this has something to do with it? 🤷♂️
That I'm not sure. I don't know much about Next.
Yeah no worries. I am more speaking out loud now.
Appreciate the response. Something tells me it's either how I am calling users in the client side that is causing some refresh or there is an underlying bug related to refresh that I have discovered.
Ok another interesting find:
auth/v1/token?grant_type=refresh_token
which is being called to check refresh status, fails when I leave the page open and let it sit. That is what kicks off the whole problem it seems.A major difference in that code is that I am calling the db using an async useEffect and not a server action... Maybe this has something to do with it? 🤷♂️this looks sus from what you've described — are you doing this in the component that's causing you trouble?
Nope just a couple of places where I wasn't using a legit server action. However I think I found the problem.
It looks like how Cookies are being handled has changed in November which was after I implemented it. I narrowed down the issue to the server client not setting the cookies right and a re-review of the guide code shows a change. I will post more tomorrow so others will benefit from this discovery.
Gotta love working with Auth/Reauth tokens. It's a straightforward enough thing that is always a pain to triage and diagnose. And usually ends up being something simple like this.
If this stems from the guide, you might consider creating an issue on the supabase repo and just linking to it here.