From a5fec30bd07445ba6a19e7417e313331ce3c1d87 Mon Sep 17 00:00:00 2001 From: DHCross <45954119+DHCross@users.noreply.github.com> Date: Tue, 16 Dec 2025 19:53:14 -0600 Subject: [PATCH] Fix auth token refresh and restore last report CTA --- components/ChatClient.tsx | 25 ++++++++++++++++- hooks/useAuth.ts | 58 ++++++++++++++++++++++++++++++--------- 2 files changed, 69 insertions(+), 14 deletions(-) diff --git a/components/ChatClient.tsx b/components/ChatClient.tsx index ca7afca6..513fe64c 100644 --- a/components/ChatClient.tsx +++ b/components/ChatClient.tsx @@ -1212,7 +1212,7 @@ export default function ChatClient() { {/* Conditional guidance based on whether they have Math Brain data */} - {hasMathBrainSession === false && ( + {hasMathBrainSession === false && !canRecoverStoredPayload && (
@@ -1265,6 +1265,29 @@ export default function ChatClient() {
)} + {hasMathBrainSession !== true && canRecoverStoredPayload && ( +
+
+ 📂 +
+

Saved Math Brain report detected

+

+ I can restore your last export even though I couldn't automatically confirm Math Brain is active in this tab. + Load it below to start the structured Poetic Brain reading. +

+ +
+
+
+ )} + {/* Always available actions */}

Or explore without chart data:

diff --git a/hooks/useAuth.ts b/hooks/useAuth.ts index 47e47f39..fbd9fe70 100644 --- a/hooks/useAuth.ts +++ b/hooks/useAuth.ts @@ -83,7 +83,7 @@ export function useAuth() { const client = clientRef.current; if (!client) { // Fallback to stored token if client not ready - return typeof window !== 'undefined' + return typeof window !== 'undefined' ? window.localStorage.getItem(AUTH_TOKEN_KEY) : null; } @@ -102,16 +102,31 @@ export function useAuth() { if (token && typeof window !== 'undefined') { window.localStorage.setItem(AUTH_TOKEN_KEY, token); } - + return token; } catch (error) { console.warn('[useAuth] Failed to get token silently:', error); - - // If refresh fails, try to return cached token as last resort - // (it might still work if the error was transient) - return typeof window !== 'undefined' - ? window.localStorage.getItem(AUTH_TOKEN_KEY) - : null; + + // Clear any stale token so we do not keep sending invalid credentials + if (typeof window !== 'undefined') { + window.localStorage.removeItem(AUTH_TOKEN_KEY); + } + + // If login is required, force a redirect so the user can re-authenticate cleanly + const requiresLogin = (error as any)?.error === 'login_required' || (error as any)?.error === 'consent_required'; + if (requiresLogin) { + try { + await client.loginWithRedirect({ + authorizationParams: { + redirect_uri: getRedirectUri(), + } + }); + } catch (redirectError) { + console.warn('[useAuth] Redirect for re-auth failed:', redirectError); + } + } + + return null; } }, []); @@ -129,8 +144,8 @@ export async function getAccessTokenAsync(): Promise { const client = await getAuth0Client(); if (!client) { - return typeof window !== 'undefined' - ? window.localStorage.getItem(AUTH_TOKEN_KEY) + return typeof window !== 'undefined' + ? window.localStorage.getItem(AUTH_TOKEN_KEY) : null; } @@ -149,9 +164,26 @@ export async function getAccessTokenAsync(): Promise { return token; } catch (error) { console.warn('[getAccessTokenAsync] Failed to get token:', error); - return typeof window !== 'undefined' - ? window.localStorage.getItem(AUTH_TOKEN_KEY) - : null; + + // Clear stale token to avoid repeated invalid-session failures + if (typeof window !== 'undefined') { + window.localStorage.removeItem(AUTH_TOKEN_KEY); + } + + const requiresLogin = (error as any)?.error === 'login_required' || (error as any)?.error === 'consent_required'; + if (requiresLogin) { + try { + await client.loginWithRedirect({ + authorizationParams: { + redirect_uri: getRedirectUri(), + } + }); + } catch (redirectError) { + console.warn('[getAccessTokenAsync] Redirect for re-auth failed:', redirectError); + } + } + + return null; } }