Skip to Content
TecnicaAutenticazione🔥 FIX CRITICO: Login in Produzione

🔥 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/me non riceve il cookie auth-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:

  1. ✅ POST /api/auth/login → cookie impostato
  2. ✅ Login success
  3. router.push("/") → redirect alla homepage
  4. ❌ Il cookie NON viene inviato perché il browser considera il redirect come una “navigazione”
  5. ❌ 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 produzione

2. 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 successfully

3. 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: LaxIMPORTANTE!
  • ✅ Path: /
  • ✅ Max-Age: 604800 (7 giorni)

4. Test del Flusso Completo

  1. Apri DevTools > Network tab
  2. Vai alla pagina di login
  3. Inserisci credenziali e fai login
  4. Controlla:
    • ✅ POST /api/auth/login → Status 200, Set-Cookie header presente
    • ✅ GET /api/auth/me → Status 200, Cookie: auth-token=... header presente
    • ✅ Redirect a / (dashboard)

Perché Funzionava in Locale?

In sviluppo (localhost), probabilmente:

  • Non avevi NODE_ENV=production impostato
  • 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