HTTP en profondeur - 07 - Les cookies

Tout sur les cookies HTTP : Set-Cookie, attributs de sécurité, SameSite, third-party cookies et limites.

07 - Les cookies

Ce que tu vas apprendre

  • La mecanique exacte de Set-Cookie et Cookie
  • Chaque attribut de cookie et son rôle (Secure, HttpOnly, SameSite, Domain, Path, Max-Age, Expires)
  • La différence entre session cookies et persistent cookies
  • Pourquoi les third-party cookies disparaissent
  • Les limites techniques des cookies (taille, nombre)
  • Comment lire et écrire des cookies en JavaScript

Prerequisites

Avoir lu 06 - Les headers HTTP pour comprendre le fonctionnement général des headers.


Les cookies ont ete inventes en 1994 par Lou Montulli chez Netscape pour résoudre un problème fondamental : HTTP est sans état. Chaque requête est independante. Le serveur ne sait pas que la requête 2 vient du meme client que la requête 1. Montulli a emprunte le concept de "magic cookie" d'Unix et l'a colle dans le navigateur.

Trente ans plus tard, les cookies sont partout. Sessions, préférences, analytics, publicite. Et aussi : failles de sécurité, problèmes de vie privee, casse-tête RGPD. Comprendre comment ils fonctionnent, vraiment, c'est la base pour les utiliser correctement.

Le mecanisme de base

Deux headers font tout le travail :

Le serveur créé un cookie avec Set-Cookie dans la réponse :

HTTP/1.1 200 OK
Set-Cookie: session=abc123
Set-Cookie: theme=dark

Le navigateur renvoie les cookies avec Cookie dans les requêtes suivantes :

GET /api/profile HTTP/1.1
Host: example.com
Cookie: session=abc123; theme=dark

C'est tout. Le serveur pose un cookie, le navigateur le renvoit automatiquement a chaque requête vers le meme domaine. Pas besoin de code JavaScript, pas besoin d'intervention de l'utilisateur.

Chaque Set-Cookie ne concerne qu'un seul cookie. Pour en poser trois, il faut trois headers Set-Cookie. En revanche, le header Cookie envoie tous les cookies d'un coup, separes par ; .

Set-Cookie: name=value; Domain=example.com; Path=/; Expires=Thu, 01 Jan 2027 00:00:00 GMT; Max-Age=31536000; Secure; HttpOnly; SameSite=Lax

Decoupons chaque morceau.

name=value

Le nom et la valeur du cookie. Pas d'espaces dans le nom, pas de caractères speciaux non encodes dans la valeur. En pratique, encode la valeur en base64 ou en percent-encoding si elle contient des caractères bizarres.

Set-Cookie: session=eyJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjo0Mn0.abc

Domain

Set-Cookie: token=xyz; Domain=example.com

Le domaine pour lequel le cookie est valide. Si tu mets Domain=example.com, le cookie est envoye pour example.com et tous ses sous-domaines (api.example.com, www.example.com).

Si tu omets Domain, le cookie n'est valide que pour le domaine exact qui l'a pose. Pas les sous-domaines. C'est souvent plus restrictif et donc plus sécurisé.

Path

Set-Cookie: admin_token=xyz; Path=/admin

Le path pour lequel le cookie est valide. Path=/admin signifie que le cookie est envoye pour /admin, /admin/users, /admin/settings, mais pas pour /api ou /.

En pratique, Path=/ est le plus courant. Les restrictions par path ne sont pas un mecanisme de sécurité fiable -- du JavaScript sur /public peut lire les cookies de /admin si HttpOnly n'est pas active.

Expires et Max-Age

Set-Cookie: prefs=dark; Expires=Thu, 01 Jan 2027 00:00:00 GMT
Set-Cookie: prefs=dark; Max-Age=31536000

Expires donne une date absolue d'expiration. Max-Age donne une duree en secondes. Si les deux sont presents, Max-Age prend la priorité.

Si aucun des deux n'est present, c'est un session cookie : il est supprime quand le navigateur se ferme. En theorie. En pratique, les navigateurs modernes avec la restauration de session gardent souvent les session cookies meme apres la fermeture. Ne compte pas sur la fermeture du navigateur pour invalider une session.

Un cookie avec Expires ou Max-Age est un persistent cookie : il survit a la fermeture du navigateur.

Pour supprimer un cookie, mets Max-Age=0 ou une date Expires dans le passe :

Set-Cookie: session=; Max-Age=0

Secure

Set-Cookie: session=abc; Secure

Le cookie n'est envoye que sur des connexions HTTPS. Sans Secure, un attaquant sur le meme réseau WiFi peut intercepter le cookie en HTTP. Mets Secure sur tous tes cookies sensibles. En fait, mets-le sur tous tes cookies.

HttpOnly

Set-Cookie: session=abc; HttpOnly

Le cookie n'est pas accessible via JavaScript (document.cookie). Protection contre les attaques XSS : meme si un attaquant injecte du JavaScript dans ta page, il ne peut pas lire le cookie de session.

Mets HttpOnly sur tous les cookies de session. C'est la regle numero un de la sécurité des cookies.

SameSite

Set-Cookie: session=abc; SameSite=Strict
Set-Cookie: session=abc; SameSite=Lax
Set-Cookie: tracking=xyz; SameSite=None; Secure

SameSite contrôle quand le cookie est envoye dans les requêtes cross-site :

Strict : le cookie n'est jamais envoye dans les requêtes cross-site. Si tu es sur evil.com et que tu cliques sur un lien vers example.com, le cookie de example.com n'est pas envoye. Tres sécurisé mais peut casser la navigation (tu arrives deconnecte apres avoir clique sur un lien externe).

Lax : le cookie est envoye pour la navigation top-level (liens, redirections) mais pas pour les sous-requêtes cross-site (images, iframes, fetch). C'est le défaut dans les navigateurs modernes et le meilleur compromis pour la plupart des cas.

None : le cookie est envoye partout, y compris en cross-site. Obligatoirement accompagne de Secure. C'est le mode nécessaire pour les iframes embarquees, les widgets tiers, et le tracking cross-site.

Le combo recommande pour un cookie de session :

Set-Cookie: session=abc123; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=86400

Third-party cookies et vie privee

Un cookie first-party est pose par le site que tu visites. Un cookie third-party est pose par un domaine différent (une image, un script, une iframe d'un autre site).

# Tu visites example.com
# La page charge une image de tracker.ad-network.com
# tracker.ad-network.com pose un cookie :
Set-Cookie: user_id=12345; Domain=ad-network.com; SameSite=None; Secure

Ce cookie est envoye a ad-network.com sur chaque site qui charge une ressource de ce domaine. Le réseau publicitaire peut ainsi te suivre de site en site.

Les navigateurs bloquent progressivement les third-party cookies. Safari les bloque depuis 2020 (ITP). Firefox les bloque en mode strict. Chrome les bloque depuis 2025 avec la Privacy Sandbox. Le tracking par cookies tiers est en voie de disparition.

Lire et écrire des cookies en JavaScript

Pour les cookies qui ne sont pas HttpOnly, JavaScript peut les lire et les écrire via document.cookie :

javascript// Lire tous les cookies (format bizarre, chaine unique)
console.log(document.cookie);
// "theme=dark; lang=fr"

// Ecrire un cookie
document.cookie = "theme=light; Path=/; Max-Age=31536000";

// Supprimer un cookie
document.cookie = "theme=; Max-Age=0";

L'API document.cookie est archaique. Chaque affectation ajoute ou modifie un cookie (pas d'ecrasement de la liste complète). La lecture retourne une chaîne plate sans les attributs. C'est moche mais ca marche.

Pour quelque chose de plus propre, il y a la Cookie Store API (encore experimentale) :

javascript// Cookie Store API (Chrome uniquement pour l'instant)
const cookie = await cookieStore.get("session");
console.log(cookie.value);

await cookieStore.set({
  name: "theme",
  value: "dark",
  expires: Date.now() + 365 * 24 * 60 * 60 * 1000
});

Les limites techniques

Les specs imposent des minimums que les navigateurs doivent supporter :

  • Au moins 50 cookies par domaine
  • Au moins 4096 octets par cookie (nom + valeur + attributs)
  • Au moins 3000 cookies au total dans le navigateur

En pratique, les navigateurs sont plus genereux. Mais ne stocke pas 3 KB de JSON dans un cookie. C'est envoye a chaque requête, y compris les requêtes d'images et de CSS. Un cookie de 4 KB sur un site avec 50 ressources par page, c'est 200 KB de trafic supplementaire. Utilise localStorage ou sessionStorage pour les donnees volumineuses.

Les erreurs classiques

Cookie de session sans HttpOnly : une faille XSS permet de voler toutes les sessions.

Cookie sans Secure sur un site HTTPS : le cookie peut fuiter sur des requêtes HTTP accidentelles (redirection, mixed content).

SameSite=None sans Secure : les navigateurs rejettent ce combo. Si tu as besoin de SameSite=None, Secure est obligatoire.

Stocker des donnees sensibles dans le cookie : le cookie est stocke en clair sur le disque du client. Mets un identifiant de session dans le cookie, et les donnees sur le serveur.

Oublier de supprimer le cookie a la deconnexion : appeler Set-Cookie: session=; Max-Age=0 dans la réponse du endpoint de logout.

Sur paltemps.fr, on suit une checklist simple : chaque cookie de session a HttpOnly, Secure, SameSite=Lax, et une duree de vie explicite. Pas d'exception.

Résumé

  • Set-Cookie pose un cookie, Cookie le renvoie automatiquement
  • HttpOnly protégé contre le vol par XSS -- a mettre sur tous les cookies de session
  • Secure limite l'envoi aux connexions HTTPS
  • SameSite=Lax est le meilleur défaut pour la plupart des cas
  • Les session cookies disparaissent a la fermeture du navigateur (en theorie)
  • Les third-party cookies sont en voie de disparition
  • Limite de 4 KB par cookie, et tout est envoye a chaque requête
  • document.cookie est archaique mais fonctionnel

Precedent : 06 - Les headers HTTP Suivant : 08 - Le caching HTTP

Sources

Réservez un audit gratuit de 30 minutes. Je vous montre concrètement ce qu'on peut automatiser.