import { writable, derived } from 'svelte/store'; import type { User } from 'oidc-client-ts'; import { userManager, isOidcConfigured } from './oidcConfig'; // Stores export const user = writable(null); export const isLoading = writable(true); export const isAuthenticated = derived(user, ($user) => $user !== null); export const isConfigured = isOidcConfigured; // Cookie management function setCookieFromUser(u: User) { if (!u?.access_token) return; const isProduction = window.location.hostname !== 'localhost'; const domain = isProduction ? '.orfl.xyz' : undefined; const secure = isProduction; const sameSite = isProduction ? 'None' : 'Lax'; const cookieValue = `fa_session=${u.access_token}; path=/; ${secure ? 'secure; ' : ''}samesite=${sameSite}${domain ? `; domain=${domain}` : ''}`; document.cookie = cookieValue; } function clearFaSessionCookie() { const isProduction = window.location.hostname !== 'localhost'; const domain = isProduction ? '.orfl.xyz' : undefined; const cookieValue = `fa_session=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT${domain ? `; domain=${domain}` : ''}`; document.cookie = cookieValue; } // Track if callback has been handled to prevent double processing let callbackHandled = false; export async function initAuth() { if (!userManager) { isLoading.set(false); return; } // Handle callback if auth params are present const url = new URL(window.location.href); const hasAuthParams = url.searchParams.has('code') || url.searchParams.has('id_token') || url.searchParams.has('error'); if (hasAuthParams && !callbackHandled) { callbackHandled = true; try { const result = await userManager.signinRedirectCallback(); user.set(result ?? null); if (result) { setCookieFromUser(result); } } catch (e) { console.error('Failed to complete sign-in redirect', e); } finally { const cleanUrl = `${url.origin}${url.pathname}`; window.history.replaceState({}, document.title, cleanUrl); } } // Load existing user try { const loadedUser = await userManager.getUser(); user.set(loadedUser ?? null); if (loadedUser) { setCookieFromUser(loadedUser); } } catch (e) { console.error('Failed to load user', e); } isLoading.set(false); // Event listeners userManager.events.addUserLoaded((u) => { user.set(u); setCookieFromUser(u); }); userManager.events.addUserUnloaded(() => { user.set(null); clearFaSessionCookie(); }); userManager.events.addUserSignedOut(() => { user.set(null); clearFaSessionCookie(); }); } export async function login() { if (!userManager) { console.warn('OIDC is not configured; set PUBLIC_OIDC_* environment variables.'); return; } await userManager.signinRedirect(); } export async function logout() { if (!userManager) { console.warn('OIDC is not configured; set PUBLIC_OIDC_* environment variables.'); return; } try { clearFaSessionCookie(); await userManager.signoutRedirect(); } catch (error) { console.error('Failed to sign out via redirect, clearing local session instead.', error); await userManager.removeUser(); user.set(null); } }