Working with Cookies for Authentication

1. Setting Authentication Cookies

HeaderExample
Set-Cookie__Host-sid=abc...; HttpOnly; Secure; SameSite=Lax; Path=/; Max-Age=28800
ReadClient → automatic on same-origin requests
ClearSet-Cookie: sid=; Max-Age=0; Path=/
AttributeEffectRecommended
HttpOnlyJS cannot read via document.cookieAlways for auth
SecureSent over HTTPS onlyAlways
SameSiteLax / Strict / NoneLax (default)
DomainLimits which hosts receive cookieOmit unless needed
PathLimits URL path scope/
Max-Age / ExpiresPersistenceMatch session policy
Partitioned NEWCHIPS — partitioned by top-level siteThird-party contexts

3. Understanding SameSite Attribute

ValueBehaviorUse Case
StrictNever sent cross-site (including top-level nav)Banking, no inbound links
LaxSent on top-level GET nav onlyStandard apps (default in modern browsers)
NoneSent cross-site (requires Secure)Third-party widgets, SSO iframes
ScenarioSetting
Single hostOmit Domain (host-only)
Share across subdomainsDomain=example.com
Limit to APIPath=/api
Strictest__Host- prefix: no Domain, Path=/, Secure
TypeLifespan
Session cookieUntil browser closes (no Max-Age)
PersistentMax-Age in seconds (or Expires UTC)
Server-revocableSet Max-Age=0 on revoke endpoint

6. Using Signed Cookies

import { createHmac, timingSafeEqual } from "crypto";
const sign = (v) => v + "." + createHmac("sha256", SECRET).update(v).digest("base64url");
const verify = (cookie) => {
  const [v, sig] = cookie.split(".");
  const expected = createHmac("sha256", SECRET).update(v).digest();
  const actual = Buffer.from(sig, "base64url");
  return actual.length === expected.length && timingSafeEqual(actual, expected) ? v : null;
};
NeedApproach
ConfidentialityAES-256-GCM (AEAD)
Key rotationKey ID prefix, support multiple keys
Libraryiron-session, cookie-encrypter, NextAuth
Anti-patternECB mode, custom XOR
PrefixEnforced Constraints
__Secure-Must include Secure attribute
__Host-Secure + Path=/ + no Domain attribute
Note: __Host- prefix prevents subdomain attackers from setting cookies that override yours.
Cookie CategoryConsent Required?
Strictly necessary (auth, CSRF)No (legitimate interest)
Functional (UI prefs)Usually yes (GDPR)
AnalyticsYes
Marketing / trackingYes, opt-in
VectorMitigation
XSSHttpOnly, CSP, sanitization
NetworkSecure + HSTS + TLS 1.3
Subdomain takeover__Host- prefix
Physical accessShort expiry + re-auth
Malicious extensionsToken binding (DBSC)

11. Mitigating CSRF with Cookies

TechniqueDetail
SameSite=Lax/StrictPrimary defense (browser-enforced)
CSRF tokenSynchronizer pattern: hidden form field matches cookie/session
Double-submit cookieJS reads CSRF cookie, sends as header; server compares
Custom headerRequire X-Requested-With on JSON APIs (triggers preflight)
Origin/Referer checkServer validates origin matches expected