Je voudrais implémenter l'authentification basée sur JWT dans notre nouvelle API REST. Mais puisque l'expiration est définie dans le jeton, est-il possible de la prolonger automatiquement? Je ne veux pas que les utilisateurs aient besoin de se connecter après toutes les X minutes s'ils utilisaient activement l'application pendant cette période. Ce serait un énorme échec UX.
Mais prolonger l'expiration crée un nouveau jeton (et l'ancien est toujours valide jusqu'à son expiration). Et générer un nouveau jeton après chaque demande me semble idiot. Cela ressemble à un problème de sécurité lorsque plusieurs jetons sont valides en même temps. Bien sûr, je pouvais invalider l'ancien utilisé en utilisant une liste noire, mais je devrais stocker les jetons. Et l'un des avantages de JWT est l'absence de stockage.
J'ai trouvé comment Auth0 l'a résolu. Ils utilisent non seulement un jeton JWT mais également un jeton d'actualisation: https://docs.auth0.com/refresh-token
Mais encore une fois, pour implémenter cela (sans Auth0), je devrais stocker des jetons de rafraîchissement et maintenir leur expiration. Quel est donc le véritable avantage? Pourquoi ne pas avoir un seul jeton (pas JWT) et conserver l'expiration sur le serveur?
Y a-t-il d'autres options? L'utilisation de JWT n'est-elle pas adaptée à ce scénario?
Réponses:
Je travaille chez Auth0 et j'ai été impliqué dans la conception de la fonctionnalité d'actualisation du jeton.
Tout dépend du type d'application et voici notre approche recommandée.
des applications Web
Un bon schéma consiste à actualiser le jeton avant son expiration.
Définissez l'expiration du jeton sur une semaine et actualisez le jeton à chaque fois que l'utilisateur ouvre l'application Web et toutes les heures. Si un utilisateur n'ouvre pas l'application pendant plus d'une semaine, il devra se reconnecter et ceci est une UX d'application web acceptable.
Pour actualiser le jeton, votre API a besoin d'un nouveau point de terminaison qui reçoit un JWT valide et non expiré et renvoie le même JWT signé avec le nouveau champ d'expiration. Ensuite, l'application Web stockera le jeton quelque part.
Applications mobiles / natives
La plupart des applications natives ne se connectent qu'une seule fois.
L'idée est que le jeton d'actualisation n'expire jamais et qu'il peut toujours être échangé contre un JWT valide.
Le problème avec un jeton qui n'expire jamais est que cela ne signifie jamais. Que faites-vous si vous perdez votre téléphone? Il doit donc être identifiable par l'utilisateur d'une manière ou d'une autre et l'application doit fournir un moyen de révoquer l'accès. Nous avons décidé d'utiliser le nom de l'appareil, par exemple "iPad de maryo". Ensuite, l'utilisateur peut accéder à l'application et révoquer l'accès à "l'iPad de maryo".
Une autre approche consiste à révoquer le jeton d'actualisation sur des événements spécifiques. Un événement intéressant change le mot de passe.
Nous pensons que JWT n'est pas utile pour ces cas d'utilisation, nous utilisons donc une chaîne générée de manière aléatoire et nous la stockons de notre côté.
la source
Dans le cas où vous gérez vous-même l'authentification (c'est-à-dire n'utilisez pas de fournisseur comme Auth0), les éléments suivants peuvent fonctionner:
L'indicateur «reauth» dans le backend de la base de données est défini lorsque, par exemple, l'utilisateur a réinitialisé son mot de passe. L'indicateur est supprimé lorsque l'utilisateur se connecte la prochaine fois.
De plus, supposons que vous ayez une politique selon laquelle un utilisateur doit se connecter au moins une fois toutes les 72 heures. Dans ce cas, votre logique d'actualisation de jeton API vérifierait également la dernière date de connexion de l'utilisateur à partir de la base de données utilisateur et refuser / autoriser l'actualisation du jeton sur cette base.
la source
Je bricolais lors du déplacement de nos applications vers HTML5 avec des API RESTful dans le backend. La solution que j'ai trouvée était:
Comme vous pouvez le voir, cela réduit les demandes fréquentes de jetons d'actualisation. Si l'utilisateur ferme le navigateur / l'application avant le déclenchement de l'appel de renouvellement de jeton, le jeton précédent expirera à temps et l'utilisateur devra se reconnecter.
Une stratégie plus compliquée peut être mise en œuvre pour répondre à l'inactivité des utilisateurs (par exemple, négligé un onglet de navigateur ouvert). Dans ce cas, l'appel de renouvellement de jeton doit inclure le temps d'expiration attendu qui ne doit pas dépasser le temps de session défini. L'application devra suivre la dernière interaction de l'utilisateur en conséquence.
Je n'aime pas l'idée de définir une longue expiration, donc cette approche peut ne pas fonctionner correctement avec des applications natives nécessitant une authentification moins fréquente.
la source
Une solution alternative pour invalider les JWT, sans stockage sécurisé supplémentaire sur le backend, consiste à implémenter une nouvelle
jwt_version
colonne entière sur la table des utilisateurs. Si l'utilisateur souhaite se déconnecter ou expirer les jetons existants, il incrémente simplement lejwt_version
champ.Lors de la génération d'un nouveau JWT, encodez le
jwt_version
dans la charge utile JWT, en incrémentant éventuellement la valeur au préalable si le nouveau JWT doit remplacer tous les autres.Lors de la validation du JWT, le
jwt_version
champ est comparé à côté deuser_id
et l'autorisation n'est accordée que si elle correspond.la source
Bonne question - et il y a une mine d'informations dans la question elle-même.
L'article Actualiser les jetons: quand les utiliser et comment ils interagissent avec les JWT donne une bonne idée de ce scénario. Quelques points sont: -
Jetez également un œil à auth0 / angular-jwt angularjs
Pour l'API Web. lire Activer les jetons d'actualisation OAuth dans l'application AngularJS à l'aide d'ASP .NET Web API 2 et Owin
la source
J'ai en fait implémenté cela en PHP en utilisant le client Guzzle pour créer une bibliothèque cliente pour l'API, mais le concept devrait fonctionner pour d'autres plates-formes.
Fondamentalement, j'émets deux jetons, un court (5 minutes) et un long qui expire après une semaine. La bibliothèque cliente utilise un middleware pour tenter une actualisation du jeton court si elle reçoit une réponse 401 à une requête. Il réessayera alors la demande d'origine et s'il a pu actualiser obtient la réponse correcte, de manière transparente pour l'utilisateur. S'il échoue, il enverra simplement le 401 à l'utilisateur.
Si le jeton court a expiré, mais reste authentique et que le jeton long est valide et authentique, il actualisera le jeton court en utilisant un point de terminaison spécial sur le service que le jeton long authentifie (c'est la seule chose pour laquelle il peut être utilisé). Il utilisera ensuite le jeton court pour obtenir un nouveau jeton long, le prolongeant ainsi une semaine de plus chaque fois qu'il actualise le jeton court.
Cette approche nous permet également de révoquer l'accès dans un délai maximum de 5 minutes, ce qui est acceptable pour notre utilisation sans avoir à stocker une liste noire de jetons.
Édition tardive: relisant ce mois après qu'il était frais dans ma tête, je dois souligner que vous pouvez révoquer l'accès lors de l'actualisation du jeton court, car cela donne la possibilité d'appels plus coûteux (par exemple, appelez la base de données pour voir si l'utilisateur a été interdit) sans le payer à chaque appel vers votre service.
la source
Voici les étapes à suivre pour révoquer votre jeton d'accès JWT:
1) Lorsque vous vous connectez, envoyez 2 jetons (jeton d'accès, jeton d'actualisation) en réponse au client.
2) Le jeton d'accès aura un délai d'expiration inférieur et le rafraîchissement aura un délai d'expiration long.
3) Le client (frontal) stockera le jeton d'actualisation dans son stockage local et le jeton d'accès dans les cookies.
4) Le client utilisera un jeton d'accès pour appeler les API. Mais lorsqu'il expire, choisissez le jeton d'actualisation dans le stockage local et appelez l'API du serveur d'authentification pour obtenir le nouveau jeton.
5) Votre serveur d'authentification aura une API exposée qui acceptera le jeton de rafraîchissement et vérifiera sa validité et retournera un nouveau jeton d'accès.
6) Une fois le jeton d'actualisation expiré, l'utilisateur sera déconnecté.
Veuillez me faire savoir si vous avez besoin de plus de détails, je peux également partager le code (Java + Spring boot).
la source
jwt-autorefresh
Si vous utilisez un nœud (React / Redux / Universal JS), vous pouvez installer
npm i -S jwt-autorefresh
.Cette bibliothèque planifie l'actualisation des jetons JWT à un nombre calculé par l'utilisateur de secondes avant l'expiration du jeton d'accès (en fonction de la revendication exp codée dans le jeton). Il dispose d'une suite de tests complète et vérifie plusieurs conditions pour s'assurer que toute activité étrange est accompagnée d'un message descriptif concernant les erreurs de configuration de votre environnement.
Exemple d'implémentation complet
mentions légales: je suis le mainteneur
la source
jwt-autorefresh
décode est d'extraire laexp
revendication afin qu'elle puisse déterminer dans quelle mesure planifier la prochaine actualisation.J'ai résolu ce problème en ajoutant une variable dans les données de jeton:
J'ai défini l'
expiresIn
option à l'heure souhaitée avant que l'utilisateur ne soit obligé de se reconnecter. Le mien est réglé sur 30 minutes. Elle doit être supérieure à la valeur desoftexp
.Lorsque mon application côté client envoie une demande à l'API du serveur (où le jeton est requis, par exemple la page de liste des clients), le serveur vérifie si le jeton soumis est toujours valide ou non en fonction de sa
expiresIn
valeur d' expiration ( ) d'origine. S'il n'est pas valide, le serveur répondra avec un état particulier pour cette erreur, par exemple.INVALID_TOKEN
.Si le jeton est toujours valide en fonction de la
expiredIn
valeur, mais qu'il a déjà dépassé lasoftexp
valeur, le serveur répondra avec un état distinct pour cette erreur, par exemple.EXPIRED_TOKEN
:Côté client, s'il a reçu
EXPIRED_TOKEN
réponse, il doit renouveler le token automatiquement en envoyant une demande de renouvellement au serveur. Cela est transparent pour l'utilisateur et est automatiquement pris en charge par l'application cliente.La méthode de renouvellement sur le serveur doit vérifier si le jeton est toujours valide:
Le serveur refusera de renouveler les jetons s'il a échoué la méthode ci-dessus.
la source
Que diriez-vous de cette approche:
Nous n'avons pas besoin de point de terminaison supplémentaire pour actualiser le jeton dans ce cas. J'apprécierais n'importe quel feedack.
la source
Aujourd'hui, beaucoup de gens optent pour faire de la gestion de session avec JWTs sans être conscients de ce qu'ils donnent pour l'amour de la perception de simplicité. Ma réponse développe la 2ème partie des questions:
Les JWT sont capables de prendre en charge la gestion de session de base avec certaines limitations. Étant des jetons auto-descriptifs, ils ne nécessitent aucun état côté serveur. Cela les rend attrayants. Par exemple, si le service n'a pas de couche de persistance, il n'est pas nécessaire d'en apporter une uniquement pour la gestion de session.
Cependant, l'apatridie est également la principale cause de leurs lacunes. Puisqu'ils ne sont émis qu'une seule fois avec un contenu et une expiration fixes, vous ne pouvez pas faire les choses que vous souhaitez avec une configuration de gestion de session typique.
À savoir, vous ne pouvez pas les invalider à la demande. Cela signifie que vous ne pouvez pas implémenter une déconnexion sécurisée car il n'y a aucun moyen d'expiration des jetons déjà émis. Vous ne pouvez pas non plus implémenter le délai d'inactivité pour la même raison. Une solution consiste à conserver une liste noire, mais cela introduit l'état.
J'ai écrit un article expliquant ces inconvénients plus en détail. Pour être clair, vous pouvez contourner ces problèmes en ajoutant plus de complexité (sessions glissantes, jetons d'actualisation, etc.)
En ce qui concerne les autres options, si vos clients interagissent uniquement avec votre service via un navigateur, je recommande fortement d'utiliser une solution de gestion de session basée sur les cookies. J'ai également compilé une liste des méthodes d'authentification actuellement largement utilisées sur le web.
la source