diff --git a/frontend-modern/src/stores/websocket.ts b/frontend-modern/src/stores/websocket.ts index 722fbd584..076d3ad4a 100644 --- a/frontend-modern/src/stores/websocket.ts +++ b/frontend-modern/src/stores/websocket.ts @@ -611,6 +611,18 @@ export function createWebSocketStore(url: string) { return; } + // If we get a 1008 (policy violation) close code, it's likely an auth failure + // Redirect to login page to re-authenticate + if (event.code === 1008) { + logger.warn('WebSocket closed due to authentication failure, redirecting to login'); + // Clear auth and reload to trigger login + if (typeof window !== 'undefined') { + localStorage.setItem('just_logged_out', 'true'); + window.location.href = '/'; + } + return; + } + handleReconnect(); }; diff --git a/frontend-modern/src/utils/apiClient.ts b/frontend-modern/src/utils/apiClient.ts index b5d86104c..177d84148 100644 --- a/frontend-modern/src/utils/apiClient.ts +++ b/frontend-modern/src/utils/apiClient.ts @@ -219,11 +219,17 @@ class ApiClient { const response = await fetch(url, finalOptions); - // If we get a 401, our auth might be invalid - if (response.status === 401 && this.hasAuth()) { - // Could trigger a re-login flow here - logger.warn('Authentication failed - credentials may be incorrect'); - // Don't clear auth automatically - let the user retry + // If we get a 401 on an API call (not during initial auth check), redirect to login + // Skip redirect for specific auth-check endpoints to avoid loops + if (response.status === 401 && !url.includes('/api/security/status') && !url.includes('/api/state')) { + logger.warn('Authentication expired - redirecting to login'); + // Clear auth and redirect to login + if (typeof window !== 'undefined') { + this.clearAuth(); + localStorage.setItem('just_logged_out', 'true'); + window.location.href = '/'; + } + return response; } // Handle CSRF token failures diff --git a/internal/api/router.go b/internal/api/router.go index d18390292..42ac62767 100644 --- a/internal/api/router.go +++ b/internal/api/router.go @@ -2772,6 +2772,10 @@ func (r *Router) handleSnapshots(w http.ResponseWriter, req *http.Request) { // handleWebSocket handles WebSocket connections func (r *Router) handleWebSocket(w http.ResponseWriter, req *http.Request) { + // Check authentication before allowing WebSocket upgrade + if !CheckAuth(r.config, w, req) { + return + } r.wsHub.HandleWebSocket(w, req) }