diff --git a/src/core/auth/auth-options.ts b/src/core/auth/auth-options.ts index 7d7c7f5..b5b4898 100644 --- a/src/core/auth/auth-options.ts +++ b/src/core/auth/auth-options.ts @@ -64,7 +64,7 @@ async function refreshAuthentikToken(token: JWT): Promise { }; if (!res.ok || !body.access_token) { console.warn("[auth] refresh failed:", res.status, body.error); - return { ...token, error: "RefreshAccessTokenError" }; + return { ...token, error: "RefreshAccessTokenError", errorAt: Date.now() }; } console.log("[auth] refresh OK expires_in=%d", body.expires_in ?? 300); return { @@ -77,7 +77,7 @@ async function refreshAuthentikToken(token: JWT): Promise { } catch (err) { const msg = err instanceof Error ? err.message : String(err); console.warn("[auth] refresh error:", msg); - return { ...token, error: "RefreshAccessTokenError" }; + return { ...token, error: "RefreshAccessTokenError", errorAt: Date.now() }; } finally { inflightRefreshes.delete(refreshToken); } @@ -142,18 +142,23 @@ export const authOptions: NextAuthOptions = { const exp = typeof token.accessTokenExpires === "number" ? token.accessTokenExpires : 0; + const errorAt = typeof token.errorAt === "number" ? token.errorAt : 0; + const cooldownDone = Date.now() - errorAt > 60_000; + const blocked = + token.error === "RefreshAccessTokenError" && !cooldownDone; const secLeft = Math.round((exp - Date.now()) / 1000); console.log( - "[auth] jwt secLeft=%d hasAccess=%s hasRefresh=%s err=%s", + "[auth] jwt secLeft=%d hasAccess=%s hasRefresh=%s err=%s blocked=%s", secLeft, !!token.accessToken, !!token.refreshToken, token.error ?? "none", + blocked, ); if ( token.accessToken && token.refreshToken && - token.error !== "RefreshAccessTokenError" && + !blocked && Date.now() > exp - 30_000 ) { return refreshAuthentikToken(token);