Cause più comuni per req.cookies === undefined in Express:
cookie-parser prima delle route che leggono i cookie.import express from 'express'; import cookieParser from 'cookie-parser'; const app = express(); app.use(cookieParser()); // ⬅️ prima di qualunque router // ...le tue route
req.cookies non viene popolato.Secure su HTTP (sviluppo).secure: true il browser non invia il cookie su richieste non-HTTPS. In locale, se usi http://localhost o http://127.0.0.1, il cookie viene ignorato. In dev usa:res.cookie(COOKIE_CODE_VERIFIER, codeVerifierCookieString, {
httpOnly: true,
sameSite: 'lax', // None è necessario solo per contesti cross-site
secure: process.env.NODE_ENV === 'production',
path: '/', // vedi punto 3
});
path, il default è la cartella della URL che ha impostato il cookie (es. da /auth/start → path=/auth). Poi chiamando /api/... il cookie non viene inviato. Imposta sempre path: '/'.localhost ≠ 127.0.0.1 e app.example.com ≠ example.com per i cookie: devono combaciare host (o usa domain adatto).fetch('https://api.example.test/route', {
method: 'POST',
credentials: 'include',
// con axios: { withCredentials: true }
});
import cors from 'cors';
app.use(cors({
origin: 'https://app.example.test', // niente '*'
credentials: true,
}));
SameSite: 'none' è obbligatorio e secure: true. Se non sei realmente cross-site, preferisci lax.undefined/null, o header Set-Cookie scartato perché troppo grande (limite per dominio).Diagnostica rapida:
Set-Cookie arrivi nella risposta corretta (DevTools → Network).Request Headers → Cookie.console.log('Raw Cookie header:', req.headers.cookie);
console.log('Parsed cookies:', req.cookies);
Nota: HttpOnly non influisce lato server; impedisce solo l’accesso via document.cookie.
Curiosità collegata: i browser stanno limitando i cookie di terza parte; se devi davvero operare in contesto cross-site valuta i cookie partizionati (“Partitioned/CHIPS”), che permettono l’uso isolato per origin, evitando i blocchi dei third-party cookie.