Authentification et sécurité web - 02 - JWT : comment ca marche et quand l'utiliser

Les JSON Web Tokens expliques : structure, signature, quand les utiliser et surtout quand NE PAS les utiliser.

02 - JWT : comment ca marche et quand l'utiliser

Ce que tu vas apprendre

  • La structure d'un JWT (header, payload, signature)
  • Comment la vérification fonctionne sans base de donnees
  • Quand utiliser un JWT et quand ne surtout pas le faire

Prerequisites

Avoir lu l'article sur les sessions et cookies. Comprendre la différence entre chiffrement symetrique et asymetrique est un plus (voir la serie clés et chiffrement).


Un JWT, c'est trois morceaux

Un JSON Web Token (prononce "djotte" en anglais, moi je dis "JWT" lettre par lettre et je ne vais pas changer) est une chaîne de caractères avec trois parties separees par des points :

eyJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOjQyLCJyb2xlIjoiYWRtaW4iLCJpYXQiOjE3MTE1OTQ4MDAsImV4cCI6MTcxMTU5ODQwMH0.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

Ca a l'air illisible, mais c'est juste du base64. Si tu le decodes :

Header (première partie) :

json{ "alg": "HS256" }

L'algorithme de signature. HS256 = HMAC-SHA256 (symetrique, un seul secret). RS256 = RSA-SHA256 (asymetrique, clé privee pour signer, clé publique pour vérifier).

Payload (deuxieme partie) :

json{
  "userId": 42,
  "role": "admin",
  "iat": 1711594800,
  "exp": 1711598400
}

Les donnees. iat = issued at, exp = expiration. Tu peux mettre ce que tu veux. Attention : le payload est encode en base64, pas chiffre. N'importe qui peut le lire. Ne mets jamais de mot de passe ou de donnees sensibles dans un JWT.

Signature (troisieme partie) :

HMAC-SHA256(base64(header) + "." + base64(payload), secret)

Le serveur calcule cette signature avec un secret que lui seul connaît. Si quelqu'un modifie le payload (par exemple pour changer role en admin), la signature ne correspondra plus et le token sera rejete.

En TypeScript

typescriptimport { sign, verify } from "jsonwebtoken";

const SECRET = process.env.JWT_SECRET;

// Creer un token
const token = sign(
  { userId: 42, role: "editor" },
  SECRET,
  { expiresIn: "1h" }
);

// Verifier un token (throws si invalide ou expire)
try {
  const payload = verify(token, SECRET);
  console.log(payload.userId); // 42
} catch (err) {
  // Token invalide, expire, ou signature incorrecte
  return new Response("Unauthorized", { status: 401 });
}

La vérification ne fait aucun appel réseau, aucune requête en base. Le serveur recalcule la signature et compare. C'est pour ca qu'on dit que les JWT sont "stateless" : le serveur n'a besoin de rien stocker.

Quand les JWT font sens

Les JWT brillent dans des cas precis.

Microservices. L'API Gateway authentifié l'utilisateur et généré un JWT. Les services en aval recoivent le JWT et le verifient avec la clé publique, sans rappeler l'API Gateway. Chaque service sait qui est l'utilisateur sans partager une base de sessions.

Applications mobiles. Pas de cookies natifs sur iOS/Android. Le JWT est stocke dans le secure storage du telephone et envoye dans le header Authorization: Bearer <token>.

APIs tierces. Tu fournis une API a des clients externes. Le JWT leur permet de s'authentifier sans que tu geres des sessions pour eux.

Quand les JWT sont le mauvais choix

Et la, je vais etre direct : pour une application web classique (un frontend et un backend sur le meme domaine), les JWT sont un mauvais choix. Je vois trop de devs les utiliser parce que c'est "moderne" ou parce qu'un tuto Medium de 2019 leur a dit de le faire.

Tu ne peux pas revoquer un JWT. Si un utilisateur clique sur "deconnexion", que fais-tu ? Le token est toujours valide jusqu'a son expiration. Tu es oblige de maintenir une blacklist cote serveur, et la tu as reinvente les sessions, mais en plus complique.

Le payload est lisible. Ce n'est pas du chiffrement, c'est du base64. Un atob() dans la console du navigateur et tu vois tout. J'ai deja vu des JWT avec des emails, des numeros de telephone, et une fois meme un hash de mot de passe dans le payload. Ne fais pas ca.

Le stockage cote client est un problème. Si tu mets le JWT dans localStorage, une faille XSS permet de le voler. Si tu le mets dans un cookie HttpOnly... alors utilise des sessions, c'est plus simple. Le OWASP Testing Guide est clair la-dessus.

Les tokens longs en header Authorization passent dans les logs. Les access logs de ton reverse proxy contiennent les headers. Si ton JWT fait 800 octets (et c'est courant), il se retrouve dans des fichiers de log, des outils de monitoring, des screenshots de debug.

Mon avis

Sur paltemps.fr, j'utilise des sessions avec cookies. C'est plus simple, plus sécurisé pour un back-office web, et ca me prend 10 lignes de code. Les JWT, je les reserve aux situations ou je n'ai pas le choix : communication entre services, APIs consommees par des mobiles, ou intégration avec des systèmes tiers.

Si tu debutes et que tu hesites entre les deux, prends les sessions. Tu pourras toujours migrer vers des JWT plus tard si ton architecture l'exige. L'inverse (remplacer des JWT par des sessions) est plus penible.

La RFC 7519 definit le format JWT si tu veux lire la spec. C'est court et lisible, pour une RFC.


Navigation : Precedent : 01 - Sessions et cookies | Suivant : 03 - OAuth2


Sources

Retrouve d'autres articles techniques sur paltemps.fr.

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