Repository navigation
Conversation
When the token endpoint rejects a refresh token with `invalid_grant`, the jwt callback kept the token and only set `error: 'RefreshTokenError'`. The access token stays expired, so every later session read (each `/api/auth/session` poll, each `auth()` call) sent the same dead token again, for the life of the session cookie (365 days, renewed on each read). Now a terminal failure (`invalid_grant`, which Auth0 returns with 403 and Ory with 400) drops the refresh token. Later reads take the no-refresh-token branch without a network call and keep reporting `RefreshTokenError`, so apps that sign out on it still do. Network errors, 5xx and 429 keep the token so the next read can retry. `refreshAccessToken` now throws `RefreshTokenRequestError` (status + OAuth error code); it and `isTerminalRefreshError` are exported. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
View your CI Pipeline Execution ↗ for commit 3c9fc92
💡 Verify your cache is correct by running tasks in a sandbox. Read docs ↗ ☁️ Nx Cloud last updated this comment at |
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
auth-next-serverno longer resends a refresh token that the auth server has rejected withinvalid_grant. Before this change, a session whose refresh token was rejected tried the same token again on every session read, for as long as the session cookie lived.Detail and impact of the change
Fixed
jwtcallback seterror: 'RefreshTokenError'but kept the refresh token, and the access token stayed expired. Every later session read (each/api/auth/sessionpoll fromuseSession, eachauth()call) tried the same refresh again. The session cookie lasts 365 days and is renewed on each read, so a single stuck session keeps calling the token endpoint indefinitely. In practice that means a steady stream of failed refreshes, with bursts of thousands a minute when one client polls quickly.invalid_grant, the refresh token is removed from the JWT. Later reads take the existing "no refresh token" branch, with no network call, and the session keeps reportingRefreshTokenError.RefreshTokenErrorrather than falling back toTokenExpired, so apps that sign the user out onRefreshTokenErrorstill do.TokenExpiredis still returned for sessions that never had a refresh token.invalid_grantcounts as terminal. Auth0 returns it with a 403 and Ory with a 400, so the OAutherrorcode is checked, not the HTTP status. Network errors, 5xx, 429 and other error codes keep the refresh token, and the next read retries as before.forceRefresh(trigger: 'update') path gets the same handling.Added
RefreshTokenRequestError, thrown byrefreshAccessTokenwhen the token endpoint rejects the request. It carriesstatusandoauthError, and still extendsErrorwith the same message as before.isTerminalRefreshError(error).auth-next-server:refresh.test.tsandconfig.test.ts. 7 of the 10 fail onmain.Anything else worth calling out?
invalid_granthappens, and this PR stops the retries once it has. Both touchrefresh.ts, so whichever merges second needs a small rebase.oxlintreports one warning inconfig.ts(an unusedidTokeninjwt.encode). It is already onmain.pnpm --filter @imtbl/auth-next-server test(10/10) andtypecheck(clean).🤖 Generated with Claude Code