# Middleware per l’autenticazione in Next.js

Il middleware filtra le richieste, non autorizza: come leggere il cookie, verificare il token e proteggere anche le Server Actions.

> Pagina: https://ui.eneawork.it/blog/nextjs-middleware-autenticazione
> Markdown: https://ui.eneawork.it/blog/nextjs-middleware-autenticazione.md

*2026-11-01*

Il middleware legge il cookie di sessione e reindirizza prima che la pagina venga renderizzata, ma non è un controllo di autorizzazione. Il permesso si verifica nella pagina o nell’azione che legge il dato.

## Cosa può fare il middleware

npm install jose

## Un matcher, poi il redirect

// middleware.ts import { NextResponse, type NextRequest } from "next/server"; const PUBLIC = ["/login", "/signup"]; export function middleware(request: NextRequest) { const { pathname } = request.nextUrl; if (PUBLIC.some((path) => pathname.startsWith(path))) return NextResponse.next(); if (!request.cookies.get("session")) { const url = request.nextUrl.clone(); url.pathname = "/login"; url.searchParams.set("next", pathname); return NextResponse.redirect(url); } return NextResponse.next(); } export const config = { matcher: ["/((?!_next/static|_next/image|favicon.ico).*)"], };

Il matcher è parte della protezione: senza esclusione degli asset, il middleware gira su ogni immagine e su ogni file CSS. Next.js 16 ha rinominato il file in proxy.ts: la funzione e il matcher si comportano allo stesso modo, cambia il nome.

## Il cookie non è una prova

Un cookie si crea dal browser in dieci secondi. Il middleware qui controlla solo che il cookie esista, e questo va bene come prima scrematura: chi non ha il cookie non arriva alla pagina. La firma del token, invece, va verificata sul server, con una chiave che il client non possiede.

// lib/session.ts import { jwtVerify } from "jose"; const secret = new TextEncoder().encode(process.env.SESSION_SECRET); export async function verifySession(token?: string) { if (!token) return null; try { const { payload } = await jwtVerify(token, secret); return payload as { userId: string; role: string }; } catch { return null; } }

## Verifica dove il dato viene letto

La pagina non si fida del fatto che il middleware sia passato: ripete la verifica e filtra la query per l’utente della sessione. Se domani qualcuno cambia il matcher, il controllo resta. Questa è la differenza tra un cancello e una recinzione.

// app/dashboard/page.tsx import { cookies } from "next/headers"; import { redirect } from "next/navigation"; import { verifySession } from "@/lib/session"; export default async function DashboardPage() { const session = await verifySession((await cookies()).get("session")?.value); if (!session) redirect("/login"); const invoices = await db.invoice.findMany({ where: { userId: session.userId } }); return ; }

## Il costo di girare su tutto

Il middleware esegue su ogni richiesta che corrisponde al matcher, prima che la route esista. Una fetch esterna o una query al database lì dentro rallenta ogni pagina del sito, comprese quelle pubbliche. Tieni il controllo locale: un cookie, un header, un confronto di stringhe.

## Un blocco di login non è un sistema di sessioni

I blocchi di login e di autenticazione danno form, stati e markup, non la gestione del token. Il record Sign In mostra la parte visibile di un flusso completo. La sessione la costruisci tu: firma, scadenza, revoca.

Misurato il 1 novembre 2026 sul repository EneUI: dei 1.556 blocchi, 30 riguardano l’accesso (15 login, 10 authentication, 5 signup). Su 1.514 profili di libreria, 664 dichiarano una licenza MIT. Metodo: conteggio del campo categories in data/blocks.json e del campo license in data/library_profiles.json, con uno script Node.

## Errori che si vedono in produzione

## Un limite da dichiarare

Il middleware non revoca una sessione già emessa. Un token valido resta valido fino alla scadenza, anche dopo un logout o un cambio di password, a meno che la pagina non consulti una lista di revoca. Tieni la scadenza corta e la revoca nel punto che legge il dato.

I blocchi di accesso già pronti sono confrontati in i migliori blocchi di autenticazione; il confine tra server e client component è spiegato in server component che importa un hook. Il confronto 21st.dev vs shadcnblocks aiuta a scegliere da dove copiare il form.

## FAQ

### Il middleware basta per proteggere una pagina?

No. Filtra le richieste senza cookie, ma la verifica del token e del permesso deve avvenire nella pagina o nell’azione che legge il dato.

### Perché il middleware non può leggere il database?

Perché gira su un runtime leggero, senza driver Node. Una query lì dentro rallenta ogni richiesta e spesso non è nemmeno disponibile.

### Come evito un loop di redirect sul login?

Inserisci il login e le altre pagine pubbliche in una lista esclusa, controllata prima del redirect.

### Devo proteggere anche le Server Actions?

Sì. Un’azione è un endpoint POST: chi la chiama non passa dal middleware della pagina, quindi ripeti il controllo dentro l’azione.

### Middleware o proxy in Next.js 16?

Sono la stessa cosa: il file è stato rinominato proxy.ts, la funzione e il matcher non cambiano.
