1. What Is a Cookie?
A cookie is a small piece of text data that a web server asks the browser to store and then send back with future requests to the same server. Cookies let sites “remember” you:
- Session state (e.g. you’re logged in)
- User preferences (language, theme)
- Shopping carts
- Analytics/tracking
Cookies live entirely on the client; the server only sees what the browser sends.
2. The Cookie “Handshake”
- Server → Client
- In an HTTP response, the server includes one or more
Set-Cookie
headers:HTTP/1.1 200 OK Set-Cookie: sessionId=38afes7a8; Path=/; Secure; HttpOnly; SameSite=Strict
- In an HTTP response, the server includes one or more
- Client Stores Cookie
- Browser checks attributes (domain, path, Secure, etc.) and, if valid, stores it.
- Client → Server
- On subsequent requests matching domain/path and protocol, the browser adds a
Cookie
header:GET /dashboard HTTP/1.1 Host: example.com Cookie: sessionId=38afes7a8
- On subsequent requests matching domain/path and protocol, the browser adds a
3. Key Cookie Attributes
Attribute | Purpose |
---|---|
Name=Value | The data payload |
Domain | Which host(s) should receive the cookie |
Path | URL path prefix for which the cookie applies |
Expires / Max-Age | When the cookie should be deleted (persistent vs session) |
Secure | Only send over HTTPS |
HttpOnly | Inaccessible to JavaScript (mitigates XSS risks) |
SameSite | Controls cross-site sending (Strict, Lax, None) |
- If Expires/Max-Age is omitted → session cookie (deleted when browser closes).
- If present → persistent cookie, survives restarts until the date.
4. Types of Cookies
- Session Cookies
- Stored in memory; cleared on browser close.
- Common for authentication sessions.
- Persistent Cookies
- Stored on disk until expiry.
- Used for “remember me,” preferences, or long-term identifiers.
- First-Party vs. Third-Party
- First-party: Set by the site you’re visiting.
- Third-party: Set by external domains (e.g., ad networks); often blocked by browsers for privacy.
5. Security & Privacy Considerations
- Session Hijacking: If an attacker steals a valid session cookie, they can impersonate the user.
- Mitigation: use Secure, HttpOnly, regenerate session IDs on login, implement short lifetimes.
- Cross-Site Request Forgery (CSRF): Cookies automatically accompany cross-site POSTs/GETs.
- Mitigation: use SameSite=Lax or SameSite=Strict, implement CSRF tokens.
- XSS: Malicious scripts can read non-HttpOnly cookies.
- Mitigation: mark sensitive cookies HttpOnly, sanitize user input.
- GDPR & CCPA: Regulations require user consent for tracking cookies.
- Mitigation: provide clear consent banners, allow users to opt-out.
6. Typescript cookie.utils.ts
Here a pratical example to integrate cookie in a node.js that uses the Fastify library
export type FastifyReplyWrap = {
status: Function;
header: Function;
send: Function;
setCookie: Function;
clearCookie: Function;
};
export type CookieSetOptions = {
name: string;
value: string;
path: string;
domain: string;
maxAge?: number;
httpOnly?: boolean;
secure?: boolean;
sameSite?: "strict" | "lax" | "none";
};
export type CookieClearOptions = {
name: string;
path: string;
domain: string;
httpOnly?: boolean;
secure?: boolean;
sameSite?: "strict" | "lax" | "none";
};
export default class CookieUtils {
public static setCookie(
reply: FastifyReplyWrap,
options: CookieSetOptions
): FastifyReplyWrap {
return reply.setCookie(options.name, options.value, {
httpOnly: options.httpOnly ?? true,
secure: options.secure ?? true,
path: options.path,
sameSite: options.sameSite ?? "strict",
domain: options.domain,
maxAge: options.maxAge
});
}
public static clearCookie(
reply: FastifyReplyWrap,
options: CookieClearOptions
): FastifyReplyWrap {
return reply.clearCookie(options.name, {
httpOnly: options.httpOnly ?? true,
secure: options.secure ?? true,
path: options.path,
sameSite: options.sameSite ?? "strict",
domain: options.domain
});
}
/**
* From set-cookie string return a structured Map
* @param cookies
* @returns
*/
public static parseSetCookie(
cookies: string
): Map<string, Map<CookieProperty, string>> {
const cookieMap = new Map<string, Map<CookieProperty, string>>();
cookies.split(", ").forEach((cookie) => {
const [keyValue, ...attributes] = cookie.split("; ");
const [key, value] = keyValue.split("=");
const attrMap = new Map<CookieProperty, string>();
attributes.forEach((attr) => {
const [attrKey, attrValue] = attr.split("=");
attrMap.set(attrKey as CookieProperty, attrValue || "");
});
cookieMap.set(key, new Map([["value", value], ...attrMap]));
});
return cookieMap;
}
}
type CookieProperty =
| "value"
| "Domain"
| "Path"
| "HttpOnly"
| "Secure"
| "SameSite";
7. Best Practices
- Minimize Sensitive Data: Store only non-sensitive identifiers; keep data server-side.
- Use Secure & HttpOnly: Always flag cookies containing session tokens.
- Leverage SameSite: Default to
Lax
orStrict
to prevent CSRF. - Limit Scope: Set narrow Domain/Path to reduce exposure.
- Regular Rotation: Regenerate and expire session cookies periodically.
Further Reading
- RFC 6265: HTTP State Management Mechanism
- OWASP’s guide on Session Management