From f8fc3fa9c4a406b7ac43cc45de716d66e104a6e9 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 18 Nov 2025 20:30:37 +0000 Subject: [PATCH] Fix complete session handling for 401 errors in all hooks - Add baseApiService token clearing on 401 in use-user.ts - Add baseApiService token clearing on 401 in use-chats.ts (both fetchChats and deleteChat) - Add baseApiService token clearing on 401 in use-search-space.ts - Update all redirects to /login?error=session_expired for better UX - Add session_expired error message to auth-errors.ts This ensures consistent session invalidation across all API hooks, preventing stale auth state in the baseApiService singleton. --- surfsense_web/hooks/use-chats.ts | 11 +++++++---- surfsense_web/hooks/use-search-space.ts | 6 ++++-- surfsense_web/hooks/use-user.ts | 7 +++++-- surfsense_web/lib/auth-errors.ts | 6 ++++++ 4 files changed, 22 insertions(+), 8 deletions(-) diff --git a/surfsense_web/hooks/use-chats.ts b/surfsense_web/hooks/use-chats.ts index e6233e55b..e39a2062b 100644 --- a/surfsense_web/hooks/use-chats.ts +++ b/surfsense_web/hooks/use-chats.ts @@ -2,6 +2,7 @@ import { useCallback, useEffect, useState } from "react"; import { toast } from "sonner"; +import { baseApiService } from "@/lib/apis/base-api.service"; interface Chat { created_at: string; @@ -46,9 +47,10 @@ export function useChats({ ); if (response.status === 401) { - // Clear token and redirect to home + // Clear token from both localStorage and baseApiService localStorage.removeItem("surfsense_bearer_token"); - window.location.href = "/"; + baseApiService.setBearerToken(""); + window.location.href = "/login?error=session_expired"; throw new Error("Unauthorized: Redirecting to login page"); } @@ -90,9 +92,10 @@ export function useChats({ ); if (response.status === 401) { - // Clear token and redirect to home + // Clear token from both localStorage and baseApiService localStorage.removeItem("surfsense_bearer_token"); - window.location.href = "/"; + baseApiService.setBearerToken(""); + window.location.href = "/login?error=session_expired"; throw new Error("Unauthorized: Redirecting to login page"); } diff --git a/surfsense_web/hooks/use-search-space.ts b/surfsense_web/hooks/use-search-space.ts index 2c512b954..8113a24ec 100644 --- a/surfsense_web/hooks/use-search-space.ts +++ b/surfsense_web/hooks/use-search-space.ts @@ -2,6 +2,7 @@ import { useCallback, useEffect, useState } from "react"; import { toast } from "sonner"; +import { baseApiService } from "@/lib/apis/base-api.service"; interface SearchSpace { created_at: string; @@ -38,9 +39,10 @@ export function useSearchSpace({ searchSpaceId, autoFetch = true }: UseSearchSpa ); if (response.status === 401) { - // Clear token and redirect to home + // Clear token from both localStorage and baseApiService localStorage.removeItem("surfsense_bearer_token"); - window.location.href = "/"; + baseApiService.setBearerToken(""); + window.location.href = "/login?error=session_expired"; throw new Error("Unauthorized: Redirecting to login page"); } diff --git a/surfsense_web/hooks/use-user.ts b/surfsense_web/hooks/use-user.ts index 23a23237b..d8105740f 100644 --- a/surfsense_web/hooks/use-user.ts +++ b/surfsense_web/hooks/use-user.ts @@ -2,6 +2,7 @@ import { useEffect, useState } from "react"; import { toast } from "sonner"; +import { baseApiService } from "@/lib/apis/base-api.service"; interface User { id: string; @@ -33,9 +34,11 @@ export function useUser() { }); if (response.status === 401) { - // Clear token and redirect to home + // Clear token from both localStorage and baseApiService localStorage.removeItem("surfsense_bearer_token"); - window.location.href = "/"; + baseApiService.setBearerToken(""); + // Redirect to login with session expired message + window.location.href = "/login?error=session_expired"; throw new Error("Unauthorized: Redirecting to login page"); } diff --git a/surfsense_web/lib/auth-errors.ts b/surfsense_web/lib/auth-errors.ts index ce50c9c99..0becb4932 100644 --- a/surfsense_web/lib/auth-errors.ts +++ b/surfsense_web/lib/auth-errors.ts @@ -92,6 +92,12 @@ const AUTH_ERROR_MESSAGES: AuthErrorMapping = { description: "Login is temporarily unavailable. Please try again later", }, + // Session errors + session_expired: { + title: "Session expired", + description: "Your session has expired. Please sign in again", + }, + // Network errors NETWORK_ERROR: { title: "Connection failed",