J'aime JWT. C'est vraiment amusant de travailler avec. Ma question est la suivante: si je reçois un JWT et que je peux décoder la charge utile, comment est-il sécurisé? Ne pourrais-je pas simplement extraire le jeton de l'en-tête, décoder et modifier les informations utilisateur dans la charge utile et les renvoyer avec le même secret codé correct?
Je sais qu'ils doivent être en sécurité, mais j'aimerais vraiment comprendre les technologies. Qu'est-ce que je rate? Merci!
Les JWT peuvent être signés, cryptés ou les deux. Si un jeton est signé, mais pas chiffré, tout le monde peut en lire le contenu, mais lorsque vous ne connaissez pas la clé privée, vous ne pouvez pas le modifier. Sinon, le destinataire remarquera que la signature ne correspond plus.
Répondez à votre commentaire: je ne suis pas sûr de bien comprendre votre commentaire. Juste pour être sûr: connaissez-vous et comprenez-vous les signatures numériques? J'expliquerai brièvement une variante (HMAC, symétrique, mais il en existe beaucoup d'autres).
Supposons qu'Alice souhaite envoyer un JWT à Bob. Ils connaissent tous les deux un secret partagé. Mallory ne connaît pas ce secret, mais veut intervenir et changer le JWT. Pour éviter cela, Alice calcule Hash(payload + secret)
et l'ajoute en tant que signature.
Lors de la réception du message, Bob peut également calculer Hash(payload + secret)
pour vérifier si la signature correspond. Cependant, si Mallory change quelque chose dans le contenu, elle ne pourra pas calculer la signature correspondante (ce qui serait Hash(newContent + secret)
). Elle ne connaît pas le secret et n'a aucun moyen de le découvrir. Cela signifie que si elle change quelque chose, la signature ne correspond plus et Bob n'acceptera plus le JWT.
Supposons que j'envoie le message {"id":1}
à une autre personne et que je le signe avec Hash(content + secret)
. (+ est juste concaténation ici). J'utilise la fonction SHA256 Hash et la signature que je reçois est: 330e7b0775561c6e95797d4dd306a150046e239986f0a1373230fda0235bda8c
. À vous de jouer: incarnez Mallory et essayez de signer le message {"id":2}
. Vous ne pouvez pas parce que vous ne savez pas quel secret j'ai utilisé. Si je suppose que le destinataire connaît le secret, il PEUT calculer la signature de tout message et vérifier s'il est correct.
Vous pouvez aller à jwt.io
, coller votre jeton et lire le contenu. Au début, cela choque beaucoup de gens.
La réponse courte est que JWT ne se préoccupe pas du cryptage. Cela concerne la validation. C'est-à-dire qu'il peut toujours obtenir la réponse pour "faire manipuler le contenu de ce jeton"? Cela signifie que la manipulation du jeton JWT par l'utilisateur est vaine, car le serveur le reconnaîtra et l'ignorera. Le serveur ajoute une signature basée sur la charge utile lors de l'émission d'un jeton au client. Plus tard, il vérifie la charge utile et la signature correspondante.
La question logique est de savoir quelle est la motivation pour ne pas se préoccuper des contenus cryptés?
La raison la plus simple est parce qu’il suppose qu’il s’agit en grande partie d’un problème résolu. Si vous traitez avec un client tel que le navigateur Web, par exemple, vous pouvez stocker les jetons JWT dans un cookie de type _secure + httpsOnly
_ (ne peut pas être lu par Javascript + ne peut pas être lu par HTTP) et parle au serveur. sur un canal crypté (HTTPS). Une fois que vous savez que vous avez un canal sécurisé entre le serveur et le client, vous pouvez échanger en toute sécurité JWT ou ce que vous voulez.
Cela rend la chose simple. Une implémentation simple facilite l’adoption, mais permet également à chaque couche de faire ce qu’elle fait de mieux (laissez HTTPS gérer le cryptage).
JWT n'est pas conçu pour stocker des données sensibles. Une fois que le serveur reçoit le jeton JWT et le valide, il est libre de rechercher l'ID utilisateur dans sa propre base de données pour obtenir des informations supplémentaires sur cet utilisateur (autorisations, adresse postale, etc.). Cela permet à JWT de rester de petite taille et évite les fuites d'informations par inadvertance, car tout le monde sait qu'il ne faut pas conserver de données sensibles dans JWT.
Ce n'est pas très différent de la façon dont les cookies fonctionnent. Les cookies contiennent souvent des charges utiles non chiffrées. Si vous utilisez HTTPS, tout va bien. Si vous ne l'êtes pas, il est conseillé de chiffrer les cookies sensibles eux-mêmes. Ne pas le faire signifiera qu'une attaque de l'homme du milieu est possible - un serveur proxy ou un fournisseur d'accès lit les cookies puis les rejoue plus tard en se faisant passer pour vous. Pour des raisons similaires, JWT doit toujours être échangé sur une couche sécurisée telle que HTTPS.
Le contenu d'un jeton Web JSON (JWT) n'est pas intrinsèquement sécurisé, mais une fonctionnalité intégrée permet de vérifier l'authenticité du jeton. Un JWT est trois hachages séparés par des points. Le troisième est la signature. Dans un système à clé publique/privée, l'émetteur signe la signature du jeton avec une clé privée qui ne peut être vérifiée que par la clé publique correspondante.
Il est important de comprendre la distinction entre émetteur et vérificateur. Le destinataire du jeton est responsable de sa vérification.
L'utilisation sécurisée de JWT dans une application Web se fait en deux étapes critiques: 1) envoyez-les par un canal crypté, et 2) vérifiez la signature immédiatement après l'avoir reçue. La nature asymétrique de la cryptographie à clé publique permet la vérification de la signature JWT. Une clé publique vérifie qu'un JWT a été signé par sa clé privée correspondante. Aucune autre combinaison de clés ne peut effectuer cette vérification, empêchant ainsi les tentatives d'emprunt d'identité. Suivez ces deux étapes et nous pouvons garantir avec une certitude mathématique l’authenticité d’un JWT.
More reading: Comment une clé publique vérifie-t-elle une signature?
Seul le privateKey de JWT, qui se trouve sur votre serveur, décryptera le JWT crypté. Ceux qui connaissent la privateKey pourront décrypter le fichier JWT chiffré.
Cachez la clé privée dans un emplacement sécurisé sur votre serveur et ne communiquez jamais cette clé à personne.
Pour les personnes qui ne peuvent pas se permettre des requêtes de base de données coûteuses telles que moi, une option pour conserver les données confidentielles (privilèges utilisateur, etc.) est la suivante: lors de la génération du fichier JWT, vous pouvez chiffrer ces données et les attacher au jeton JWT. (Gardez la clé de cryptage dans le backend)
Lorsque vous souhaitez lire les informations sensibles, vous pouvez envoyer le jeton JWT au serveur principal, le déchiffrer et récupérer les informations. De cette façon, vous n’avez pas à faire de recherches dans la base de données ni à avoir les informations sensibles nues dans l’interface via le jeton JWT.
Je suggérerais de jeter un coup d'oeil sur JWE en utilisant des algorithmes spéciaux qui ne sont pas présents dans jwt.io pour déchiffrer
Lien de référence: https://www.npmjs.com/package/node-webtokens
jwt.generate('PBES2-HS512+A256KW', 'A256GCM', payload, pwd, (error, token) => {
jwt.parse(token).verify(pwd, (error, parsedToken) => {
// other statements
});
});
Cette réponse est peut-être trop tardive ou vous avez peut-être déjà trouvé le chemin, mais j’ai quand même pensé que cela serait utile pour vous et les autres également.
Un exemple simple que j'ai créé: https://github.com/hansiemithun/jwe-example