web-dev-qa-db-fra.com

Jetons Web JSON (JWT) en tant que jetons d'identification et d'authentification des utilisateurs

J'implémente un service REST qui nécessite une authentification. Je ne peux pas stocker d'état par utilisateur (tel qu'un jeton généré de manière aléatoire) car mon service n'a pas d'accès direct à une base de données, uniquement à un autre service backend.

La solution que j'ai trouvée consiste à créer un jeton Web JSON ( JWT ) lorsque l'utilisateur s'authentifie. L'ensemble de revendications JWT contient l'ID utilisateur dans le champ Objet ("sous"). Le serveur crypte ensuite le jeu de revendications directement ("alg": "dir") en utilisant AES GCM avec une clé de 256 bits ("enc": "A256GCM") créant un JWE . La clé est générée une fois au démarrage du service et stockée en mémoire.

Pour s'authentifier, le client soumet le nom d'utilisateur/mot de passe et le serveur répond avec le jeton décrit ci-dessus. Le client envoie ensuite ce jeton à chaque demande ultérieure.

Lorsque le client soumet le jeton avec les demandes suivantes, le serveur le déchiffre à l'aide de la clé et suppose que l'ID utilisateur dans le champ "sub" est l'ID de l'utilisateur actuel, sans plus vérifications d'authentification. L'expiration du jeton est gérée par le champ "exp" dans le jeu de revendications JWT.

La connexion entre le client et le serveur utilisera SSL/TLS, donc le jeton ne fuira pas.

J'utilise cette bibliothèque pour créer et lire des JWT car je ne me fais pas confiance pour écrire le bon code de cryptographie.

Mes questions:

  1. L'approche ci-dessus est-elle sécurisée? Un attaquant peut-il usurper l'identité d'un autre utilisateur en manipulant le jeton?
  2. L'approche est-elle trop compliquée? L'utilisation de MAC (en d'autres termes: JWS ) au lieu du cryptage aurait-elle la même sécurité? (ou peut-être plus, car c'est plus simple et il y a moins de chance de faire une erreur). Il n'y a rien de particulièrement secret dans l'ensemble de revendications JWT, et l'utilisateur connaissant son propre ID n'a pas d'importance.
  3. Mon choix d'algorithme JWE et de chiffrement est-il approprié?
    • Pour le "alg" JWE, la bibliothèque que j'utilise prend en charge le chiffrement direct (en utilisant la clé directement pour chiffrer l'ensemble de revendications) et RSA (en générant une nouvelle clé pour chiffrer l'ensemble de revendications pour chaque jeton, et en chiffrant la clé générée avec un Clé publique RSA). J'ai choisi le premier car il est plus facile de générer une clé symétrique qu'une clé RSA.
    • Pour le JWE "enc", la bibliothèque prend en charge AES GCM et AES CBC HMAC SHA2 (avec différentes longueurs de bits). J'ai choisi GCM arbitrairement.
70
imgx64

Votre approche de base est valide: générez le JWT lorsque l'utilisateur se connecte, attendez-vous à ce que les messages suivants portent le JWT, faites confiance au champ sujet du JWT dans ces messages suivants si le JWT est valide. Mais vous devez être conscient de plusieurs choses:

  1. Comme le dit Daisetsu, vous pouvez utiliser un MAC ("alg": "HS256") car les MAC sont spécifiquement conçus pour empêcher l'altération de la charge utile, tandis que les algorithmes de chiffrement sont généralement (contre-intuitivement) ne le sont pas. Cependant, puisque vous utilisez spécifiquement AES en mode GCM , vous bénéficiez déjà d'un cryptage inviolable ("cryptage authentifié"), ce n'est donc pas vraiment un problème.
  2. Lors de la validation d'un JWT entrant, faites attention à ce que vous considérez comme valide. Par exemple, je pourrais appeler votre service avec {"sub": "me", "alg": "none"} et bien que ce JWT soit valide dans un certain sens, ce n'est pas quelque chose que vous voulez accepter.
  3. Étant donné que JWT est un projet, pas encore une norme, il pourrait changer. Si elle change suffisamment, la bibliothèque que vous utilisez devra peut-être changer de manière à rompre la compatibilité avec votre code.
  4. Si vous ne pouvez stocker aucun état côté serveur, vous n'avez aucun moyen d'invalider le JWT lorsque l'utilisateur se déconnecte. En effet, votre service n'a pas de fonction de déconnexion, ce qui peut être un problème de sécurité, surtout si vous définissez trop tard le délai d'expiration.
  5. Si vous définissez l'heure d'expiration trop tôt, vous pouvez avoir un problème avec les utilisateurs toujours connectés mais n'ayant pas de JWT valide. Cela peut entraîner des problèmes de gestion des erreurs et de flux de travail utilisateur.

Puisque vous avez dit que votre serveur n'avait pas accès à une base de données, je suppose que la connexion réelle est gérée ailleurs, peut-être le serveur principal que vous avez mentionné. Vous n'avez pas dit comment votre serveur sait que l'utilisateur vient de se connecter. Selon la perception qu'ont les utilisateurs de la relation entre votre service et la chose à laquelle ils savent qu'ils se sont connectés, les deux derniers points ci-dessus peuvent être sans objet.

52
gatkin

Si aucune des données n'est sensible, il vous suffit de préserver l'intégrité des données. La signature (JWS) du jeton devrait être suffisante pour cela.

Si vous faites juste une signature, vous devriez être bien avec HMAC SHA-256. N'oubliez pas de définir une expiration du jeton et de vérifier si l'utilisateur s'est déconnecté manuellement (dans ce cas, invalidez le jeton). Une fois que vous prenez en compte l'expiration et la déconnexion, il n'y a pas grand-chose à craindre (en termes d'algorithme). Les chances que quelqu'un craque un SHA-256 au cours d'une seule session (devraient) être relativement faibles (en supposant que vous ayez besoin d'une nouvelle authentification à un intervalle RAISONNABLE).

Comme toujours avec la signature, assurez-vous de fournir le contenu à signer (nom d'utilisateur, type de compte, etc.) ne laissez jamais aucune des données définies par l'utilisateur être signée ou vous pourriez être dans une situation dangereuse.

Avertissement: Ce message est strictement mon avis. Je ne fais aucune réclamation sur la fiabilité ou l'adéquation de mes réponses. Vous devriez toujours consulter un professionnel de la sécurité pour discuter de vos problèmes spécifiques de mise en œuvre de la sécurité. C'est purement éducatif.

10
Daisetsu