De nos jours, le schéma de sécurité repose sur deux jetons assez courants. Il y a beaucoup d'informations sur le thème sur Internet. Il n'y a souvent qu'une description de ce que sont les jetons d'actualisation et d'accès et comment les utiliser.
Pour comprendre le concept derrière les jetons, je voudrais faire une simple expérience de pensée.
Imaginons que vous soyez un étudiant qui aime l'argent mais qui a souvent environ zéro sur le solde de son compte.
Sur le chemin de votre université, vous ouvrez votre application mobile bancaire pour vérifier le solde de votre compte.
Pour vous montrer qu'une application de solde doit exécuter une demande auprès du serveur bancaire:
GET http://api.mybank.com/balance HTTP 1.1
et reçoit une réponse
{ balance: '$0.0' }

Ce serait bien si personne sauf vous ne pouvait vérifier votre compte bancaire. Pour ce faire, ajoutons un en-tête spécial avec le nom d'utilisateur et votre mot de passe unique:
`Autorisation: nom d'utilisateur mot de passe
Autorisation: JohnDwayson QWERTY1 »
Le serveur peut désormais vous authentifier par votre nom d'utilisateur et votre mot de passe personnels. Cela signifie que la paire JohnDwayson QWERTY1 doit être conservée dans un endroit secret sur votre téléphone mobile pour être protégée de quelqu'un qui n'est pas autorisé à dépenser votre argent. Ce serait encore mieux si nous pouvions éviter de stocker le mot de passe mais personne ne veut le saisir trop souvent.
Lorsque nous utilisons notre application mobile pendant 30 minutes dans un bus, elle enverra votre mot de passe sur le réseau plusieurs fois en 30 minutes.

Chaque requset contient un mot de passe
Continuons notre expérience de pensée. Vous êtes toujours dans un bus et votre application envoie une demande au serveur.
Que se passe-t-il si une fraude vous attend dans un bus et qu'il peut intercepter un ou quelques paquets http de votre téléphone portable vers le serveur bancaire?
Si l'application met à jour les informations chaque minute, la fraude aura 30 possibilités de croiser les demandes et d'obtenir votre mot de passe.
Supposons qu'il ait volé 5-6 messages. Votre mot de passe est désormais compromis et la fraude peut l'utiliser pour accéder aux informations de votre compte.

Un homme au milieu peut entendre le mot de passe
Que peut-il faire de ces informations? Bonne nouvelle qu'il ne peut pas dépenser votre argent car vous ne l'avez pas ... pour l'instant :) Il ne peut pas non plus changer votre mot de passe car dans ce cas, vous le remarquerez et pouvez utiliser les SMS d'une banque pour récupérer le mot de passe. L'ancien mot de passe volé dans ce cas ne sera plus valide et l'étudiant économisera son argent
Mais ce qu'il peut faire, c'est de continuer à vérifier votre équilibre en parallèle avec vous. Il peut facilement écrire un script Python qui vérifiera votre compte toutes les 10 secondes et dès que vous recevrez de l'argent, il pourra dépenser chaque centime pour acheter des bitcoins. Probablement pire encore si son script dépensera 5 à 10 buks chaque jour, et il ne sera probablement pas remarqué pendant des mois ou des années.

Le pirate attend votre argent
Pour éviter cela, nous pouvons demander à l'utilisateur de changer son mot de passe après un certain temps. Disons que le mot de passe sera valide pendant 3 mois. Heureusement, après 3 mois, il perdra l'accès à votre compte. La mauvaise chose est qu'il ne perdra l'accès à votre compte qu'après 3 mois. Évidemment, pour éviter cela, nous pouvons vous demander de changer votre mot de passe tous les mois ou semaines. Mais cela peut être gênant pour les utilisateurs finaux.
Ce serait bien si nous n'utilisions pas trop souvent notre mot de passe dans nos demandes. Pour ce faire, nous pouvons introduire un point de terminaison spécial: http://api.mybank.com/login . Nous allons envoyer nos informations d'identification uniquement à ce point de terminaison et en retour, le serveur générera pour nous un jeton spécial. Que ce soit juste une chaîne unique, GUID, que le serveur stocke dans sa base de données. Appelons cette chaîne unique est un jeton d'accès. Nous l'utiliserons à la place de notre nom d'utilisateur et de notre mot de passe dans l'en-tête de chaque conversation de demande avec le serveur. Similaire au mot de passe, définissons le délai d'expiration du jeton d'accès.

Pour mettre à jour le solde, nous n'avons pas besoin d'un mot de passe
Reproduisons notre expérience de pensée.
Nous sommes dans le bus et quelqu'un a volé notre demande http pour vérifier le solde. Mais maintenant, la fraude n'a qu'un jeton d'accès.

Il ne suffit pas de voler uniquement le jeton d'accès
Quel pirate informatique peut faire maintenant avec ces informations? Tout d'abord, il ne peut toujours pas dépenser votre argent. Deuxièmement, il ne peut pas changer de mot de passe car il ne le sait tout simplement pas. De plus, l'heure d'expiration du mot de passe et du jeton d'accès est désormais deux paramètres distincts. Nous pouvons laisser le délai d'expiration du mot de passe à 3 mois et nous devons choisir l'expiration du jeton d'accès. Nous aimerions définir cette durée aussi courte que possible, car pour obtenir un nouveau jeton d'accès, nous ne pouvons pas utiliser le jeton lui-même. Si quelqu'un vole ce jeton, il pourra le renouveler aussi longtemps qu'il le voudra.
Lorsque le jeton d'accès a expiré, pour en obtenir un nouveau, nous devons envoyer à nouveau les informations d'identification de l'utilisateur. Si vous êtes dans un bus pendant 30 minutes et que votre délai d'expiration pour le jeton d'accès est de 15 minutes, vous devez envoyer votre mot de passe au moins 2 fois. Habituellement, nous voulons mettre à jour le jeton d'accès plus tôt, disons toutes les 10 minutes, sinon l'utilisateur peut remarquer des retards pour obtenir un nouveau jeton. En outre, cela résout le problème lorsque peu de demandes en même temps échouent en raison du jeton expiré et nous devons les réessayer dans le bon ordre après avoir obtenu un nouveau jeton.
Maintenant, les résultats sont meilleurs. La fraude n'a accès à nos données que pendant 10 minutes au lieu de 3 mois. Mais il a encore de la bonne monnaie pour voler notre mot de passe et nous ne le remarquerons peut-être pas tant qu'il n'aura pas volé notre argent.
Le problème est maintenant d'obtenir un jeton d'accès, nous avons toujours besoin du mot de passe. Et si nous générions une chaîne unique de plus. Un jeton spécial utilisé uniquement pour obtenir un jeton d'accès.
Pour y parvenir, notre point de terminaison de connexion doit accepter le nom d'utilisateur et le mot de passe et renvoie un nouveau jeton appelé Actualiser le jeton. Que nous stockerons dans notre application mobile. Le jeton d'actualisation peut avoir une durée d'expiration plus longue, par exemple un mois.

Renouveler le flux pour les jetons d'actualisation et d'accès
Chaque fois que nous devons renouveler le jeton d'accès, nous devons simplement envoyer un jeton d'actualisation. Ainsi, notre mot de passe ne sera envoyé au serveur qu'une fois par mois ou plus rarement. Fondamentalement, nous n'avons besoin que d'un mot de passe pour récupérer le premier jeton d'actualisation.
Nous avons toujours besoin d'un jeton d'accès pour exécuter les demandes afin d'obtenir des données du serveur. Donc:
POST /login with username and password returns us refresh token
POST /renew with refresh token returns us access token
POST /balance with access token returns us actual balance
Reprenons notre expérience.
Nous sommes dans un bus. Notre élève vérifie son solde.
Mais maintenant, notre application utilise un jeton d'actualisation qui est stocké quelque part dans un fichier sur un téléphone mobile.
L'application envoie des demandes comme:
POST /renew
GET /balance
GET /balance
GET /balance
POST /renew
GET /balance
GET /balance
GET /balance
Comme précédemment, le pirate informatique recoupe quelques requêtes avec un jeton d'accès dans un bus.
Le délai d'expiration du jeton d'accès étant de 15 minutes, nous mettons à jour les jetons toutes les 10 minutes.
Le pirate ne peut utiliser les informations volées que pendant 10 minutes ou moins.
Que se passe-t-il s'il intersecte l'une des demandes / renouvellement et dispose d'un jeton d'actualisation et d'accès? Théoriquement, il peut utiliser un jeton d'actualisation pendant un mois pour obtenir de nouveaux jetons d'accès et toujours pouvoir voler de l'argent.
Mais si nous régénérons les deux jetons à chaque demande / renouvellement et que le serveur ne stocke qu'un seul jeton d'actualisation à la fois. La copie de fraude du jeton d'actualisation est également devenue invalide dans 10 minutes et il ne peut pas l'utiliser sans nous faire savoir que le jeton est compromis. S'il essaie de renouveler le jeton, cela invalidera notre jeton et nous serons obligés de nous reconnecter.
Un autre avantage du jeton d'actualisation est que nous n'avons pas besoin de stocker le mot de passe dans une application ou un navigateur et de stocker uniquement le dernier jeton d'actualisation à la place.
Une chose intéressante est que le jeton d'accès peut être non seulement une chaîne aléatoire, mais peut contenir des informations utiles. Par exemple, il peut s'agir du délai d'expiration, de l'ID utilisateur et du rôle utilisateur. Dans ce cas, il est appelé jeton autonome et le serveur n'a pas besoin d'un accès à la base de données pour valider le jeton et les autorisations utilisateur. Il peut être très utile dans les microservices car il peut augmenter les performances et diminuer le couplage entre les microservices.
C'est un peu le thème de l'article, mais il convient de mentionner la scope
.
Et si nous demandons / renouvelons le point de terminaison uniquement pour un jeton d'accès qui peut être utilisé exclusivement pour vérifier l'équilibre?
Si l'utilisateur veut dépenser de l'argent, il devrait recevoir un deuxième jeton différent pour cela? Nous pouvons appeler ce paramètre «portée».
Nous pouvons donc demander / renouveler? Scope = [balance, news]. Si notre pirate conserve ce jeton, il ne peut pas l'utiliser pour dépenser notre argent!
Une idée basée sur deux jetons offre une meilleure sécurité d'utilisation qu'un simple mot de passe ou un jeton par conception. Au lieu de choisir un mot de passe plus long ou des algorithmes de sécurité plus forts.
C'était mon explication du concept de base derrière les jetons et comment ils fonctionnent.
Sur une pratique, il existe plusieurs implémentations différentes de ce concept qui peuvent être facilement googlé.
Petite note sur la flexibilité dans le choix d'une heure d'expiration pour le mot de passe et les jetons.
Le délai d'expiration typique peut être:
Pour le mot de passe, c'est 3-6 mois. Il est bon d'avoir cette limitation. Comme les bases de données peuvent être volées et que l'utilisateur peut réutiliser le même mot de passe entre les services.
Pour le jeton d'actualisation, le délai d'expiration peut être d'environ une semaine ou un mois. Pour les personnes qui travaillent dans un bureau avec un site Web, il est utile d'avoir ce temps au moins plus d'un week-end. Sinon, ils doivent entrer un mot de passe tous les lundis.
Le délai d'expiration du jeton d'accès peut être compris entre 10 et 60 minutes. Un temps plus court nécessite plus de demandes de renouvellement, mais un temps plus long peut donner plus de chances de fraude.
Conclusion :
Nous devons utiliser un mot de passe pour obtenir un jeton d'actualisation de longue durée. Envoyez ensuite un jeton d'actualisation pour obtenir un jeton d'accès de courte durée. Utilisez ensuite un jeton d'accès pour exécuter des requêtes utiles.