Redirect to login when authentication expires

Related to #626

When authentication expires after some time, users see "Connection lost"
and must refresh the page to see "Authentication required". This commit
implements automatic redirect to login when authentication expires.

Changes:
- Add authentication check to WebSocket endpoint to prevent unauthenticated
  WebSocket connections
- Handle WebSocket close with code 1008 (policy violation) as auth failure
  and redirect to login
- Intercept 401 responses on API calls (except initial auth checks) and
  automatically redirect to login page
- Clear stored credentials and set logout flag before redirect to ensure
  clean login flow

This provides a better user experience by immediately redirecting to the
login page when the session expires, rather than showing a confusing
"Connection lost" message that requires manual page refresh.
This commit is contained in:
rcourtman 2025-11-05 19:36:01 +00:00
parent b44084af3c
commit 059e8bf562
3 changed files with 27 additions and 5 deletions

View file

@ -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();
};

View file

@ -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

View file

@ -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)
}