Les meilleures pratiques pour l’authentification et l’autorisation dans Angular sans enfreindre les principes RESTful?

J’ai lu pas mal de discussions sur l’authentification et l’autorisation avec REST et Angular, mais je n’ai toujours pas l’impression d’avoir une bonne solution pour ce que j’espère faire. Pour certains antécédents, je prévois de créer une application dans AngularJS où je veux prendre en charge:

  1. Accès limité aux invités
  2. Accès basé sur des rôles à l’application une fois authentifié
  3. Authentification via des API

Tous les appels à l’API REST devront être effectués via SSL. J’aimerais créer l’application sans enfreindre les principes RESTful, à savoir ne pas conserver l’état de session stocké sur le serveur. Bien entendu, tout ce qui est fait vis-à-vis de l’autorisation du côté client doit être renforcé côté serveur. Comme nous avons besoin de passer l’état complet à chaque requête, je sais que je dois passer une sorte de jeton pour que le serveur principal recevant la demande REST puisse à la fois authentifier et autoriser l’appel.

Cela dit, ma principale question concerne l’authentification – quelles sont les meilleures pratiques ici? Il semble qu’il y ait beaucoup d’approches différentes discutées, en voici quelques unes:

  • http://broadcast.oreilly.com/2009/12/principles-for-standardized-rest-authentication.html
  • http://frederiknakstad.com/2013/01/21/authentication-in-single-page-applications-with-angular-js/
  • http://docs.aws.amazon.com/AmazonS3/latest/dev/RESTAuthentication.html

Il y avait une question similaire posée ( authentification de l’application des meilleures pratiques d’AngularJS ), mais à moins que je ne comprenne pas la réponse, cela semble impliquer qu’une session de serveur devrait être utilisée, ce qui enfreint les principes de RESTful.

Ma principale préoccupation avec Amazon AWS et l’article de George Reese est qu’il semble supposer que le consommateur est un programme plutôt qu’un utilisateur final. Un secret partagé peut être envoyé à un programmeur à l’avance, qui peut alors l’utiliser pour coder des appels ici. Ce n’est pas le cas ici – je dois appeler l’API REST à partir de l’application au nom de l’utilisateur.

Cette approche serait-elle suffisante? Disons que j’ai une ressource de session:

POST / api / session

Créer une nouvelle session pour un utilisateur

Pour créer une session, vous devez POST un object JSON contenant le “nom d’utilisateur” et le “mot de passe”.

{ "email" : "[email protected]", "password" : "password" } 

Exemple Curl

 curl -v -X POST --data '{"username":"[email protected]","password":"password"}' "https://app.example.com/api/session" --header "Content-Type:application/json" 

Réponse

 HTTP/1.1 201 Created { "session": { "id":"520138ccfa4634be08000000", "expires":"2014-03-20T17:56:28+0000" } } 

Codes de statut

  • 201 – Création, nouvelle session établie
  • 400 – Demande incorrecte, l’object JSON n’est pas valide ou les informations requirejses sont manquantes
  • 401 – Non autorisé, Vérifier la combinaison email / mot de passe
  • 403 – Accès refusé, compte désactivé ou licence invalide

Je laisse les détails de HATEOAS pour plus de clarté. Sur le backend, il y aurait une nouvelle clé de session de durée limitée créée et associée à l’utilisateur. Sur les requêtes suivantes, je pourrais passer ceci dans le cadre des en-têtes HTTP:

 Authorization: MyScheme 520138ccfa4634be08000000 

Les serveurs dorsaux seraient alors responsables de digérer ceci hors de la requête, en trouvant l’utilisateur associé et en appliquant les règles d’autorisation pour la demande. Il devrait probablement mettre à jour l’expiration de la session également.

Si tout cela se passe sur SSL, est-ce que je laisse la porte ouverte à toutes sortes d’attaques contre lesquelles je devrais protéger? Vous pouvez essayer de deviner les clés de session et les placer dans l’en-tête. Je suppose donc que je pourrais append un GUID d’utilisateur à la clé de session pour empêcher davantage les attaques par force brute.

Cela fait quelques années que j’ai programmé activement et je ne fais que revenir dans le swing ici. Je m’excuse si je suis obtus ou que je réinvente inutilement la roue, espérant simplement que mes idées seront transmises à la communauté en me basant sur mes lectures et voir si elles réussissent le test décisif.

Lorsque quelqu’un pose une question sur l’authentification REST, je m’en remets aux services Web d’Amazon et je suggère essentiellement de “faire cela”. Pourquoi? Car, du sharepoint vue de la «sagesse des foules», AWS résout le problème, est fortement utilisé, fortement analysé et approuvé par des personnes qui connaissent et se soucient beaucoup plus que la plupart des demandes sécurisées. Et la sécurité est un bon endroit pour “ne pas réinventer la roue”. En termes de “épaules pour se tenir”, vous pouvez faire pire que AWS.

À présent, AWS n’utilise pas de technique de jeton, mais utilise plutôt un hachage sécurisé basé sur des secrets partagés et la charge utile. C’est sans doute une implémentation plus compliquée (avec tous ses processus de normalisation, etc.).

Mais ça marche.

L’inconvénient est que votre application doit conserver le secret partagé des personnes (c.-à-d. Le mot de passe) et que le serveur doit également y avoir access en version texte brut. Cela signifie généralement que le mot de passe est stocké sous forme cryptée, puis déchiffré comme il convient. Et cela invite encore plus de complexité dans la gestion des clés et d’autres choses du côté du serveur par rapport à la technique de hachage sécurisée.

Le plus gros problème, bien sûr, avec toute technique de passage de jetons est les attaques de Man in the Middle et les attaques par rejeu. SSL les atténue généralement, naturellement.

Bien sûr, vous devriez également considérer la famille OAuth, qui a ses propres problèmes, notamment l’interopérabilité, mais si ce n’est pas un objective principal, les techniques sont certainement valables.

Pour votre application, le bail symbolique n’est pas une grosse affaire. Votre application devra toujours fonctionner dans les délais impartis ou être en mesure de la renouveler. Pour ce faire, il faudra soit conserver les informations d’identification de l’utilisateur, soit les demander à nouveau. Il suffit de traiter le jeton comme une ressource de première classe, comme toute autre chose. Si possible, essayez d’associer d’autres informations à la demande et regroupez-les dans le jeton (signature du navigateur, adresse IP), juste pour appliquer une certaine localité.

Vous êtes toujours ouvert aux problèmes de rediffusion (potentiels), où la même demande peut être envoyée deux fois. Avec une implémentation de hachage classique, un horodatage fait partie de la signature, ce qui peut encadrer la durée de vie de la demande. C’est résolu différemment dans ce cas. Par exemple, chaque demande peut être envoyée avec un ID de série ou un GUID et vous pouvez enregistrer que la demande a déjà été lue pour éviter qu’elle ne se reproduise. Différentes techniques pour cela.

Voici un article incroyable sur l’authentification et les services de connexion construits avec angular.

https://medium.com/opinionated-angularjs/7bbf0346acec

Cette question SO fait un bon travail en résumant ma compréhension de REST

Les sessions violent-elles vraiment le RESTfulness?

Si vous stockez un jeton dans une session, vous créez toujours un état côté serveur (il s’agit d’un problème car cette session est généralement stockée sur un seul serveur, ce qui peut être atténué par des sessions adhésives ou d’autres solutions).

J’aimerais savoir quel est votre raisonnement pour créer un service RESTful parce que ce n’est peut-être pas vraiment une préoccupation majeure.

Si vous envoyez un jeton dans le corps avec chaque requête (puisque tout est chiffré avec SSL, cela est correct), vous pouvez avoir un nombre illimité de serveurs (équilibrés en charge) qui traitent la requête sans aucune connaissance préalable de l’état.

En résumé, je pense que viser les implémentations RESTful est un bon objective, mais le fait d’être purement sans état crée une complexité supplémentaire en matière d’authentification et de vérification des permissions.

Jusqu’à présent, j’ai commencé à construire mes back-end en pensant à REST, en créant des URI qui ont du sens et utilisent les verbes HTTP corrects, mais utilisent toujours un jeton dans une session pour simplifier l’authentification (sans plusieurs serveurs).

J’ai lu les liens que vous avez postés, celui d’AngularJS semble se concentrer uniquement sur le client et ne semble pas adresser explicitement le serveur dans cet article, il fait un lien vers un autre (je ne suis pas un utilisateur Node alors pardonnez-moi si mon interprétation est fausse ici) mais il semble que le serveur compte sur le client pour lui indiquer le niveau d’autorisation dont il dispose, ce qui n’est clairement pas une bonne idée.