Utiliser les cookies HTTP

Un cookie HTTP (également appelé cookie web ou cookie de navigateur) est une donnée de petite taille envoyée par le serveur au navigateur web de l'utilisatrice ou de l'utilisateur. Le navigateur peut alors enregistrer le cookie et le renvoyer au serveur lors des requêtes ultérieures.

Généralement, un cookie HTTP sert à indiquer que deux (ou plusieurs) requêtes proviennent du même navigateur où une personne est connectée. Il permet de mémoriser des informations d'état alors que le protocole HTTP est sans état.

Les cookies ont trois usages principaux :

La gestion de session

Connexions aux sites, chariots d'achats, scores de jeux, ou toute autre chose que le serveur devrait mémoriser

La personnalisation

Les préférences et autres éléments de configuration

Le pistage

L'enregistrement et l'analyse du comportement de la personne visitant le site

Les cookies ont été un outil général de stockage côté client. Bien que cela était pertinent lorsque c'était la seule façon de stocker des données côté client, il est désormais recommandé d'utiliser des API modernes dédiées à cet usage. Les cookies sont envoyés avec chaque requête et peuvent alourdir les performances (notamment pour les connexions mobiles). Les API modernes pour le stockage de données client sont :

Note : Pour observer les cookies enregistrés (et les autres types de stockage utilisés par une page web), vous pouvez activer l'inspecteur de stockage dans les outils de développement de Firefox et ouvrir le niveau Cookies dans la hiérarchie de l'onglet Stockage.

Après avoir reçu une requête HTTP, un serveur peut envoyer un ou plusieurs en-têtes Set-Cookie avec la réponse. Le navigateur enregistre alors généralement le ou les cookies et les renvoie via l'en-tête HTTP Cookie (en-US) pour les requêtes envers le même serveur. Il est possible d'indiquer une date d'expiration ou une durée de vie après laquelle le cookie ne devrait plus être envoyé. Il est également possible d'ajouter des restrictions supplémentaires pour le domaine et les chemins pour lesquels le cookie peut être envoyé. Pour plus de détails sur les attributs des en-têtes mentionnés plus tôt, consultez la page de référence pour Set-Cookie.

L'en-tête de réponse Set-Cookie envoie des cookies depuis le serveur jusqu'à l'agent utilisateur. On peut définir un cookie simple de cette façon :

Set-Cookie: <nom-cookie>=<valeur-cookie>

Dans l'exemple qui suit, le serveur indique au client, via les en-têtes, de stocker une paire de cookies :

HTTP/2.0 200 OK
Content-Type: text/html
Set-Cookie: delicieux_cookie=choco
Set-Cookie: savoureux_cookie=menthe

[contenu de la page]

Ensuite, pour chaque requête ultérieure à ce serveur, le navigateur renverra les cookies enregistrés via l'en-tête Cookie (en-US).

GET /page_exemple.html HTTP/2.0
Host: www.example.org
Cookie: delicieux_cookie=choco; savoureux_cookie=menthe

Note : Voici différents guides pour utiliser l'en-tête Set-Cookie avec différentes technologies côté serveur :

La durée de vie d'un cookie peut être définie de deux façons :

  • Les cookies de session sont supprimés à la fin de la session courante. C'est le navigateur qui définit cet instant et certains navigateurs restaurent les sessions au redémarrage. Dans cette configuration, les cookies de session peuvent durer indéfiniment.
  • Les cookies permanents sont supprimés à la date indiquée par l'attribut Expires ou après une période indiquée par l'attribut Max-Age.

Par exemple :

Set-Cookie: id=a3fWa; Expires=Thu, 31 Oct 2021 07:28:00 GMT;

Note : Lorsqu'une date et une heure sont indiquées dans l'attribut Expires, elles sont relatives au client qui enregistre le cookie et pas au serveur.

Si votre site permet d'authentifier des utilisatrices ou utilisateurs, il devrait régénérer et renvoyer les cookies de session à chaque fois que la personne s'authentifie, y compris pour ceux qui existent déjà. Cette approche permet d'éviter les attaques par fixation de session (en-US), où une tierce partie peut réutiliser des cookies de session.

Restreindre l'accès aux cookies

Il est possible de s'assurer que les cookies sont envoyés de façon sécurisée et ne sont pas manipulés par des acteurs indésirables à l'aide de deux attributs :

  • Secure
  • HttpOnly

Un cookie avec l'attribut Secure sera uniquement envoyé au serveur si la requête est chiffrée (avec le protocole HTTPS). Il ne sera jamais envoyé sur une adresse HTTP non sécurisée (exception faite de localhost). Cela signifie qu'une attaque d'interception ne permettra pas de lire l'information. Les sites qui utilisent un protocole non sécurisé, comme ceux avec http: dans l'URL, ne peuvent pas définir de cookies avec l'attribut Secure. Toutefois, l'attribut Secure ne garantit pas une protection absolue des données sensibles des cookies. Ainsi, quelqu'un qui a accès au disque dur du client (ou au code JavaScript du site si l'attribut HttpOnly n'est pas ajouté) pourra toujours lire et modifier l'information.

Lorsque l'attribut HttpOnly est indiqué, le cookie est inaccessible en JavaScript et ne peut pas être manipulé avec l'API Document.cookie (en-US), il est uniquement envoyé au serveur. Ainsi, les cookies qui persistent côté serveur pour les sessions n'ont pas besoin d'être disponibles en JavaScript et devraient être paramétrés avec l'attribut HttpOnly. Cette précaution permet de réduire les risque d'attaque XSS (en-US).

Voici un exemple :

Set-Cookie: id=a3fWa; Expires=Thu, 21 Oct 2021 07:28:00 GMT; Secure; HttpOnly

Définir où les cookies sont envoyés

Les attributs Domain et Path définissent la portée d'un cookie, c'est-à-dire les URL vers lesquelles le cookie pourra être envoyé.

Attribut Domain

L'attribut Domain indique les hôtes qui peuvent recevoir un cookie. Si cet attribut est absent, la valeur par défaut sera l'hôte qui a défini le cookie en excluant les sous-domaines. Si Domain est indiqué, les sous-domaines sont toujours inclus. Aussi, indiquer Domain est moins restrictif que de l'omettre. Toutefois, cet attribut peut s'avérer utile lorsque les sous-domaines doivent partager de l'information à propos d'une personne.

Ainsi, si on définit Domain=mozilla.org, les cookies seront disponibles sur les sous-domaines comme developer.mozilla.org.

Attribut Path

L'attribut Path indique un chemin d'URL qui doit exister dans l'URL demandée pour que l'en-tête Cookie soit envoyé. Le caractère %x2F ("/") est considéré comme un séparateur de répertoire et les sous-répertoires correspondront alors.

Ainsi, si on indique Path=/docs, les requêtes vers les chemins suivants contiendront les cookies :

  • /docs
  • /docs/
  • /docs/Web/
  • /docs/Web/HTTP

En revanche, pour ces chemins, les cookies ne seront pas ajoutés :

  • /
  • /docsets
  • /fr/docs

Attribut SameSite

L'attribut SameSite permet aux serveurs d'indiquer quand les cookies doivent être envoyés lors de requêtes vers d'autres origines/sites. Cela fournit une certaine protection contre les attaques cross-site request forgery.

Cet attribut peut prendre trois valeurs différentes :

Strict

Le navigateur envoie uniquement le cookie pour les requêtes vers le même site d'origine du cookie

Lax

Similaire à Strict, mais le navigateur envoie également le cookie lorsque la personne navigue vers le site d'origine du cookie (même si elle vient d'un site différent), par exemple lorsqu'elle suit un lien depuis un site externe.

None.

Les cookies sont envoyés pour les requêtes du même site et pour les autres sites, mais uniquement dans des contextes sécurisés (autrement dit, si on a SameSite=None, l'attribut Secure doit également être présent).

Si aucun attribut SameSite n'est indiqué, la valeur par défaut est Lax.

Voici un exemple :

Set-Cookie: macle=mavaleur; SameSite=Strict

Note : La spécification concernant SameSite a changé (MDN documente le comportement actuel). Voir le tableau de compatibilité pour SameSite pour plus d'informations dont l'attribut est géré selon les versions des navigateurs :

  • SameSite=Lax est désormais la valeur par défaut si SameSite n'est pas indiqué. Auparavant, les cookies étaient par défaut envoyés pour toutes les requêtes.
  • Les cookies avec SameSite=None doivent désormais utiliser l'attribut Secure (autrement dit, le contexte doit être sécurisé).
  • Les cookies provenant d'un même domaine ne sont plus considérés comme provenant du même site si le schéma utilisé est différent (http: est considéré comme différent de https:).

Étant donné la conception du mécanisme des cookies, un serveur ne peut pas confirmer qu'un cookie a été défini depuis une origine sécurisée ou même l'emplacement depuis lequel un cookie a été défini à l'origine.

Une application vulnérable sur un sous-domaine pourrait donc définir un cookie avec l'attribut Domain, ce qui donnerait accès à ce cookie sur l'ensemble des sous-domaines. Ce mécanisme pourrait être abusé lors d'une attaque par fixation de session. Voir la description de ce type d'attaque (en-US) pour plus d'informations sur les méthodes de prévention.

Comme mesure de défense en profondeur, on peut utiliser des préfixes de cookie pour confirmer différents aspects du cookie. Deux préfixes sont disponibles :

__Host-

Si un nom de cookie utilise ce préfixe, il sera uniquement accepté dans un en-tête Set-Cookie si :

  • Il est marqué avec l'attribut Secure
  • Il a été envoyé depuis une origine sécurisée
  • Il n'inclut pas d'attribut Domain
  • L'attribut Path vaut /.

Ainsi, de tels cookies peuvent être vus comme verrouillés au domaine.

__Secure-

Si un nom de cookie utilise ce préfixe, il sera uniquement accepté dans un en-tête Set-Cookie s'il est marqué avec l'attribut Secure et qu'il a été envoyé depuis une origine sécurisée. Il s'agit d'une forme plus faible que celle fournie par le préfixe __Host-.

Le navigateur rejettera les cookies avec ces préfixes et qui ne respectent pas ces contraintes. On notera qu'ainsi, les cookies créés par les sous-domaines et avec ces préfixes sont confinés au sous-domaine en question ou ignorés complètement. Comme le serveur d'application vérifie uniquement le nom d'un cookie donné pour l'authentification ou la validité d'un jeton CSRF, cela sert de mesure contre les fixations de session.

Attention : Sur le serveur d'application, l'application web doit vérifier le nom complet du cookie, incluant le préfixe. Les agents utilisateurs ne suppriment pas le préfixe avant de l'envoyer dans l'en-tête Cookie (en-US) de la réponse.

Pour plus d'informations sur les préfixes et la compatibilité des navigateurs associée, voir la section sur les préfixes de la page sur l'article de référence Set-Cookie.

Accéder aux cookies en JavaScript avec Document.cookie

On peut créer de nouveaux cookies en JavaScript à l'aide de la propriété Document.cookie (en-US). Il est aussi possible d'accéder aux cookies existants depuis le code JavaScript si l'attribut HttpOnly n'a pas été ajouté.

document.cookie = "delicieux_cookie=choco";
document.cookie = "savoureux_cookie=menthe";
console.log(document.cookie);
// affiche ce qui suit dans la console "delicieux_cookie=choco; savoureux_cookie=menthe"

Les cookies créés en JavaScript ne peuvent pas inclure l'attribut HttpOnly.

Voir la section qui suit sur la sécurité : les cookies disponibles en JavaScript peuvent être volés via des attaques XSS.

Sécurité

Note : Quand des informations sont enregistrées dans des cookies, elles sont visibles et éditables par l'utilisatrice ou l'utilisateur final·e. Selon le cas d'usage de l'application, vous pouvez utiliser un identifiant opaque qui sera utilisé par le serveur ou utiliser d'autres mécanismes d'authentification ou de confidentialité comme les JSON Web Tokens.

Plusieurs mécanismes existent pour prévenir les attaques utilisant les cookies :

  • L'attribut HttpOnly qui permet d'éviter l'accès aux cookies en JavaScript.
  • Les cookies utilisés pour des informations sensibles (par exemple pour indiquer un état authentifié) devraient avoir :
    • Une durée de vie courte
    • L'attribut SameSite fixé à Strict ou Lax (voir l'attribut SameSite ci-avant). Pour les navigateurs qui prennent en charge SameSite, cela permet de s'assurer que le cookie d'authentification n'est pas envoyé pour les requêtes entre plusieurs sites/origines. La requête malveillante serait alors vue comme non-authentifiée depuis le serveur d'application.

Pistage et vie privée

Cookies tiers

Un cookie est associé à un domaine et à un schéma donné (par exemple http ou https). Il peut être associé à des sous-domaines si l'attribut Set-Cookie Domain est fourni. Si le domaine et le schéma du cookie correspondent à la page courante, le cookie est considéré comme provenant du même site que la page et donc comme un cookie en propre.

Si le domaine et schéma sont différents, le cookie n'est pas considéré comme provenant du même site et est alors qualifié de cookie tiers. Bien que le serveur hébergeant la page définit des cookies en propre, la page peut contenir des images ou d'autres ressources situées sur d'autres domaines (par exemple des publicités) qui peuvent définir des cookies tiers. Ces cookies sont principalement utilisés pour les publicités et le pistage sur le Web (voir les types de cookies utilisés par Google).

Un serveur tiers peut créer un profil d'une personne à partir des habitudes et parcours de navigation grâce aux cookies qui lui sont envoyés par le navigateur lors de l'accès à différents sites. Par défaut, Firefox et Safari bloquent les cookies tiers connus pour le pistage. Ces cookies peuvent aussi être bloqués en utilisant les paramètres des autres navigateurs ou des extensions. Le blocage des cookies peut parfois empêcher le bon fonctionnement de composants tiers (comme les intégrations de réseaux sociaux).

Note : Les serveurs peuvent (et devraient) définir l'attribut SameSite pour indiquer si un cookie peut être envoyé ou non à un site tierce.

Régulations relatives aux cookies

Les régulations ou législations qui s'appliquent aux cookies incluent:

  • Le règlement général sur la protection des données (RGPD ou GDPR en anglais) de l'Union européenne
  • La directive ePrivacy de l'Union européenne
  • Le California Consumer Privacy Act pour l'état de Californie aux États-Unis (s'applique aux entités ayant un revenu brut supérieur à 25 millions de dollars entre autres choses)

Ces textes ont une portée mondiale et s'appliquent à tout site web auquel peut accéder une personne de ces juridictions (ici l'Union européenne et la Californie). Ils décrivent des règles sur :

  • La notification des personnes utilisant le site en cas d'utilisation des cookies.
  • La capacité des personnes à pouvoir refuser tout ou partie des cookies.
  • La capacité des personnes à utiliser les fonctionnalités principales sans recevoir de cookies.

D'autres législations peuvent exister et c'est à l'équipe qui conçoit et développe le site/l'application de les connaître et de s'y conformer. Certaines entreprises fournissent des services relatifs aux bannières de cookies qui peuvent aider à se conformer à ces lois.

Autres méthodes pour stocker des informations dans le navigateur

Si on veut stocker des données dans le navigateur, une autre approche consiste à utiliser l'API Web Storage API. Les propriétés window.sessionStorage et window.localStorage peuvent être vues comme des analogues respectifs aux cookies de session et aux cookies permanents, mais permettent de stocker plus de données que les cookies et ne sont jamais envoyées implicitement au serveur. Pour des données plus structurées et plus volumineuses, on pourra utiliser l'API IndexedDB, ou une bibliothèque tierce qui facilite son utilisation.

Certaines techniques peuvent être utilisées pour recréer des cookies après leur suppression. On parle alors de cookies zombies. Ces techniques ne respectent pas les règles relatives à la vie privée et être contraires aux lois sur ces questions, exposant un site web qui les utiliserait à des poursuites.

Voir aussi