fix: keep the Lite session when the token endpoint is only rate limiting

Bulwark Lite deleted the remembered refresh token on any non-5xx error
from `/auth/token`, so a 429 or 408 during a busy moment signed the
user out for good. Like the server build, it now clears the token only
when the server refuses it (400, 401, 403) and treats everything else
as an outage.
This commit is contained in:
Linus Rath
2026-09-26 16:17:29 +02:00
parent aa0075a8e1
commit f9af701bb9
2 changed files with 13 additions and 1 deletions
+7
View File
@@ -233,6 +233,13 @@ describe('liteRefreshTokens', () => {
expect(readLiteRefreshToken(0)?.refreshToken).toBe('RT');
});
it.each([429, 408])('keeps the token on a %i, which is an outage and not a sign-out', async (status) => {
saveLiteRefreshToken(0, { serverUrl: SERVER, username: 'a', refreshToken: 'RT' }, true);
fetchMock.mockResolvedValue(new Response('', { status }));
await expect(liteRefreshTokens(0)).rejects.toMatchObject({ code: 'token_exchange_failed', status });
expect(readLiteRefreshToken(0)?.refreshToken).toBe('RT');
});
it('propagates network errors and keeps the token', async () => {
saveLiteRefreshToken(0, { serverUrl: SERVER, username: 'a', refreshToken: 'RT' }, true);
fetchMock.mockRejectedValue(new TypeError('offline'));
+6 -1
View File
@@ -356,7 +356,12 @@ export async function liteRefreshTokens(slot: number, clientIdOverride?: string)
}).toString(),
});
if (response.status >= 500) {
// Only a definitive refusal (400/401/403) ends the session, as in the
// server build. A rate limit (429), a request timeout (408) or a 5xx is an
// outage: the refresh token stays, so the session resumes once the server
// answers again.
const refused = response.status === 400 || response.status === 401 || response.status === 403;
if (!response.ok && !refused) {
throw new LiteLoginError('token_exchange_failed', response.status);
}
const tokens = (await response.json().catch(() => ({}))) as TokenResponse;