🔥 FIX CRITICO: Login in Produzione
⚠️ PROBLEMA IDENTIFICATO E RISOLTO
Il Bug
Sintomi:
- ✅ In locale: login funziona perfettamente
- ❌ In produzione: login API ritorna 200 OK ma non si accede alla dashboard
- ❌ La chiamata
/api/auth/menon riceve il cookieauth-token
La Causa Principale: SameSite=“strict”
Il problema era nella configurazione del cookie:
// ❌ CODICE PROBLEMATICO (PRIMA)
response.cookies.set("auth-token", token, {
httpOnly: true,
secure: true,
sameSite: "strict", // ← QUESTO ERA IL PROBLEMA!
maxAge: 60 * 60 * 24 * 7,
path: "/",
});Perché sameSite: "strict" causava il problema:
Con sameSite: "strict", il browser blocca completamente l’invio del cookie in qualsiasi navigazione cross-site, inclusi i redirect interni.
Quando l’utente fa login:
- ✅ POST
/api/auth/login→ cookie impostato - ✅ Login success
- ❌
router.push("/")→ redirect alla homepage - ❌ Il cookie NON viene inviato perché il browser considera il redirect come una “navigazione”
- ❌ GET
/api/auth/me→ NO COOKIE → 401 Unauthorized
La Soluzione: SameSite=“lax”
// ✅ CODICE CORRETTO (DOPO)
response.cookies.set("auth-token", token, {
httpOnly: true,
secure: isProduction,
sameSite: "lax", // ← RISOLVE IL PROBLEMA!
maxAge: 60 * 60 * 24 * 7,
path: "/",
});Perché sameSite: "lax" risolve il problema:
- ✅ Permette il cookie nelle navigazioni top-level GET (inclusi redirect)
- ✅ Permette il cookie in tutte le richieste same-site
- ✅ Blocca ancora i cookie nelle richieste POST/DELETE cross-site (protezione CSRF)
- ✅ È la policy raccomandata da Google e MDN per cookie di sessione
- ✅ Compatibile con i redirect post-login
Modifiche Implementate
1. File: /src/app/api/auth/login/route.ts
// Imposta cookie httpOnly
const isProduction = process.env.NODE_ENV === "production";
response.cookies.set("auth-token", token, {
httpOnly: true,
secure: isProduction,
sameSite: "lax", // ← CAMBIATO da "strict" a "lax"
maxAge: 60 * 60 * 24 * 7,
path: "/",
});
// Logging dettagliato per debug
console.log("[LOGIN] Cookie set successfully");
console.log("[LOGIN] - isProduction:", isProduction);
console.log("[LOGIN] - secure:", isProduction);
console.log("[LOGIN] - sameSite: lax");2. File: /src/app/api/auth/me/route.ts
Aggiunto logging per debug:
export async function GET(request: NextRequest) {
// Debug: mostra tutti i cookie
const allCookies = request.cookies.getAll();
console.log("[AUTH/ME] All cookies:", allCookies.map(c => c.name).join(", "));
const token = request.cookies.get("auth-token")?.value;
console.log("[AUTH/ME] auth-token present:", !!token);
if (!token) {
console.log("[AUTH/ME] No auth-token found");
console.log("[AUTH/ME] Available cookies:", allCookies.length);
// ...
}
}Test in Produzione
1. Deploy delle modifiche
# Assicurati che NODE_ENV=production sia impostato
git add .
git commit -m "fix: change cookie sameSite to lax for production login"
git push
# Deploy su produzione2. Verifica nei Log del Server
Dopo il deploy, fai login e controlla i log. Dovresti vedere:
[LOGIN] Attempting login for: user@example.com
[LOGIN] Login successful for user: 507f...
[LOGIN] Cookie set successfully
[LOGIN] - isProduction: true
[LOGIN] - secure: true
[LOGIN] - sameSite: lax
[LOGIN] - path: /
[AUTH/ME] All cookies: auth-token, other-cookies...
[AUTH/ME] auth-token present: true
[AUTH/ME] Token decoded successfully for user: 507f...
[AUTH/ME] User data fetched successfully3. Verifica nel Browser DevTools
Application > Cookies > your-domain.com
Il cookie auth-token deve avere:
- ✅ Name:
auth-token - ✅ Value:
eyJhbGciOiJS...(JWT token) - ✅ HttpOnly: ✓
- ✅ Secure: ✓ (in produzione con HTTPS)
- ✅ SameSite:
Lax← IMPORTANTE! - ✅ Path:
/ - ✅ Max-Age: 604800 (7 giorni)
4. Test del Flusso Completo
- Apri DevTools > Network tab
- Vai alla pagina di login
- Inserisci credenziali e fai login
- Controlla:
- ✅ POST
/api/auth/login→ Status 200,Set-Cookieheader presente - ✅ GET
/api/auth/me→ Status 200,Cookie: auth-token=...header presente - ✅ Redirect a
/(dashboard)
- ✅ POST
Perché Funzionava in Locale?
In sviluppo (localhost), probabilmente:
- Non avevi
NODE_ENV=productionimpostato - Quindi usava
sameSite: "lax"invece di"strict" - Ecco perché funzionava!
Riferimenti
TLDR: sameSite: "strict" è troppo restrittivo per un’app con redirect post-login. Usa sameSite: "lax".
Last updated on