/** * auth-init.js — Enterprise Authentication Initialization * * Runs on page load to establish UI auth state and protect routes. * Strictly aligned with HTTP-Only Cookie architecture. */ (function initAuthState() { 'use strict'; const currentPath = window.location.pathname; // ── 1. Check if user just logged in ────────────────────────────────────── const justLoggedIn = sessionStorage.getItem('just_logged_in'); if (justLoggedIn) sessionStorage.removeItem('just_logged_in'); // ── 2. Sync User Metadata ──────────────────────────────────────────────── // We treat the 'user' object in localStorage as our UI "Auth Hint". // The actual security is handled by the invisible HTTP-Only access_token cookie. // Cookie Sync: Check for the 'qualora_logged_in' mirror cookie. // This allows JS to see if the server thinks we are authenticated (breaks 302 loops). function getCookie(name) { const value = `; ${document.cookie}`; const parts = value.split(`; ${name}=`); if (parts.length === 2) return parts.pop().split(';').shift(); return null; } const isLoggedIn = getCookie('qualora_logged_in') === 'true'; let userJSON = localStorage.getItem('user'); // Fallback to session if local is empty (e.g., privacy mode) if (!userJSON) { userJSON = sessionStorage.getItem('user'); if (userJSON) localStorage.setItem('user', userJSON); } let user = null; if (userJSON) { try { // If the mirror cookie is missing, the server session is gone. // We MUST purge the local 'Auth Hint' to prevent redirect loops. if (!isLoggedIn && !justLoggedIn) { localStorage.removeItem('user'); sessionStorage.removeItem('user'); userJSON = null; } else { user = JSON.parse(userJSON); // Validation: Ensure it's a real user object if (!user || (!user.email && !user._id)) { user = null; localStorage.removeItem('user'); } } } catch (e) { console.warn('[Qualora] Failed to parse user metadata:', e.message); localStorage.removeItem('user'); } } // ── 3. Route Guarding ──────────────────────────────────────────────────── // List of routes that require an authenticated session const protectedRoutes = ['/dashboard', '/audit', '/admin', '/knowledge-base', '/agents']; const isProtectedRoute = protectedRoutes.some(route => currentPath.startsWith(route)); if (isProtectedRoute && !user) { // Race condition check: If we just logged in, allow temporary pass-through if (justLoggedIn) { user = { _id: 'loading', email: 'loading...', temp: true }; } else { console.warn('[Qualora] Unauthorized access attempt. Redirecting to landing.'); window.location.href = '/'; return; } } // ── 4. Landing Page Logic ──────────────────────────────────────────────── // If authenticated and sitting on landing page, move to dashboard if ((currentPath === '/' || currentPath === '/index.html') && user && !user.temp) { window.location.href = '/dashboard'; return; } // ── 5. Establish Global Auth Context ───────────────────────────────────── // NOTE: 'token' is now null because it is hidden in an HTTP-Only cookie. window.__authState = { isAuthenticated: !!user && !user.temp, user: user, cookieManaged: true, // Internal flag for fetch-wrapper lastChecked: new Date().toISOString() }; // Notify other modules (like nav-controllers) that auth state is ready document.dispatchEvent(new CustomEvent('authStateReady', { detail: window.__authState })); console.log(`[Qualora] Auth initialized. Mode: ${user ? 'Authenticated' : 'Guest'}`); })();