CodeGym /Cours /Spring Security /JWT dans l' API stateless

JWT dans l' API stateless

Spring Security
Niveau 22, Leçon 0
Disponible

1. JWT en une phrase : ce que c'est et ce que ce n'est pas

Si vous voyez JWT pour la première fois, il ressemble à peu près au mot de passe Wi‑Fi que quelqu'un a recopié du plafond : beaucoup de caractères, des points, une magie incompréhensible. Mais le regard le plus court et le plus honnête sur JWT est celui-ci : JWT est une chaîne compacte qui transporte un petit ensemble de données (claims) entre les requêtes et est protégée par une signature contre une modification invisible. Voilà. Ni plus, ni moins.

Dès que le serveur cesse de stocker la session et de se souvenir de l'utilisateur entre les requêtes, une nouvelle question d'ingénierie apparaît : qu'est-ce que le client va apporter à la place de la mémoire côté serveur pour que, à chaque requête, on puisse reconstruire l'Authentication ? JWT apparaît exactement à cet endroit.

Les problèmes commencent lorsque l'on perçoit JWT comme un « nouveau modèle de sécurité » ou un « remplacement total du serveur ». JWT n'est pas Spring Security et encore moins une « autorisation ». Il ne décide pas à votre place si l'utilisateur peut publier un brouillon. Il ne remplace pas vos règles @PreAuthorize, ne connaît pas la propriété, ne sait pas distinguer « tout seul » un 401 d'un 403. Il aide simplement à transmettre ce que le serveur a besoin de savoir pour prendre ces décisions.

Il est très utile de garder en tête un petit tableau de différences — non pas comme un résumé d'examen, mais comme un antidote aux deux illusions courantes.

Ce que c'est De quoi il s'agit Ce que ça apporte Ce qu'il n'apporte pas
JWT en tant que format Structure du token et ensemble de champs Une « fiche de données » portable et pratique Une sécurité automatique « par le simple fait d'avoir un token »
Signature JWT Intégrité des données Protection contre la modification invisible du payload Confidentialité du payload (il est lisible)
Modèle de sécurité de l'application Règles d'accès et cycle de vie Qui a accès à quoi et comment les erreurs sont traitées Ne peut pas être « remplacé » par une seule chaîne de token

On a envie de plaisanter, mais la plaisanterie est déjà là : combien de fois JWT est désigné comme le « roi de tous les problèmes ». JWT, c'est comme un passeport. Le passeport aide à identifier une personne et porte un certain contexte. Mais le passeport ne garde pas le musée, ne ferme pas les portes, ne décide pas si vous pouvez entrer dans la réserve de tableaux. Le musée décide cela avec des règles, des gardiens et des tourniquets. JWT dans notre application est un « document » comme un autre, pas un « gardien ».

2. API stateless et « transfert de mémoire » entre les requêtes

Dans le monde basé sur les sessions, tout était assez confortable. L'utilisateur se connectait une fois, le serveur plaçait le contexte de sécurité nécessaire dans la session, le client transportait un cookie, et les requêtes suivantes ressemblaient à une « continuation de la conversation ». Le monde stateless ressemble plutôt à une situation de « contrôle des documents à chaque entrée ». Le serveur ne stocke pas « votre fiche » entre les requêtes, donc le client doit apporter la preuve de qui il est à chaque fois.

Et ici, il est facile de confondre deux choses : les credentials et le token. Les credentials sont ce par quoi l'utilisateur prouve son identité lors de la connexion (par exemple, le mot de passe). Le token est ce que le système délivre après une authentification réussie pour que le client puisse ensuite confirmer son identité sans transmettre le mot de passe à chaque requête. C'est comme une salle de sport : vous montrez une pièce d'identité une fois à l'accueil (credentials), on vous donne un bracelet (token), et ensuite vous entrez avec le bracelet, sans agiter votre passeport devant le tourniquet.

JWT joue généralement le rôle de ce token. Il transporte une information « minimalement suffisante » sur l'utilisateur (et parfois sur son contexte d'accès de base) pour que le serveur puisse reconstruire l'Authentication le temps d'une requête spécifique.

Il est important de noter tout de suite : JWT n'apparaît pas parce que nous voulions une technologie à la mode, mais parce que l'architecture stateless exige de transporter le contexte d'authentification entre les requêtes sans session côté serveur. JWT est l'un des formats qui rend cela pratique, car il est compact, textuel, standardisé et s'intègre bien dans HTTP.

Du point de vue de notre projet Secure Content Platform API, cela signifie une chose simple : lorsque le client accédera, par exemple, à /api/me ou à /api/drafts/{id}, le serveur ne pourra plus se « souvenir » de l'utilisateur via la session. Il devra restaurer qui vous êtes en fonction de ce que vous avez apporté dans la requête. JWT est un moyen d'apporter ce contexte.

3. Token signé : intégrité vs confidentialité

L'idée fausse la plus nuisible à propos de JWT est à peu près celle-ci : « Si j'ai un JWT, alors les données à l'intérieur sont cachées ». Non. JWT dans le scénario typique du cours est signé, pas chiffré. Or, la signature et le chiffrement résolvent des problèmes différents.

La signature répond à la question : « Quelqu'un a-t-il pu modifier les données à l'intérieur du token sans qu'on le remarque ? ». C'est une question d'intégrité. Si vous recevez un token, vérifiez la signature et qu'elle est correcte, vous pouvez avoir confiance que le payload n'a pas été modifié après l'émission.

Mais la signature ne répond pas à la question : « Quelqu'un peut-il lire le contenu ? ». Dans un JWT classique, le payload est visible. On peut le décoder. Et c'est normal. JWT a été conçu comme un format pratique à transporter, pas comme un coffre-fort.

Il est donc utile de percevoir JWT comme un conteneur transparent avec un sceau. Le conteneur est transparent — le payload est lisible. Le sceau est présent — la modification est détectable après vérification de la signature. De là découle une règle d'ingénierie simple : il ne faut pas mettre de données sensibles dans JWT, parce que quiconque a le token entre les mains pourra les voir.

Et cela amène une autre réflexion mature : la sécurité de JWT ne repose pas sur la « confidentialité du token », mais sur le fait que le token ne peut pas être contrefait sans qu'on le remarque si la signature est correctement vérifiée. C'est un style de pensée fondamentalement différent de « cachons simplement les données et personne ne devinera ».

4. Base64URL : lisibilité du token

Au début, JWT agace parce qu'il ressemble à une chaîne chaotique. En réalité, les deux premières parties du token sont du simple JSON, simplement emballé en Base64URL pour que la chaîne soit facile à transporter dans HTTP et les URL. Base64URL est un encodage, pas une cape d'invisibilité.

Pour ce point, un seul fait suffit : le payload est lisible. Si on y met email, displayName ou quelque chose d'autre de sensible, cela ne « reste pas quelque part sur le backend », mais part avec le token chez le client et dans toute couche intermédiaire où ce token se trouve.

Cela suffit déjà pour ne pas confondre emballage pratique et protection réelle.

5. JWT comme contrat de données : un minimum de champs

JWT est pratique car il peut transporter des données. JWT est dangereux car il peut en transporter trop. Le débutant tombe souvent dans le piège : « Puisque c'est un token, mettons-y tout ce dont nous pourrions avoir besoin. Comme ça, on n'aura pas à aller en base de données ». Cela semble être une économie, mais cela se transforme souvent en fragilité, fuites et instantanés obsolètes de la réalité.

Pour garder le contrôle, il est utile de considérer JWT comme un contrat de données, et non comme un « sac dans lequel on peut tout mettre ». Un contrat signifie que vous décidez à l'avance : quels champs sont vraiment nécessaires à l'application pour restaurer l'utilisateur courant et le contexte d'accès de base, et lesquels sont simplement pratiques mais nuisibles.

Dans notre projet, le contrat minimal se résume généralement à trois choses :

— qui est l'utilisateur (sub et/ou un userId stable) ;
— quel est son contexte d'accès compact, par exemple les rôles ;
— jusqu'à quand ce token est valide (exp).

Cela suffit pour restaurer l'Authentication et prendre une décision de base sur l'accès. Tout ce qui n'est pas nécessaire immédiatement à chaque requête, il est généralement préférable de le lire sur le serveur.

C'est ainsi qu'il est plus facile de ne pas confondre le token avec le profil utilisateur : JWT doit transporter le minimum sans lequel une requête stateless ne peut être traitée, et non pas toute la biographie, les paramètres et les champs sensibles.

6. JWT dans le modèle de sécurité : flux général

Pour que JWT cesse d'être simplement un format et devienne une pièce compréhensible de l'architecture, il est utile de voir le tableau général d'une requête. Mais ici, il suffit de rester au niveau « qui fait quoi », sans classes ni filtres. Ainsi, le rôle du token lui-même devient visible, et pas seulement la future implémentation.

sequenceDiagram
    participant C as Client
    participant A as "API (Secure Content Platform)"

    C->>A: "(1) Connexion avec credentials (username/password)"
    A-->>C: "(2) Réponse : access token (JWT)"
    C->>A: "(3) Requête vers /api/me avec le token"
    A->>A: "(4) Vérifie la signature et la validité du token"
    A->>A: "(5) Extrait le subject/rôles et prend une décision d'accès"
    A-->>C: "(6) Réponse JSON ou erreur de sécurité (401/403)"

À ce niveau, on voit déjà plusieurs choses qui correspondent bien à nos connaissances précédentes.

Premièrement, le token n'est pas un credentials. Les credentials sont nécessaires au moment 1, le token apparaît après 2. Deuxièmement, JWT aide précisément dans la partie stateless entre les requêtes 3 : le serveur reçoit à chaque fois non pas une session cookie, mais un token. Troisièmement, le payload est toujours lisible, mais on ne peut faire confiance aux données qu'il contient qu'après vérification de la signature et de la validité.

Enfin, JWT n'annule pas vos contraintes métier. Si l'utilisateur a le rôle USER, cela ne se transforme pas en « peut publier ». Si l'utilisateur a userId=42, cela ne signifie pas que le brouillon avec authorId=99 devient « le sien ». Les règles basées sur la propriété restent des règles basées sur la propriété ; simplement, au lieu de « récupérer l'id depuis la session », on « prend l'id depuis le token » (ou depuis l'Authentication reconstruite qui sera construite à partir du token).

Si vous gardez cette image en tête, il sera plus facile d'aborder les détails particuliers par la suite. Et inversement : si vous commencez à apprendre JWT comme un ensemble d'appels magiques à une bibliothèque, vous arriverez rapidement à un état du genre « ça marche, mais je ne sais pas pourquoi ».

7. Erreurs typiques lors des premiers pas avec JWT

JWT n'a presque pas de « mathématiques complexes » au niveau du développeur, mais il y a beaucoup de pièges dans le modèle mental. Et c'est normal : le cerveau aime simplifier. Simplement, en sécurité, les simplifications agissent parfois comme un bouton d'« autodestruction », mais sans belle animation.

Erreur n°1 : penser que Base64URL « cache » le payload.
Quand vous voyez une longue chaîne, vous êtes tenté de dire « bon, c'est encodé, donc c'est caché ». Base64URL est simplement une façon de transformer du JSON en une chaîne sûre. Si vous pouvez décoder le payload avec une ligne de code, alors n'importe qui ayant le token peut le décoder.

Erreur n°2 : confondre « signature » et « chiffrement ».
La signature rend la contrefaçon difficile, mais la lecture reste facile. De ce fait, on compare souvent le token à un « sceau », et c'est une analogie réussie. Si vous avez mis quelque chose en trop dans le payload, la signature ne sauve rien : le superflu sera visible par tous ceux qui voient le token.

Erreur n°3 : mettre dans le token tout et n'importe quoi « pour l'avenir ».
JWT se transforme rapidement en mini-base de données : profil, paramètres, biographie, couleur préférée du bouton « Enregistrer ». Ensuite, cela commence à vivre sa propre vie : les tokens gonflent, les structures changent, des champs obsolètes apparaissent, le client transporte des mégaoctets dans les en-têtes. JWT gagne précisément par le minimalisme : moins il y a de données, plus la maintenance est simple et plus le risque de fuite est faible.

Erreur n°4 : placer des champs sensibles (même « pas vraiment des mots de passe »).
passwordHash, les drapeaux internes de sécurité, les valeurs qu'il serait dommage de perdre ou dangereux de montrer — tout cela ne doit pas se trouver dans un payload lisible. « Mais c'est un hash ! » — ce n'est pas un argument. C'est une valeur sensible, et vous ne voulez pas la voir dans des logs tiers, dans un proxy, dans DevTools ou sur une capture d'écran que quelqu'un a jointe à un ticket.

Erreur n°5 : croire que JWT résout automatiquement l'autorisation.
JWT est un format. Il ne remplace pas vos règles d'URL et vos @PreAuthorize. Il ne fait pas pour vous la vérification de propriété. Si dans votre projet, la règle est « seul l'auteur peut modifier le brouillon », elle reste « seul l'auteur peut modifier le brouillon », même si le token contient le mot USER en grosses lettres et écrit avec une belle police.

1
Mission
Spring Security, niveau 22, leçon 0
Bloqué
Décodage du payload Base64URL
Décodage du payload Base64URL
1
Mission
Spring Security, niveau 22, leçon 0
Bloqué
Révision des champs pour le payload JWT
Révision des champs pour le payload JWT
Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION