web-dev-qa-db-fra.com

Authentification JWT et implémentation de jeton d'actualisation

Je développe une application REST avec son propre mécanisme d'authentification et d'autorisation. Je souhaite utiliser les jetons Web JSON pour l'authentification. Ce qui suit est une implémentation valide et sûre?

  1. Une API REST sera développée pour accepter le nom d'utilisateur et le mot de passe et effectuer l'authentification. La méthode HTTP à utiliser est POST afin qu'il n'y ait pas de mise en cache. En outre, il y aura SSL pour la sécurité au moment du transit
  2. Au moment de l'authentification, deux JWT seront créés: jeton d'accès et jeton d'actualisation. Le jeton d'actualisation aura une validité plus longue. Les deux jetons seront écrits dans des cookies, de manière à être envoyés dans toutes les demandes ultérieures.
  3. À chaque appel de l'API REST, les jetons seront récupérés à partir de l'en-tête HTTP. Si le jeton d'accès n'a pas expiré, vérifiez les privilèges de l'utilisateur et autorisez l'accès en conséquence. Si le jeton d'accès a expiré mais que le jeton d'actualisation est valide, recréez un nouveau jeton d'accès et un jeton d'actualisation avec de nouvelles dates d'expiration (effectuez toutes les vérifications nécessaires pour vous assurer que les droits de l'utilisateur à s'authentifier ne sont pas révoqués) et renvoyés via des cookies
  4. Fournissez une API de déconnexion REST qui réinitialisera le cookie et, par conséquent, les appels d'API ultérieurs seront rejetés jusqu'à la fin de la connexion.

Ma compréhension du jeton d'actualisation est la suivante:

En raison de la présence du jeton d'actualisation, nous pouvons conserver une période de validité plus courte pour le jeton d'accès et vérifier fréquemment (à l'expiration du jeton d'accès) que l'utilisateur est toujours autorisé à se connecter.

S'il vous plait corrigez moi si je me trompe.

7
Saptarshi Basu

Une API REST sera développée pour accepter le nom d'utilisateur et le mot de passe, puis exécuter la commande l'authentification. La méthode HTTP à utiliser est POST afin qu'il y ait n'est pas en cache. En outre, il y aura SSL pour la sécurité au moment de transit

C'est la façon dont la plupart le font, alors vous êtes bon ici.

Au moment de l'authentification, deux JWT seront créés - jeton d'accès et rafraîchir le jeton. Le jeton d'actualisation aura une validité plus longue. Les deux le Les jetons seront écrits dans les cookies, de sorte qu'ils soient envoyés à chaque demandes ultérieures

Stocker les jetons dans des cookies n’est pas dangereux en soi, mais si vous obtenez en quelque sorte votre module JWT sur votre serveur pour les lire à partir de là, vous êtes vulnérable aux attaques CSRF où toute page Web peut obliger un navigateur d’utilisateur à envoyer un formulaire et vos cookies à des sites. votre serveur, sauf si vous utilisez des jetons CSRF. Donc, généralement, ils sont stockés dans localStorage et ajoutés "manuellement" pour demander des en-têtes à chaque fois.

À chaque appel de l'API REST, les jetons seront extraits du HTTP entête. Si le jeton d'accès n'a pas expiré, vérifiez les privilèges de l'utilisateur et autoriser l'accès en conséquence. Si le jeton d'accès est expiré mais le jeton d'actualisation est valide, recréez un nouveau jeton d'accès et actualisez Jeton avec nouvelles dates d'expiration (faites toutes les vérifications nécessaires pour vous assurer que les droits d'utilisateur pour s'authentifier ne sont pas révoqués) et renvoyés via Biscuits

En dehors des dangers liés aux cookies, cela semble sans danger.

Fournissez une API de déconnexion REST qui réinitialisera le cookie et, par conséquent, les appels d'API ultérieurs seront rejetés jusqu'à ce que la connexion soit terminée.

Vous n'avez même pas besoin de faire un appel d'API, vous pouvez simplement purger les cookies ou l'objet localStorage et vous assurer que votre client ne casse pas les jetons manquants.

La norme pour le module express-jwt prévoit que les jetons se trouvent dans son propre en-tête "Authorization: Bearer [Token]", ce que je recommanderais fortement aux cookies. L’API localStorage est disponible jusqu’à IE8 vous devriez donc être bon.

Modifier:

Tout d'abord, il est important de connaître la différence entre les attaques XSS et CSRF, car elles sont souvent considérées comme identiques.

XSS, c’est lorsque les utilisateurs obtiennent que des fichiers JS non sécurisés s’exécutant sur votre domaine dans les navigateurs d’autres utilisateurs. Lorsque cela se produit, ni JWT dans localStorage ni sessions et JWT dans les cookies ne sont sécurisés. Avec l'indicateur httpOnly sur les cookies, vous ne pouvez pas y accéder directement, mais le navigateur les enverra quand même avec des requêtes AJAX à votre serveur. Si cela se produit, vous n'avez généralement pas de chance. Pour éviter cela, assurez-vous d'échapper à toutes les entrées utilisateur si elles sont envoyées au navigateur.

Si vous chargez des fichiers JS tiers avec des balises de script ou des iframes, cela risque de compromettre localStorage à moins que vous ne soyez prudent, mais je n'ai pas assez travaillé avec cela pour vous aider ici.

CSRF n’est utilisé que lorsque d’autres domaines tentent d’envoyer des formulaires HTML normaux à votre serveur en obligeant le navigateur à envoyer automatiquement des cookies. Les cadres empêchent cela en insérant des chaînes aléatoires uniques en tant que champs cachés et en les vérifiant à nouveau lors de leur soumission. Les JWT dans localStorage sont à l'abri de cette situation, car chaque domaine possède sa propre zone de stockage locale.

Mais finalement, tout dépend de si votre service utilisera un seul domaine. Dans ce cas, les cookies httpOnly seront plus sûrs et plus faciles à configurer, mais si vous souhaitez étendre votre service sur plusieurs domaines tels que api.domain.com + app .domain.com ou ajoutez une application native que vous êtes obligé de stocker, vous êtes des JWT dans localStorage ou dans une autre zone de stockage native.

J'espère que cela t'aides!

7
Hjort-e

Ma compréhension du jeton d'actualisation est la suivante:

En raison de la présence du jeton d'actualisation, nous pouvons conserver une période de validité plus courte pour le jeton d'accès et vérifier fréquemment (à l'expiration du jeton d'accès) que l'utilisateur est toujours autorisé à se connecter.

S'il vous plait corrigez moi si je me trompe.

En supposant que vous envisagiez d'utiliser JWT en tant que porteur dans OAuth (et je vous conseillerais vivement de suivre le protocole OAuth 2.0), c'est exact. 

Avec une revendication supplémentaire d'auth-time (horodatage de l'authentification) dans votre JWT, vous pouvez même supprimer le deuxième jeton et envoyer votre accès sous forme de jeton d'actualisation (le serveur d'authentification pourrait alors émettre un nouveau jeton d'accès si le jeton est valide & auth-time dans la plage autorisée) ... mais bien sûr, il est également bon de suivre la norme;) 

Quoi qu'il en soit, il y a certains aspects supplémentaires (qui tendent à devenir difficiles ou vont même à l'encontre des idées fondamentales de JWT) que vous devriez considérer avant d'utiliser les JWT en tant que rafraîchissement, car cela signifie fondamentalement que vous introduisez JWT à vie longue:

  • avez-vous besoin de quelque chose comme une déconnexion utilisateur forcée/une révocation de jeton par sujet (par exemple, si un utilisateur est identifié comme frauduleux)?
  • avez-vous besoin de quelque chose comme la révocation d'un jeton spécifique (par exemple, si un utilisateur perd un périphérique)?
  • ...

En fonction de votre cas d'utilisation, vous devez prendre en compte toutes les implications possibles des jetons de longue durée, car ils vous obligent généralement à introduire un type d'état sur votre serveur (par exemple, pour autoriser la révocation/liste noire). N'oubliez pas que la beauté et la sécurité du concept JWT résident dans la courte durée de vie des JWT. 

1
jbspeakr

J'ai posé cette question il y a deux ans et j'ai également accepté la réponse. Cependant, sur la base de mon expérience et de mes études au cours des deux dernières années, j'aimerais répondre à cette question au cas où quelqu'un trébucherait sur ce sujet avec la même question.

L'approche mentionnée dans la question est similaire au type d'octroi "Informations d'authentification de mot de passe du propriétaire de la ressource" d'OAuth 2.0. Cependant, je pense qu'il est préférable d'utiliser le type "Autorisation du code d'autorisation" et Cookie pour stocker les jetons au lieu de navigateur localStorage ou sessionStorage. J'ai détaillé mes raisons, points d'implémentation, considérations de sécurité et références dans cette réponse StackOverlow .

0
Saptarshi Basu