From 62b1a34a682af261c2f30b1d6e48ce19aa35e4fe Mon Sep 17 00:00:00 2001 From: Barkley Trimsworth Date: Mon, 30 Mar 2026 18:58:39 +0000 Subject: [PATCH] fix: redirect unauthenticated users from customer portal to login When CustomerPortal mounts without a valid sessionId param or when session creation fails, the portal chrome was rendering for unauthenticated users. Add initComplete + sessionError state to track async initialization, and redirect to /login when no valid session exists after init completes. Co-Authored-By: Paperclip --- apps/web/src/portal/CustomerPortal.tsx | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/apps/web/src/portal/CustomerPortal.tsx b/apps/web/src/portal/CustomerPortal.tsx index 65a17e3..7fb9d87 100644 --- a/apps/web/src/portal/CustomerPortal.tsx +++ b/apps/web/src/portal/CustomerPortal.tsx @@ -1,5 +1,5 @@ import { useState, useCallback, useEffect, useRef } from "react"; -import { useSearchParams } from "react-router-dom"; +import { useSearchParams, Navigate } from "react-router-dom"; import { Home, Calendar, PawPrint, FileText, CreditCard, MessageSquare, Settings, LogOut, Shield, @@ -34,6 +34,8 @@ export function CustomerPortal() { const [mobileNavOpen, setMobileNavOpen] = useState(false); const [showAuditLog, setShowAuditLog] = useState(false); const [session, setSession] = useState(null); + const [sessionError, setSessionError] = useState(false); + const [initComplete, setInitComplete] = useState(false); const [sessionExtended, setSessionExtended] = useState(false); const { branding } = useBranding(); const [searchParams, setSearchParams] = useSearchParams(); @@ -45,7 +47,10 @@ export function CustomerPortal() { initDone.current = true; const sessionId = searchParams.get("sessionId"); - if (!sessionId) return; + if (!sessionId) { + setInitComplete(true); + return; + } fetch(`/api/impersonation/sessions/${sessionId}`) .then((r) => { @@ -55,15 +60,26 @@ export function CustomerPortal() { .then((s) => { if (s && s.status === "active") { setSession(s); + } else { + setSessionError(true); } // Clean sessionId from URL setSearchParams({}, { replace: true }); }) .catch(() => { + setSessionError(true); setSearchParams({}, { replace: true }); + }) + .finally(() => { + setInitComplete(true); }); }, []); + // Redirect to login if session initialization completed but no valid session exists + if (initComplete && !session) { + return ; + } + const handleEnd = useCallback(async () => { if (!session) return; try {