TASK-004: Bootstrap frontend auth state from backend session check
Validates session on app mount by calling GET /api/auth/session instead of relying solely on cached sessionStorage. This ensures the UI state always reflects server reality — expired or revoked sessions are detected immediately. Changes: - Backend: Add GET /api/auth/session endpoint (requires valid session, returns 200/401) - Frontend: Add useSessionValidation hook for mount-time validation - Frontend: Add SessionValidationLoading component for validation spinner - Frontend: Update AuthProvider to call validation on mount with loading state - Frontend: Add validateSession API function - Docs: Update Features.md with session validation behavior - Docs: Update Web-Development.md with session validation pattern Handles three outcomes: 1. Valid session (200): Proceed with cached state 2. Invalid session (401): Clear sessionStorage and redirect to login 3. Network error: Don't logout (backend may be temporarily unreachable) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* Authentication API functions.
|
||||
*
|
||||
* Wraps calls to POST /api/auth/login and POST /api/auth/logout
|
||||
* Wraps calls to POST /api/auth/login, POST /api/auth/logout, and GET /api/auth/session
|
||||
* using the central typed fetch client.
|
||||
*/
|
||||
|
||||
@@ -27,3 +27,17 @@ export async function login(password: string): Promise<LoginResponse> {
|
||||
export async function logout(): Promise<LogoutResponse> {
|
||||
return api.post<LogoutResponse>(ENDPOINTS.authLogout, {});
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the current session with the backend.
|
||||
*
|
||||
* This is called on app mount to confirm the session is still valid on the
|
||||
* server side, rather than relying solely on the cached sessionStorage flag.
|
||||
*
|
||||
* @param signal - Optional abort signal for request cancellation.
|
||||
* @returns An object confirming the session is valid.
|
||||
* @throws {ApiError} When the session is invalid or expired (401).
|
||||
*/
|
||||
export async function validateSession(signal?: AbortSignal): Promise<{ valid: boolean }> {
|
||||
return api.get<{ valid: boolean }>(ENDPOINTS.authSession, signal);
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ export const ENDPOINTS = {
|
||||
// -------------------------------------------------------------------------
|
||||
authLogin: "/auth/login",
|
||||
authLogout: "/auth/logout",
|
||||
authSession: "/auth/session",
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Dashboard
|
||||
|
||||
Reference in New Issue
Block a user