Working with Cookies

CommandPurpose
npm i cookie-parserReads cookies into req.cookies
npm i cookieLower-level serialize/parse only

Example: With secret for signing

import cookieParser from "cookie-parser";
app.use(cookieParser(env.COOKIE_SECRET));   // string or array of strings (rotation)

3. Reading Cookies

PropertyDetail
req.cookiesPlain unsigned cookies
req.signedCookiesSigned cookies (verified)

Example: Read both

const lang = req.cookies.lang || "en";
const userId = req.signedCookies.userId;  // false if signature invalid

4. Setting Cookies

res.cookie("session", token, {
  httpOnly: true,
  secure: true,
  sameSite: "lax",
  maxAge: 1000 * 60 * 60 * 24 * 7,  // 7 days
  path: "/",
  domain: ".example.com"
});

5. Deleting Cookies

MethodNotes
res.clearCookie(name, opts)Sends Set-Cookie with past expiry
Same opts requiredpath and domain MUST match the original

Example: Logout

res.clearCookie("session", { path: "/", domain: ".example.com" });
OptionPurpose
maxAgeLifetime in ms (preferred)
expiresDate object
httpOnlyNot accessible via JS (XSS protection)
secureHTTPS only
sameSite"strict", "lax", "none"
signedSign with cookieParser secret
pathURL prefix where sent (default /)
domainSend to subdomains
priority"low", "medium", "high"
partitionedCHIPS — third-party cookie isolation NEW

7. Using Signed Cookies

res.cookie("userId", String(user.id), {
  signed: true,
  httpOnly: true,
  sameSite: "lax",
  secure: true
});
Note: Signing prevents tampering, NOT eavesdropping. Always pair with httpOnly + secure for sensitive cookies.

8. Reading Signed Cookies

ResultMeaning
String valueSignature valid
falseSignature invalid (tampered)
undefinedCookie not set
const userId = req.signedCookies.userId;
if (userId === false) return res.status(401).json({ error: "Tampered cookie" });
ScenarioSetting
Subdomain sharingdomain: ".example.com"
Single domainOmit domain
Admin section onlypath: "/admin"

10. Using SameSite Attribute

ValueSent on cross-siteCSRF protection
strictNeverStrongest
lax (browser default)Top-level GET nav onlyStrong
noneAlways (requires secure)None — needs CSRF tokens
Warning: SameSite=None requires Secure. Most browsers default to Lax when unspecified.