fix(auth): keep login state on rate-limited or failing token refresh
When the dashboard token refresh endpoint returned 429 (shared critical rate limit) the frontend classified it as out_of_sync, cleared local auth state, and redirected to /sign-in. The rate limit itself is working as intended; the bug is that a temporary rejection was treated as a terminal auth failure. - Treat 429 refresh responses as transient errors on the frontend, keeping the session retryable instead of clearing it. Only explicit 401 or confirmed session mismatch/race exhaustion clears auth state. - Return Retry-After on all rate-limited responses (remaining TTL on Redis, window duration on the in-memory limiter) so clients can back off. - Log the underlying error with request context when auth session errors map to 500 AUTH_INTERNAL_ERROR, and replace fmt.Println with request-scoped logging in the Redis rate limiter error paths. Fixes #6361
This commit is contained in:
@@ -147,6 +147,30 @@ describe('authentication session coordination', () => {
|
||||
assert.equal(transientCount, 1)
|
||||
})
|
||||
|
||||
test('a rate limited refresh remains retryable without clearing the session', async () => {
|
||||
let transientCount = 0
|
||||
let clearCount = 0
|
||||
const runtime: AuthRefreshRuntime = {
|
||||
request: async () => ({ status: 429 }),
|
||||
getExpectedSID: () => bundle.session.sid,
|
||||
parseBundle: () => null,
|
||||
acceptBundle: () => undefined,
|
||||
clear: () => {
|
||||
clearCount += 1
|
||||
},
|
||||
markTransient: () => {
|
||||
transientCount += 1
|
||||
},
|
||||
wait: async () => undefined,
|
||||
}
|
||||
|
||||
const outcome = await createRefreshRunner(runtime)()
|
||||
|
||||
assert.equal(outcome.kind, 'transient_error')
|
||||
assert.equal(clearCount, 0)
|
||||
assert.equal(transientCount, 1)
|
||||
})
|
||||
|
||||
test('an exhausted refresh race clears the unusable local session', async () => {
|
||||
const requestedDelays: number[] = []
|
||||
const clears: Array<[boolean, string | undefined]> = []
|
||||
|
||||
@@ -253,7 +253,7 @@ export function createRefreshRunner(
|
||||
return { kind: 'anonymous' }
|
||||
}
|
||||
|
||||
if (!response.status || response.status >= 500) {
|
||||
if (!response.status || response.status >= 500 || response.status === 429) {
|
||||
runtime.markTransient()
|
||||
return {
|
||||
kind: 'transient_error',
|
||||
|
||||
Reference in New Issue
Block a user