diff --git a/surfsense_backend/app/config/__init__.py b/surfsense_backend/app/config/__init__.py index 47e529741..63de28bfc 100644 --- a/surfsense_backend/app/config/__init__.py +++ b/surfsense_backend/app/config/__init__.py @@ -916,7 +916,7 @@ class Config: # JWT Token Lifetimes ACCESS_TOKEN_LIFETIME_SECONDS = int( - os.getenv("ACCESS_TOKEN_LIFETIME_SECONDS", str(30 * 60)) # 30 minutes + os.getenv("ACCESS_TOKEN_LIFETIME_SECONDS", str(60 * 60)) # 60 minutes ) MIN_ISSUED_AT = int(os.getenv("MIN_ISSUED_AT", "0")) REFRESH_TOKEN_LIFETIME_SECONDS = int( diff --git a/surfsense_web/app/dashboard/[search_space_id]/new-chat/[[...chat_id]]/page.tsx b/surfsense_web/app/dashboard/[search_space_id]/new-chat/[[...chat_id]]/page.tsx index 407a9c53b..a9851cbbc 100644 --- a/surfsense_web/app/dashboard/[search_space_id]/new-chat/[[...chat_id]]/page.tsx +++ b/surfsense_web/app/dashboard/[search_space_id]/new-chat/[[...chat_id]]/page.tsx @@ -289,6 +289,16 @@ const TURN_CANCELLING_BACKOFF_FACTOR = 2; const TURN_CANCELLING_MAX_DELAY_MS = 1500; const RECENT_CANCEL_WINDOW_MS = 5_000; +async function getRequestHeadersWithCurrentDesktopAuth( + headers: Record = {} +): Promise> { + const token = await getDesktopAccessToken({ forceRefresh: true }); + return { + ...headers, + ...(token ? { Authorization: `Bearer ${token}` } : {}), + }; +} + function sleep(ms: number): Promise { return new Promise((resolve) => setTimeout(resolve, ms)); } @@ -941,13 +951,12 @@ export default function NewChatPage() { // Cancel ongoing request const cancelRun = useCallback(async () => { if (threadId) { - const token = await getDesktopAccessToken(); try { const response = await fetch( buildBackendUrl(`/api/v1/threads/${threadId}/cancel-active-turn`), { method: "POST", - headers: token ? { Authorization: `Bearer ${token}` } : undefined, + headers: await getRequestHeadersWithCurrentDesktopAuth(), credentials: "include", } ); @@ -995,8 +1004,6 @@ export default function NewChatPage() { if (!userQuery.trim() && userImages.length === 0) return; - const token = await getDesktopAccessToken(); - // Lazy thread creation: create thread on first message if it doesn't exist let currentThreadId = threadId; let isNewThread = false; @@ -1167,13 +1174,12 @@ export default function NewChatPage() { const hasConnectorIds = mentionPayload.connector_ids.length > 0; const hasThreadIds = mentionPayload.thread_ids.length > 0; - const response = await fetchWithTurnCancellingRetry(() => + const response = await fetchWithTurnCancellingRetry(async () => fetch(buildBackendUrl("/api/v1/new_chat"), { method: "POST", - headers: { + headers: await getRequestHeadersWithCurrentDesktopAuth({ "Content-Type": "application/json", - ...(token ? { Authorization: `Bearer ${token}` } : {}), - }, + }), credentials: "include", body: JSON.stringify({ chat_id: currentThreadId, @@ -1555,8 +1561,6 @@ export default function NewChatPage() { stagedDecisionsByInterruptIdRef.current.clear(); setIsRunning(true); - const token = await getDesktopAccessToken(); - const controller = new AbortController(); abortControllerRef.current = controller; @@ -1656,13 +1660,12 @@ export default function NewChatPage() { const selection = await getAgentFilesystemSelection(searchSpaceId, { localFilesystemEnabled, }); - const response = await fetchWithTurnCancellingRetry(() => + const response = await fetchWithTurnCancellingRetry(async () => fetch(buildBackendUrl(`/api/v1/threads/${resumeThreadId}/resume`), { method: "POST", - headers: { + headers: await getRequestHeadersWithCurrentDesktopAuth({ "Content-Type": "application/json", - ...(token ? { Authorization: `Bearer ${token}` } : {}), - }, + }), credentials: "include", body: JSON.stringify({ search_space_id: searchSpaceId, @@ -1995,8 +1998,6 @@ export default function NewChatPage() { abortControllerRef.current = null; } - const token = await getDesktopAccessToken(); - // Extract the original user query BEFORE removing messages (for reload mode) let userQueryToDisplay: string | undefined; let originalUserMessageContent: ThreadMessageLike["content"] | null = null; @@ -2113,13 +2114,12 @@ export default function NewChatPage() { requestBody.revert_actions = true; } } - const response = await fetchWithTurnCancellingRetry(() => + const response = await fetchWithTurnCancellingRetry(async () => fetch(getRegenerateUrl(threadId), { method: "POST", - headers: { + headers: await getRequestHeadersWithCurrentDesktopAuth({ "Content-Type": "application/json", - ...(token ? { Authorization: `Bearer ${token}` } : {}), - }, + }), credentials: "include", body: JSON.stringify(requestBody), signal: controller.signal,