37 lines
1.4 KiB
TypeScript
37 lines
1.4 KiB
TypeScript
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);
|