From 1e6af005a9914e28f4bb0afafaeb88f4d8e2a270 Mon Sep 17 00:00:00 2001 From: Dylan De Faoite Date: Thu, 15 Oct 2026 21:10:22 +0100 Subject: [PATCH] implement on frontend --- frontend/src/auth/AuthContext.ts | 4 +- frontend/src/auth/AuthProvider.tsx | 97 ++++++++++++++++--- frontend/src/utils/api/client.ts | 65 +++++++++++-- frontend/src/utils/api/users.ts | 28 ++++-- .../configuration/SecurityConfig.java | 11 ++- .../vodsystem/controllers/UserController.java | 17 ++-- .../controllers/dto/SessionResponse.java | 11 +++ .../com/ddf/vodsystem/security/JwtFilter.java | 2 +- 8 files changed, 194 insertions(+), 41 deletions(-) create mode 100644 src/main/java/com/ddf/vodsystem/controllers/dto/SessionResponse.java diff --git a/frontend/src/auth/AuthContext.ts b/frontend/src/auth/AuthContext.ts index 9684f2e..1fa7b5d 100644 --- a/frontend/src/auth/AuthContext.ts +++ b/frontend/src/auth/AuthContext.ts @@ -8,9 +8,9 @@ type AuthContextValue = { loading: boolean; /** Exchange a Google credential for a session, then load the user. */ login: (googleCredential: string) => Promise; - /** End the session and clear the user. */ + /** End the session and clear the user. The local session is cleared even if the server call fails. */ logout: () => Promise; - /** Re-fetch the current user (e.g. after a profile change). */ + /** Re-fetch the current user (e.g. after a profile change). Token refresh is handled automatically. */ refresh: () => Promise; }; diff --git a/frontend/src/auth/AuthProvider.tsx b/frontend/src/auth/AuthProvider.tsx index b1ee12e..97c5701 100644 --- a/frontend/src/auth/AuthProvider.tsx +++ b/frontend/src/auth/AuthProvider.tsx @@ -1,19 +1,66 @@ -import { useCallback, useEffect, useState } from "react"; +import { useCallback, useEffect, useRef, useState } from "react"; import type { ReactNode } from "react"; import type { User } from "../utils/types.ts"; import { login as apiLogin, logout as apiLogout, getUser } from "../utils/api/users.ts"; import { AuthContext } from "./AuthContext.ts"; -import {registerUnauthorizedHandler} from "../utils/api/client.ts"; +import { + refreshSession, + registerSessionRefreshedHandler, + registerUnauthorizedHandler, +} from "../utils/api/client.ts"; + +/** Refresh this long before the access token expires, so in-flight requests never see it lapse. */ +const REFRESH_MARGIN_MS = 60_000; +/** How soon to try again when a scheduled refresh fails because the network is down. */ +const RETRY_DELAY_MS = 30_000; /** * Owns the single source of truth for the authenticated user. Everything that * needs to know who is logged in — the layout, the top bar, protected pages — * reads it through the `useAuth` hook rather than fetching the user itself. + * + * It also keeps the session alive: the access token is refreshed shortly + * before it expires, rather than waiting for a request to fail. That matters + * for