From 95e4cf43b503bfac4bfc69376f999d5d7f3d0a22 Mon Sep 17 00:00:00 2001 From: kolaente Date: Fri, 19 Jun 2026 20:27:37 +0200 Subject: [PATCH] docs(auth): trim wordy refresh-dedup and retry comments --- frontend/src/helpers/auth.ts | 15 ++++++--------- frontend/src/stores/auth.ts | 12 ++++-------- 2 files changed, 10 insertions(+), 17 deletions(-) diff --git a/frontend/src/helpers/auth.ts b/frontend/src/helpers/auth.ts index 1652d169d..db1d967ba 100644 --- a/frontend/src/helpers/auth.ts +++ b/frontend/src/helpers/auth.ts @@ -35,11 +35,10 @@ export const removeToken = () => { localStorage.removeItem('desktopOAuthRefreshToken') } -// Coalesces concurrent refresh calls in the same tab into a single underlying -// refresh. The Web Locks API below only exists in secure contexts, so on -// insecure HTTP it falls back to an uncoordinated refresh — without this guard, -// triggers that fire close together (focus, proactive timer, 401 interceptor) -// each POST with the same single-use refresh cookie and all but one get a 401. +// Coalesces concurrent same-tab refreshes into one POST. Web Locks (below) is +// secure-context-only, so on insecure HTTP there's no cross-tab coordination — +// without this guard, refreshes firing close together each spend the single-use +// cookie and all but one get a 401. let inFlightRefresh: Promise | null = null /** @@ -47,10 +46,8 @@ let inFlightRefresh: Promise | null = null * The refresh token is sent automatically as an HttpOnly cookie. * The server rotates the cookie on every call. * - * Concurrent calls in the same tab share one in-flight refresh. This is the - * always-on primary dedup and works in every context (HTTP included). The Web - * Locks API used inside is the secondary, cross-tab coordination layer that - * only exists in secure contexts. + * Same-tab concurrent calls share one in-flight refresh (always-on dedup); the + * Web Locks API inside adds cross-tab coordination only in secure contexts. */ export async function refreshToken(persist: boolean): Promise { if (inFlightRefresh) { diff --git a/frontend/src/stores/auth.ts b/frontend/src/stores/auth.ts index 91f72a10d..d9096015d 100644 --- a/frontend/src/stores/auth.ts +++ b/frontend/src/stores/auth.ts @@ -55,12 +55,9 @@ function redirectToSpecifiedProvider() { } } -// Refreshes the token, retrying exactly once if the first attempt fails. -// After a lost refresh race (common on insecure HTTP without Web Locks, or -// behind a proxy that delays the rotated Set-Cookie), the browser's cookie is -// already the rotated, valid one — a second attempt then succeeds. Only when -// both attempts fail is the session genuinely dead. Exactly one retry, so a -// truly dead session still logs out without looping. +// A race-loser's refresh fails but the rotated cookie is already valid, so a +// second attempt succeeds — recovering what would otherwise be a spurious +// logout. Exactly one retry: a genuinely dead session still logs out, no loop. async function refreshTokenWithRetry(persist: boolean): Promise { try { await refreshToken(persist) @@ -525,8 +522,7 @@ export const useAuthStore = defineStore('auth', () => { const response = await HTTP.post('user/token') saveToken(response.data.token, false) } else { - // User sessions renew via the refresh-token cookie. Retry once so - // a lost refresh race doesn't spuriously log the user out. + // User sessions renew via the refresh-token cookie. await refreshTokenWithRetry(true) } await checkAuth()