web-dev-qa-db-fra.com

Système d'autorisation et d'authentification pour microservices et consommateurs

Nous prévoyons de transformer notre système d'entreprise en un système basé sur les micro-services. Ces micro-services seront utilisés par nos propres applications internes à l'entreprise et par des partenaires tiers si nécessaire. Un pour la réservation, un pour les produits, etc.

Nous ne savons pas comment gérer les rôles et les étendues. L'idée est de créer 3 rôles d'utilisateur de base tels que les administrateurs, les agents et les utilisateurs finaux et de laisser les applications grand public affiner les portées si nécessaire.

  • Admins peut créer, mettre à jour, lire et supprimer toutes les ressources par défaut (pour leur entreprise).
  • Les agents peuvent créer, mettre à jour et lire des données pour leur entreprise.
  • tilisateurs finaux peut créer, mettre à jour, supprimer et lire des données, mais ne peut pas accéder aux mêmes points de terminaison que les agents ou les administrateurs. Ils pourront également créer ou modifier des données, mais pas au même niveau que les agents ou les administrateurs. Par exemple, les utilisateurs finaux peuvent mettre à jour ou lire leurs informations de compte, tout comme l'agent pourra le faire pour eux, mais ils ne peuvent pas voir ou mettre à jour les notes d'administration.

Supposons que les agents par défaut puissent créer, lire et mettre à jour chaque ressource pour leur entreprise et que c'est leur portée maximale qui peut être demandée pour leur jeton/session, mais les développeurs de l'application client (consommateur API) ont décidé qu'un de leurs agents peut lire et créer uniquement certaines ressources.

Est-il préférable de gérer cela dans notre sécurité interne et de les laisser écrire ces données dans notre base de données, ou de laisser les clients gérer cela en interne en demandant un jeton avec une portée moindre, et de les laisser écrire quel agent aura quelle étendue dans leur base de données ? De cette façon, nous n'aurions à suivre que les portées de jetons.

L'inconvénient est que notre équipe devra également créer des mécanismes d'accès affinés dans nos applications internes.

Avec cette façon de penser, les micro-services et leur système d'autorisation ne devraient pas être dérangés par les besoins des clients, car ils ne sont que des consommateurs et ne font pas partie du système (même si certains de ces consommateurs sont nos propres applications internes)?

Cette délégation est-elle une bonne approche?

15
Robert

L'authentification et l'autorisation sont toujours de bons sujets

Je vais essayer de vous expliquer comment nous traitons les autorisations dans le service multi-locataire actuel que je travaille. L'authentification et l'autorisation sont basées sur des jetons, en utilisant la norme ouverte JSON Web Token. Le service expose une REST accessible à tout type de client (applications Web, mobiles et de bureau). Lorsqu'un utilisateur est authentifié avec succès, le service fournit un jeton d'accès qui doit être envoyé sur chaque demande au serveur.

Permettez-moi donc de présenter quelques concepts que nous utilisons en fonction de la façon dont nous percevons et traitons les données sur l'application serveur.

Ressource: Il s'agit de toute unité ou groupe de données auquel un client peut accéder via le service. À toutes les ressources que nous voulons contrôler, nous attribuons un seul nom. Par exemple, ayant les prochaines règles de point de terminaison, nous pouvons les nommer comme suit:

product

/products
/products/:id

payment

/payments/
/payments/:id

order

/orders
/orders/:id
/orders/:id/products
/orders/:id/products/:id

Disons que jusqu'à présent, nous avons trois ressources dans notre service; product, payment et order.

Action: C'est une opération qui peut être effectuée sur une ressource, comme, lire, créer, mettre à jour, supprimer, etc. Il n'est pas nécessaire d'être juste les opérations CRUD classiques, vous pouvez avoir une action nommé follow, par exemple, si vous souhaitez exposer un service qui propage une sorte d'informations à l'aide de WebSockets.

Capacité: La possibilité d'effectuer un action sur un resource. Par exemple; lire des produits, créer des produits, etc. Il s'agit essentiellement d'une paire ressource/action. Mais vous pouvez également y ajouter un nom et une description.

Rôle: Un ensemble de capacités qu'un utilisateur peut posséder. Par exemple, un rôle Cashier pourrait avoir les capacités "lire le paiement", "créer un paiement" ou un rôle Seller peut avoir le capacités "lire le produit", "lire la commande", "mettre à jour la commande", "supprimer la commande".

Enfin, un utilisateur peut se voir attribuer différents rôles.


Explication

Comme je l'ai déjà dit, nous utilisons le jeton Web JSON et les capacités qu'un utilisateur possède sont déclarées dans la charge utile du jeton. Supposons donc que nous ayons un utilisateur avec les rôles de caissier et de vendeur en même temps, pour un petit magasin de détail. La charge utile ressemblera à ceci:

{
    "scopes": {
        "payment": ["read", "create"],
        "order": ["read", "create", "update", "delete"]
    }
}

Comme vous pouvez le voir dans la revendication scopes, nous ne spécifions pas le nom des rôles (caissier, vendeur), mais uniquement les ressources et les actions impliquées sont spécifiées. Lorsqu'un client envoie une demande à un point de terminaison, le service doit vérifier si le jeton d'accès contient la ressource et l'action requises. Par exemple, une demande GET au point de terminaison /payments/88 réussira, mais une demande DELETE au même point de terminaison doit échouer.


  • Comment grouper et nommer les ressources et comment définir et nommer les actions et capacités sera une décision prise par les développeurs.

  • Quels sont les rôles et quelles capacités auront ces rôles, sont les décisions prises par les clients.


Bien sûr, vous devez ajouter des propriétés supplémentaires à la charge utile afin d'identifier l'utilisateur et le client (locataire) qui a émis le jeton.

{
    "scopes": {
        ...
    },
    "tenant": "acme",
    "user":"coyote"
}

Avec cette méthode, vous pouvez affiner l'accès de n'importe quel compte d'utilisateur à votre service. Et le plus important, vous n'avez pas à créer divers rôles prédéfinis et statiques, comme Admin, Agents et Utilisateurs finaux comme vous le faites remarquer dans votre question. Un super utilisateur sera un utilisateur possédant un role avec tous les resources et actions du service qui lui est assigné.

Maintenant, que se passe-t-il s'il y a 100 ressources et que nous voulons un rôle qui donne accès à toutes ou presque toutes?. Notre charge utile symbolique serait énorme. Cela est résolu en imbriquant les ressources et en ajoutant simplement la ressource parent dans la portée du jeton d'accès.


L'autorisation est un sujet complexe qui doit être traité en fonction des besoins de chaque application.

14
miso

Je pense que quoi qu'il en soit, vous souhaiterez que vos services acceptent un jeton d'authentification fourni par un service d'authentification que vous écrivez pour valider les utilisateurs. Il s'agit de la manière la plus simple/sécurisée d'empêcher une mauvaise utilisation de vos microservices. De plus, en général, si vous voulez qu'un client ait une bonne expérience, vous devez implémenter vous-même les fonctionnalités critiques et tester soigneusement pour vous assurer que les fonctionnalités que vous proposez sont bien implémentées.

Étant donné que tous les appelants doivent fournir à vos microservices la preuve qu'ils ont été authentifiés, vous pouvez également lier des autorisations à cette authentification. Si vous donnez la possibilité de lier un utilisateur à un groupe d'accès arbitraire (ou à des groupes si vous voulez avoir de la fantaisie, bien que les autorisations d'ajouter par rapport à soustraire soient plus difficiles à traiter ici.), Il y aura moins de questions provenant de vos clients sur la raison pour laquelle l'utilisateur x a pu effectuer une opération indésirable. Dans tous les cas, quelqu'un doit faire une vérification de la liste d'accès pour chaque service, il peut donc tout aussi bien être vous. C'est quelque chose qui se coderait très facilement au début de tous les services (if ( !TokenAuthorized(this.ServiceName, this.token) { Raise error }) Autant le faire et suivre soi-même les groupes d'utilisateurs. Il est vrai que vous devrez disposer d'un gestionnaire de groupes d'autorisations et l'intégrer dans l'interface utilisateur de gestion des utilisateurs (utiliser les groupes existants/créer un nouveau groupe pour les autorisations des utilisateurs) .Listez définitivement les utilisateurs liés à un groupe lorsque vous modifiez la définition, pour éviter toute confusion. . Mais ce n'est pas un travail difficile. Il suffit d'avoir des métadonnées pour tous les services et de lier la recherche du mappage entre le groupe et le service à la gestion des jetons d'authentification.

Ok, il y a donc pas mal de détails, mais chacun de vos clients qui veulent cette fonctionnalité devra le coder dans tous les cas, et si vous prenez en charge les autorisations utilisateur à trois niveaux, vous pouvez tout aussi bien l'étendre à l'accès par utilisateur groupes. Une intersection logique entre les autorisations de groupe de base et les autorisations spécifiques à l'utilisateur serait probablement la bonne agrégation, mais si vous voulez pouvoir ajouter et retirer des autorisations de base, des autorisations de base Admin, Agent, Utilisateur final, vous devrez le faire le drapeau à trois états usuel dans les groupes d'autorisations: Ajouter une autorisation, Refuser l'autorisation, Autorisation par défaut et combiner les autorisations de manière appropriée.

(Remarque: tout cela devrait se produire sur quelque chose comme SSL ou même SSL bidirectionnel si vous êtes préoccupé par la sécurité des deux extrémités de la conversation. Si vous "divulguez" ces jetons à un attaquant, il est comme s'il " d a craqué un mot de passe.)

3
BenPen

À mon avis, vous avez deux choix ici.

  • Si vous avez juste besoin d'avoir un accès configurable à essentiellement la même application, demandez aux services de vérifier les autorisations et donnez à vos clients une interface qui leur permet de modifier les autorisations accordées à chaque rôle. Cela permet à la plupart des utilisateurs d'utiliser la configuration de rôle par défaut, que les clients "à problème" peuvent modifier les rôles ou créer de nouveaux pour répondre à leurs besoins.

  • Si vos clients développent leurs propres applications, ils doivent introduire leur propre API intermédiaire. Qui se connecte au vôtre en tant qu'administrateur, mais vérifie la demande entrante par rapport à ses propres exigences d'authentification personnalisées avant d'appeler vos services

1
Ewan

Ici, il y a aussi une réponse courte. Vous devez implémenter toutes les fonctionnalités de base que vous souhaitez offrir vous-même à vos "clients". Il semble problématique que les clients ajoutent eux-mêmes un comportement fondamental comme les autorisations des utilisateurs, car vous effectuez déjà l'authentification des utilisateurs; si vous laissez le soin au client de l'implémenter, vous pouvez finir par "prendre en charge" plusieurs implémentations du même code d'autorisations. Même si vous ne le "possédez pas", il y aura des bogues dans leur code et vous voulez que vos clients aient les fonctionnalités qu'ils attendaient, dans des limites raisonnables, donc vous soutenez la résolution des problèmes rencontrés par un client. Prendre en charge plusieurs bases de code n'est pas amusant.

1
BenPen

Considérations de sécurité

Si je comprends bien votre conception, vous avez l'intention de déléguer certains mécanismes de contrôle d'accès aux ressources du côté client, c'est-à-dire qu'une application consommatrice réduit les éléments qu'un utilisateur peut voir. Votre hypothèse est:

les micro-services et leur système d'autorisation ne devraient pas être dérangés par les besoins des clients, car ils ne sont que des consommateurs et ne font pas partie du système

Je vois ici deux problèmes sérieux pour les affaires sérieuses:

  • Que se passe-t-il si un utilisateur voyou (par exemple dans l'une des usines de votre partenaire) procède à une ingénierie inverse de l'application cliente et découvre l'API, contourne les restrictions que son entreprise a imposées au client et utilise ces informations pour nuire à votre entreprise? Votre entreprise réclamera des dommages-intérêts, mais la société partenaire affirmera que vous n'avez pas donné les moyens de protéger suffisamment vos données.
  • Habituellement, ce n'est qu'une question de temps que les données sensibles soient utilisées à mauvais escient (ou l'audit découvrira le risque) et votre direction finira par demander un contrôle plus strict de ces données.

C'est pourquoi je vous conseille d'anticiper de tels événements et de répondre aux demandes d'autorisation. Vous êtes dans une phase de réingénierie précoce et il sera beaucoup plus facile de les prendre en compte dans votre architecture (même si vous ne les implémentez pas tous) que plus tard.

Si vous poursuivez votre poste actuel, consultez au moins votre responsable de la sécurité des informations.

Comment l'implémenter

Vous avez l'astuce:

De cette façon, nous n'aurions à suivre que les portées de jetons.

Ok, vous avez l'intention d'utiliser des jetons généraux choisis par le client. Encore une faiblesse à mes yeux, car certains clients peuvent être hors de votre contrôle.

Je ne sais pas si vous utilisez déjà JWT ou si vous utilisez d'autres techniques. Mais si vous utilisez JWT, vous pourriez avoir un jeton d'identité qui porte l'identité de l'utilisateur (et même un deuxième jeton qui identifie en toute sécurité l'application d'origine, ce qui pourrait vous permettre de différencier le niveau de confiance entre les clients internes et les clients externes ).

Comme vous avez l'intention d'opter pour une architecture de microservice, je voudrais suggérer de faire la différence entre la gestion des utilisateurs et le processus d'authentification (qui devrait fonctionner comme un service dédié) et le contrôle d'accès (qui est spécifique à chaque microservice, et doit être géré localement par chacun d'eux). Bien sûr, certains clients d'administration devraient donner un aperçu complet de plusieurs services, pour en faciliter l'utilisation).

1
Christophe