# Hook per l’autenticazione in SvelteKit: handle, locals e redirect

In SvelteKit l’autenticazione vive in hooks.server.ts: handle legge il cookie, riempie locals e il redirect sta nel load del gruppo protetto.

> Pagina: https://ui.eneawork.it/blog/sveltekit-hooks-auth
> Markdown: https://ui.eneawork.it/blog/sveltekit-hooks-auth.md

*2026-11-01*

In SvelteKit l’autenticazione si aggancia a handle in src/hooks.server.ts: la funzione gira su ogni richiesta, legge il cookie di sessione e riempie event.locals, che load e form action leggono senza ripetere la query.

## handle vede tutte le richieste

Il file si chiama hooks.server.ts e non ha equivalente lato client: nessun codice del browser può scrivere locals. Il tipo si dichiara in app.d.ts, altrimenti TypeScript vede un oggetto vuoto.

openssl rand -base64 32

// src/hooks.server.ts import type { Handle } from "@sveltejs/kit"; export const handle: Handle = async ({ event, resolve }) => { const token = event.cookies.get("session"); event.locals.user = token ? await readSession(token) : null; return resolve(event); };

La dichiarazione dei tipi sta in src/app.d.ts e vale per tutto il progetto: senza, ogni lettura di locals.user è un errore di compilazione.

// src/app.d.ts declare global { namespace App { interface Locals { user: { id: string; role: "admin" | "member" } | null; } } } export {};

## Il controllo sta nel load del gruppo

Il redirect non va nel componente: va in un +layout.server.ts che copre il gruppo di pagine protette, così la regola vive in un file invece che in dieci.

// src/routes/(app)/+layout.server.ts import { redirect } from "@sveltejs/kit"; export const load = ({ locals, url }) => { if (!locals.user) redirect(303, `/login?next=${url.pathname}`); return { user: locals.user }; };

## Più hook, in ordine

sequence() compone più funzioni handle: la prima legge il cookie, la seconda registra la richiesta, la terza applica la regola. L’ordine è quello degli argomenti, quindi chi legge locals.user viene dopo chi lo scrive.

Misurato il 1 novembre 2026: su 1.556 blocchi del catalogo 15 categorie riguardano il login e 10 l’autenticazione, su 99 categorie totali. Metodo: conteggio del campo categories di data/blocks.json con uno script Node, sul repository EneUI.

## Il limite da mettere in conto

Gli hook non girano per le pagine prerenderizzate: una pagina con export const prerender = true viene costruita una volta e non può controllare la sessione. E handle gira anche per gli asset, quindi va tenuto corto.

## Errori che si vedono

Le pagine che l’hook protegge si compongono da blocchi pronti: login e authentication coprono accesso e recupero, e flowbite-svelte fornisce i campi. Il caricamento dei dati è in load server vs universal, la validazione in form actions in SvelteKit, i file di rotta in routing e layout in SvelteKit, il confronto in Svelte vs React.

## FAQ

### Posso proteggere solo alcune pagine?

Sì, mettendo il controllo in un +layout.server.ts dentro un gruppo di rotte, per esempio (app). Le pagine fuori dal gruppo non passano da quel load e restano pubbliche senza toccare l’hook.

### Dove salvo la sessione?

In un cookie httpOnly, secure e sameSite lax, con un identificativo opaco e non i dati dell’utente. Il cookie viaggia su ogni richiesta, quindi deve essere piccolo e firmato.

### Perché locals è vuoto in TypeScript?

Perché manca la dichiarazione in src/app.d.ts. Senza l’interfaccia App.Locals il compilatore non conosce i campi che handle scrive e li segnala come assenti.

### Serve un hook per l’autorizzazione?

No, la lettura della sessione basta in un hook. Il permesso dipende dalla rotta e dal dato, quindi si controlla nel load o nell’azione che tocca quel dato, dove il contesto è noto.

### Come funziona con più hook?

Con sequence(), che li esegue in ordine e passa il risultato del primo resolve al successivo. Senza sequence vince l’ultima esportazione handle, e le altre vengono ignorate.
