fix: sync backend and frontend token refresh logic (#614)

* sync backend and frontend token refresh logic

* return react strict mode

---------

Co-authored-by: Igor Loskutov <igor.loskutoff@gmail.com>
This commit is contained in:
Igor Monadical
2025-09-08 10:40:18 -04:00
committed by GitHub
parent 02a3938822
commit 5a5b323382
3 changed files with 15 additions and 8 deletions

View File

@@ -9,9 +9,7 @@
import { useEffect } from "react"; import { useEffect } from "react";
import { useAuth } from "./AuthProvider"; import { useAuth } from "./AuthProvider";
import { REFRESH_ACCESS_TOKEN_BEFORE } from "./auth"; import { shouldRefreshToken } from "./auth";
const REFRESH_BEFORE = REFRESH_ACCESS_TOKEN_BEFORE;
export function SessionAutoRefresh({ children }) { export function SessionAutoRefresh({ children }) {
const auth = useAuth(); const auth = useAuth();
@@ -25,8 +23,7 @@ export function SessionAutoRefresh({ children }) {
const INTERVAL_REFRESH_MS = 5000; const INTERVAL_REFRESH_MS = 5000;
const interval = setInterval(() => { const interval = setInterval(() => {
if (accessTokenExpires === null) return; if (accessTokenExpires === null) return;
const timeLeft = accessTokenExpires - Date.now(); if (shouldRefreshToken(accessTokenExpires)) {
if (timeLeft < REFRESH_BEFORE) {
auth auth
.update() .update()
.then(() => {}) .then(() => {})

View File

@@ -2,6 +2,11 @@ export const REFRESH_ACCESS_TOKEN_ERROR = "RefreshAccessTokenError" as const;
// 4 min is 1 min less than default authentic value. here we assume that authentic won't be set to access tokens < 4 min // 4 min is 1 min less than default authentic value. here we assume that authentic won't be set to access tokens < 4 min
export const REFRESH_ACCESS_TOKEN_BEFORE = 4 * 60 * 1000; export const REFRESH_ACCESS_TOKEN_BEFORE = 4 * 60 * 1000;
export const shouldRefreshToken = (accessTokenExpires: number): boolean => {
const timeLeft = accessTokenExpires - Date.now();
return timeLeft < REFRESH_ACCESS_TOKEN_BEFORE;
};
export const LOGIN_REQUIRED_PAGES = [ export const LOGIN_REQUIRED_PAGES = [
"/transcripts/[!new]", "/transcripts/[!new]",
"/browse(.*)", "/browse(.*)",

View File

@@ -10,6 +10,7 @@ import {
import { import {
REFRESH_ACCESS_TOKEN_BEFORE, REFRESH_ACCESS_TOKEN_BEFORE,
REFRESH_ACCESS_TOKEN_ERROR, REFRESH_ACCESS_TOKEN_ERROR,
shouldRefreshToken,
} from "./auth"; } from "./auth";
import { import {
getTokenCache, getTokenCache,
@@ -85,9 +86,13 @@ export const authOptions: AuthOptions = {
"currentToken from cache", "currentToken from cache",
JSON.stringify(currentToken, null, 2), JSON.stringify(currentToken, null, 2),
"will be returned?", "will be returned?",
currentToken && Date.now() < currentToken.token.accessTokenExpires, currentToken &&
!shouldRefreshToken(currentToken.token.accessTokenExpires),
); );
if (currentToken && Date.now() < currentToken.token.accessTokenExpires) { if (
currentToken &&
!shouldRefreshToken(currentToken.token.accessTokenExpires)
) {
return currentToken.token; return currentToken.token;
} }
@@ -128,7 +133,7 @@ async function lockedRefreshAccessToken(
if (cached) { if (cached) {
if (Date.now() - cached.timestamp > TOKEN_CACHE_TTL) { if (Date.now() - cached.timestamp > TOKEN_CACHE_TTL) {
await deleteTokenCache(tokenCacheRedis, `token:${token.sub}`); await deleteTokenCache(tokenCacheRedis, `token:${token.sub}`);
} else if (Date.now() < cached.token.accessTokenExpires) { } else if (!shouldRefreshToken(cached.token.accessTokenExpires)) {
console.debug("returning cached token", cached.token); console.debug("returning cached token", cached.token);
return cached.token; return cached.token;
} }