Sécurisez vos ressources d'API pour la communication entre machines
Découvrez comment exploiter OAuth 2.0 et JWT pour sécuriser vos ressources d'API pour la communication entre machines.
Découvrez comment exploiter OAuth 2.0 et JWT pour sécuriser vos ressources d'API pour la communication entre machines.
Lors de la création d'un projet impliquant plusieurs services, la sécurité des ressources de l'API est une préoccupation essentielle. Dans cet article, je vous montrerai comment tirer parti d'OAuth 2.0 et JWT pour sécuriser la communication entre services (machine à machine), et comment appliquer le contrôle d'accès basé sur les rôles (RBAC) pour suivre le principe de privilège minimum.
Pour suivre, je suppose que vous avez les prérequis suivants :
À des fins de démonstration, supposons que nous ayons les services suivants :
https://cart.example.com/apihttps://payment.example.com/apiMaintenant, notre service de panier doit appeler le service de paiement pour traiter les paiements. Le flux d'authentification est le suivant :
Quelques concepts clés dans le diagramme ci-dessus :
Chaque participant dans le diagramme ci-dessus a un rôle à jouer dans le flux d'authentification :
Passons en revue le flux d'authentification étape par étape.
Pour effectuer le flux d'authentification, nous devons créer une application machine à machine (service de panier) et une ressource d'API (service de paiement) dans Logto.
Étant donné que notre service de panier doit être conscient de l'API du service de paiement lors de l'authentification, nous devons d'abord créer une ressource d'API. Allez dans Logto Console, cliquez sur API resources dans la barre latérale gauche et cliquez sur Create API resource. Dans la boîte de dialogue ouverte, nous offrons quelques tutoriels pour vous aider à démarrer. Vous pouvez également cliquer sur Continue without tutorial pour le sauter.
Entrez le nom et l'identifiant de l'API, par exemple, Service de paiement et https://payment.example.com/api, puis cliquez sur Create API resource.
Après avoir créé la ressource d'API, vous serez redirigé vers la page de détails. Nous pouvons la laisser telle quelle pour le moment.
Cliquez sur Applications dans la barre latérale gauche et cliquez sur Create application. Dans la boîte de dialogue ouverte, trouvez la carte Machine-to-machine et cliquez sur Start building.
Entrez le nom de l'application, par exemple, Service de panier, et cliquez sur Create application. Un guide interactif vous sera présenté pour vous aider à configurer l'application. Vous pouvez suivre le guide pour comprendre l'utilisation de base, ou cliquer sur Finish and done pour le sauter.
Étant donné que les applications machine à machine sont supposées être sécurisées (par exemple, elles sont déployées dans un réseau privé), nous pouvons utiliser l'autorisation "client_credentials" d'OAuth 2.0 pour obtenir un token d'accès. Elle utilise l'authentification de base pour authentifier le client :
POST.Content-Type de la requête est application/x-www-form-urlencoded.Authorization, la valeur est Basic <base64(app_id:app_secret)>, où app_id et app_secret sont l'ID et le secret de l'application machine à machine respectivement. Vous pouvez les trouver sur la page des détails de l'application.grant_type=client_credentials&resource=https://payment.example.com/api.
grant_type=client_credentials : La valeur constante pour la concession "client_credentials".resource=https://payment.example.com/api : L'identifiant de l'API de la ressource d'API que le client souhaite accéder.scope=read:payment write:payment. Nous couvrirons les portées plus tard.Voici un exemple de la requête utilisant curl :
Un corps de réponse réussi serait comme :
Nous avons maintenant le token d'accès, et nous pouvons l'ajouter à l'en-tête Authorization de la requête à la ressource d'API. Par exemple, si nous voulons appeler l'API POST /payments du service de paiement, nous pouvons envoyer la demande suivante :
Vous remarquerez peut-être que le service de paiement doit valider le JWT en utilisant le jeu de JWK, et peut avoir un cache de jeu de JWK local pour éviter de récupérer le jeu de JWK de Logto à chaque fois. Heureusement, en raison de la popularité de JWT, il existe de nombreuses bibliothèques qui peuvent vous aider à atteindre cet objectif avec quelques lignes de code.
Ces bibliothèques sont généralement appelées "jose" (JavaScript Object Signing and Encryption) ou "jsonwebtoken". Par exemple, dans Node.js, nous pouvons utiliser jose pour valider le JWT :
Si la validation réussit, la variable payload sera la charge utile JWT décodée. Sinon, une erreur sera générée.
Nous avons maintenant réussi à sécuriser la communication entre le service de panier et le service de paiement. Cependant, le flux d'authentification ne garantit que le client est le véritable service de panier, mais ne garantit pas que le service de panier a quelconque permission pour effectuer des actions sur le service de paiement.
Disons que nous voulons permettre au service de panier de créer des paiements, mais pas de lire les paiements.
Dans Logto, les "portées" et les "permissions" sont interchangeables. Allez à la page des détails de la ressource d'API du service de paiement, et naviguez vers l'onglet Permissions. Il devrait être vide maintenant. Cliquez sur Create permission, entrez read:payment comme nom de la permission, et entrez Lire les paiements comme description de la permission. Puis cliquez sur Create permission.
Répétez les étapes ci-dessus pour créer une autre permission avec le nom write:payment et la description Créer des paiements.
Un rôle est un groupe de permissions. Dans Logto, les applications machine à machine peuvent se voir attribuer des rôles pour accorder des permissions. Cliquez sur "Roles" dans la barre latérale gauche, et cliquez sur Create role.
checkout comme nom du rôle, et entrez Service de paiement comme description du rôle.write:payment.


En plus des paramètres du corps de la requête que nous avons mentionnés dans Demander un token d'accès, nous pouvons également spécifier les portées dans le corps de la requête. Par exemple, si nous voulons demander la permission write:payment, nous pouvons envoyer la requête suivante :
Pour demander plusieurs portées, vous pouvez les séparer par des espaces. Par exemple, scope=write:payment read:payment.
Si une action nécessite la permission write:payment dans le service de paiement, nous pouvons valider les portées en vérifiant que la revendication scope de la charge utile JWT :
Si vous souhaitez protéger l'accès au service de panier, vous pouvez également appliquer le même flux d'authentification. Cette fois, le service de panier est la ressource d'API, et le client est un autre service qui doit accéder.
Avec Logto, vos ressources d'API sont sécurisées avec OAuth 2.0 et JWT, et vous pouvez suivre le principe de privilège minimum en appliquant le contrôle d'accès basé sur les rôles. De plus, vous pouvez également utiliser Logto pour gérer vos utilisateurs et leurs permissions, et même vous intégrer à des fournisseurs d'identité tiers.