docs(auth): trim wordy refresh-dedup and retry comments

This commit is contained in:
kolaente 2026-06-19 20:27:37 +02:00
parent fa34e955c0
commit 95e4cf43b5
2 changed files with 10 additions and 17 deletions

View File

@ -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<void> | null = null
/**
@ -47,10 +46,8 @@ let inFlightRefresh: Promise<void> | 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<void> {
if (inFlightRefresh) {

View File

@ -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<void> {
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()