Next.js Discord

Discord Forum

Handling authentication and refresh token rotation with external API in Next.js 15

Unanswered
California pilchard posted this in #help-forum
Open in Discord
California pilchardOP
Hi everyone, I’m working on a Next.js 15 dashboard app and could use some guidance on authentication with an external backend (Golang Gin).

I save access and refresh tokens (with expiration) in httpOnly cookies. The access token expires in 15 minutes. On some pages, I need to fetch multiple endpoints (e.g., 3) in a server component. When the access token is expired, each request hits 401, and each triggers a refresh call. Instead of a single refresh and successful retries, I end up calling the refresh endpoint multiple times in parallel.

I’ve tried:
- Using an in-memory lock (globalThis) to prevent concurrent refreshes, but it doesn’t work reliably with internal API routes, likely because each request runs in an isolated context.
- Middleware that only checks the presence of a token (no refresh logic).

I’m also unsure about the best pattern for server components:
- Should I fetch internal API routes from server components, or call the backend directly?
- Is there a way to handle token refresh and set cookies entirely server-side without triggering multiple refresh calls?

I’m considering Redis for a distributed lock, but I’d like to understand if there’s a simpler approach or a standard pattern in Next.js. I’ve also looked at NextAuth/BetterAuth, but I’m not sure if they fit with an external API.
Any guidance, examples, or recommended patterns would be very helpful, thanks!

2 Replies

American black bear
man I have been under your same pain for so long. I ended up handling it in the proxy.ts which is not ideal but that's what I currently have for now.
California pilchardOP
Thanks for sharing, May I ask, when you say proxy.ts, do you mean middleware in Next.js 16? How are you handling the refresh logic there? I’d really appreciate any insight you can share.

What I’ve tried so far:
- I handling refresh in a proxy route handler. On 401, I call refresh and retry the request. This works for single requests, but when a server page triggers multiple calls in parallel (e.g. Promise.allSettled), they all hit 401 and trigger refresh at the same time. This causes a race condition and cookies don’t get updated consistently.
- I handling refresh in middleware, I tried validating the token (or calling a lightweight endpoint) and refreshing there. But there’s still a gap where middleware passes, and then the actual request in the page fails with 401. Also, there a case when in multiple tab, race condition could also happen.

I’m considering adding a buffer (e.g. refresh if token expires within 1 minute) to reduce the chance of hitting expiry during requests, but I'm not so sure.