import { dev } from '$app/environment'; import { base } from '$app/paths'; import { sequence } from '@sveltejs/kit/hooks'; import { error, type Handle } from '@sveltejs/kit'; import { config } from '$lib/server/config'; import { estRoutePublique, resoudreUtilisateur } from '$lib/server/sso'; /** * Authentification SSO : l'utilisateur vient du header injecté par le reverse proxy * YunoHost (SSOwat). Sans utilisateur, seule la page d'accueil publique est accessible ; * toute autre route (pages et endpoints API) renvoie 401. */ const authHandle: Handle = async ({ event, resolve }) => { event.locals.user = resoudreUtilisateur(event.request.headers, { ssoHeader: config.ssoHeader, devUser: config.devUser, dev }); if (!event.locals.user && !estRoutePublique(event.url.pathname, base)) { error(401, 'Authentification requise'); } return resolve(event); }; /** En-têtes de sécurité complétant la CSP (gérée par la config SvelteKit, mode nonce). */ const securityHeadersHandle: Handle = async ({ event, resolve }) => { const response = await resolve(event); response.headers.set('X-Content-Type-Options', 'nosniff'); response.headers.set('Referrer-Policy', 'strict-origin-when-cross-origin'); response.headers.set('Permissions-Policy', 'camera=(), microphone=(), geolocation=()'); return response; }; export const handle = sequence(authHandle, securityHeadersHandle);