Question Authentification RESTful


Que signifie l'authentification RESTful et comment cela fonctionne-t-il? Je ne peux pas trouver un bon aperçu sur Google. Ma seule compréhension est que vous passez la clé de session (rappel) dans l'URL, mais cela pourrait être horriblement faux.


664
2017-11-26 01:47


origine


Réponses:


Comment gérer l'authentification dans une architecture RESTful Client-Server est un sujet de débat.

Généralement, cela peut être réalisé dans le monde SOA sur HTTP via:

  • Authentification de base HTTP sur HTTPS;
  • Cookies et gestion de session
  • Jeton dans les en-têtes HTTP (par ex. OAuth 2,0);
  • Interroger l'authentification avec des paramètres de signature supplémentaires.

Vous devrez adapter, ou même mieux mélanger ces techniques, pour correspondre au mieux à votre architecture logicielle.

Chaque schéma d'authentification a ses propres PRO et CON, selon le but de votre politique de sécurité et de votre architecture logicielle.

Authentification de base HTTP via HTTPS

Cette première solution, basée sur le protocole HTTPS standard, est utilisée par la plupart des services Web.

GET /spec.html HTTP/1.1
Host: www.example.org
Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==

Il est facile à implémenter, disponible par défaut sur tous les navigateurs, mais présente des inconvénients connus, comme la fenêtre d'authentification affreuse affichée sur le navigateur, qui persistera (il n'y a pas de fonctionnalité similaire à LogOut), un processeur additionnel côté serveur consommation, et le fait que le nom d'utilisateur et le mot de passe sont transmis (via HTTPS) dans le serveur (il devrait être plus sécurisé de laisser le mot de passe uniquement du côté client, lors de la saisie au clavier Serveur).

Nous pouvons utiliser Authentification Digest, mais il nécessite également HTTPS, car il est vulnérable à MiM ou Rejouer attaques, et est spécifique à HTTP.

Session via des cookies

Pour être honnête, une session gérée sur le serveur n'est pas vraiment apatride.

Une possibilité pourrait être de maintenir toutes les données dans le contenu des cookies. Et, de par sa conception, le cookie est géré côté serveur (le client n'essaie même pas d'interpréter ces données de cookie: il les restitue au serveur à chaque requête successive). Mais ces données de cookie sont des données d'état d'application, donc le client devrait les gérer, pas le serveur, dans un monde sans état.

GET /spec.html HTTP/1.1
Host: www.example.org
Cookie: theme=light; sessionToken=abc123

La technique de cookie elle-même est liée à HTTP, donc ce n'est pas vraiment RESTful, ce qui devrait être indépendant du protocole, à mon humble avis. Il est vulnérable à MiM ou Rejouer attaques.

Accordé via Token (OAuth2)

Une alternative consiste à placer un jeton dans les en-têtes HTTP afin que la requête soit authentifiée. C'est quoi OAuth 2.0 fait, par exemple. Voir le RFC 6749:

 GET /resource/1 HTTP/1.1
 Host: example.com
 Authorization: Bearer mF_9.B5f-4.1JqM

En bref, cela ressemble beaucoup à un cookie et souffre des mêmes problèmes: non apatride, s'appuyant sur les détails de transmission HTTP, et soumis à beaucoup de faiblesses de sécurité - y compris MiM et Replay - ne doit donc être utilisé que via HTTPS.

Authentification de requête

L'authentification de requête consiste à signer chaque requête RESTful via des paramètres supplémentaires sur l'URI. Voir cet article de référence.

Il a été défini comme tel dans cet article:

Toutes les requêtes REST doivent être authentifiées en signant les paramètres de requête   triés en minuscules, ordre alphabétique en utilisant les informations d'identification privées   comme le jeton de signature. La signature doit avoir lieu avant que l'URL ne code   chaîne de requête.

Cette technique est peut-être la plus compatible avec une architecture sans état, et peut également être implémentée avec une gestion de session légère (en utilisant des sessions en mémoire au lieu de la persistance DB).

Par exemple, voici un exemple d'URI générique à partir du lien ci-dessus:

GET /object?apiKey=Qwerty2010

devrait être transmis en tant que tel:

GET /object?timestamp=1261496500&apiKey=Qwerty2010&signature=abcdef0123456789

La chaîne en cours de signature est /object?apikey=Qwerty2010&timestamp=1261496500 et la signature est le hachage SHA256 de cette chaîne en utilisant le composant privé de la clé API.

La mise en cache des données côté serveur peut toujours être disponible. Par exemple, dans notre cadre, nous mettons en cache les réponses au niveau SQL, pas au niveau de l'URI. L'ajout de ce paramètre supplémentaire ne casse donc pas le mécanisme de cache.

Voir Cet article Pour plus d'informations sur l'authentification RESTful dans notre infrastructure ORM / SOA / MVC client-serveur, basée sur JSON et REST. Puisque nous permettons la communication non seulement sur HTTP / 1.1, mais aussi sur les pipes ou les messages GDI (localement), nous avons essayé d'implémenter un vrai pattern d'authentification RESTful, et ne pas dépendre de la spécificité HTTP (comme header ou cookies).

En pratique, le prochain Authentification de jetons MAC pour OAuth 2.0 peut être une énorme amélioration par rapport au système actuel "Granted by Token". Mais ceci est encore un travail en cours, et est lié à la transmission HTTP.

Conclusion

Il vaut la peine de conclure que REST n'est pas seulement basé sur HTTP, même si, en pratique, il est principalement implémenté sur HTTP. REST peut utiliser d'autres couches de communication. Ainsi, une authentification RESTful n'est pas simplement un synonyme d'authentification HTTP, quelle que soit la réponse de Google. Il ne devrait même pas du tout utiliser le mécanisme HTTP, mais doit être extrait de la couche de communication.


522
2017-08-23 09:29



Je doute que les gens qui criaient avec enthousiasme "Authentification HTTP" aient jamais essayé de faire une application basée sur un navigateur (au lieu d'un service web de machine à machine) avec REST (sans vouloir offenser - je ne pense pas qu'ils aient jamais fait face aux complications) .

Les problèmes que j'ai rencontrés lors de l'utilisation de l'authentification HTTP sur les services RESTful qui produisent des pages HTML à afficher dans un navigateur sont les suivants:

  • l'utilisateur obtient généralement une boîte de connexion faite par navigateur moche, qui est très hostile aux utilisateurs. vous ne pouvez pas ajouter de récupération de mot de passe, de boîtes d'aide, etc.
  • se déconnecter ou se connecter sous un nom différent est un problème - les navigateurs continueront à envoyer des informations d'authentification sur le site jusqu'à ce que vous fermiez la fenêtre
  • les délais d'attente sont difficiles

Un article très perspicace qui aborde ces point par point est ici, mais cela entraîne un lot du hackery javascript spécifique au navigateur, solutions de contournement pour les solutions de contournement, et cetera. En tant que tel, il n'est pas non plus compatible avec les versions antérieures, ce qui nécessitera une maintenance constante au fur et à mesure que de nouveaux navigateurs seront publiés. Je ne considère pas cette conception propre et claire, plus je pense que c'est beaucoup de travail supplémentaire et mal de tête juste pour que je puisse montrer mon badge REST avec enthousiasme à mes amis.

Je crois que les cookies sont la solution. Mais attendez, les cookies sont mauvais, n'est-ce pas? Non, ils ne le sont pas, la façon dont les cookies sont souvent utilisés est mauvaise. Un cookie lui-même n'est qu'une partie des informations côté client, tout comme les informations d'authentification HTTP que le navigateur suivra pendant que vous naviguerez. Et cette information côté client est envoyée au serveur à chaque requête, exactement comme les informations d'authentification HTTP. Conceptuellement, la seule différence est que contenu de cette partie de l'état côté client peut être déterminée par le serveur dans le cadre de sa réponse.

En faisant des sessions une ressource RESTful avec juste les règles suivantes:

  • UNE session mappe une clé sur un identifiant utilisateur (et éventuellement un horodatage de dernière action pour les délais d'attente)
  • Si un session existe, cela signifie que la clé est valide.
  • Login signifie POSTing to / sessions, une nouvelle clé est définie en tant que cookie
  • Déconnexion signifie DELETEing / sessions / {key} (avec POST surchargé, rappelez-vous, nous sommes un navigateur, et HTML 5 est un long chemin à parcourir)
  • L'authentification est effectuée en envoyant la clé en tant que cookie à chaque requête et en vérifiant si la session existe et est valide

La seule différence avec l'authentification HTTP est que la clé d'authentification est générée par le serveur et envoyée au client qui la renvoie, au lieu que le client la calcule à partir des informations d'identification saisies.

converter42 ajoute que lorsque vous utilisez https (ce que nous devrions faire), il est important que le cookie ait son drapeau de sécurité afin que les informations d'authentification ne soient jamais envoyées via une connexion non sécurisée. Bon point, je ne l'avais pas vu moi-même.

Je pense que c'est une solution suffisante qui fonctionne bien, mais je dois admettre que je ne suis pas assez expert en sécurité pour identifier les failles potentielles dans ce système - tout ce que je sais c'est que des centaines d'applications web non-RESTful utilisent essentiellement le même protocole de connexion ($ _SESSION inphp, HttpSession dans Java EE, etc.). Le contenu de l'en-tête de cookie est simplement utilisé pour adresser une ressource côté serveur, tout comme une langue d'acceptation peut être utilisée pour accéder à des ressources de traduction, etc. Je pense que c'est la même chose, mais peut-être que d'autres ne le font pas? Qu'en penses-tu, les gars?


403
2017-07-16 07:39



Assez déjà est dit sur ce sujet par de bonnes personnes ici. Mais voici mes 2 cents.

Il y a 2 modes d'interaction:

  1. humain à machine (HTM)
  2. machine-à-machine (MTM)

La machine étant le dénominateur commun, exprimée en API REST, et les acteurs / clients étant soit les humains, soit les machines.

Maintenant, dans une architecture véritablement RESTful, le concept d'apatridie implique que tous les états d'application pertinents (c'est-à-dire les états côté client) doivent être fournis avec chaque requête. Par pertinence, cela signifie que tout ce qui est requis par l'API REST pour traiter la demande et servir une réponse appropriée.

Lorsque nous considérons cela dans le contexte des applications inter-machines, "basé sur un navigateur" comme Skrebbel le souligne ci-dessus, cela signifie que l'application (web) exécutée dans le navigateur devra envoyer son état et des informations pertinentes à chaque requête. fait aux API REST back end.

Considérez ceci: Vous avez une plate-forme de données / informations exposée en tant qu'ensemble d'API REST. Peut-être avez-vous une plateforme de BI en libre-service qui gère tous les cubes de données. Mais vous voulez que vos clients (humains) y accèdent via (1) une application web, (2) une application mobile, et (3) une application tierce. En fin de compte, même la chaîne de MTM conduit jusqu'à HTM - droit. Les utilisateurs humains restent donc au sommet de la chaîne d'information.

Dans les 2 premiers cas, vous avez besoin d'une interaction homme-machine, l'information étant réellement consommée par un utilisateur humain. Dans le dernier cas, vous avez un programme machine consommant les API REST.

Le concept d'authentification s'applique à tous les niveaux. Comment allez-vous concevoir ceci pour que vos API REST soient accessibles de manière uniforme et sécurisée? La façon dont je vois cela, il y a 2 façons:

Way-1:

  1. Il n'y a pas de login pour commencer. Chaque demande effectue la connexion
  2. Le client envoie ses paramètres d'identification + la demande spécifique paramètres avec chaque demande
  3. L'API REST les prend, se retourne, pique le magasin de l'utilisateur (quoi que ce soit) et confirme l'auth
  4. Si l'authentification est établie, traite la demande; sinon, nie avec le code d'état HTTP approprié
  5. Répétez les étapes ci-dessus pour chaque requête de toutes les API REST de votre catalogue

Way-2:

  1. Le client commence par une demande d'authentification
  2. Une API REST de connexion traitera toutes ces demandes
  3. Il prend dans les paramètres auth (clé API, uid / pwd ou quoi que vous choisissez) et vérifie auth par rapport au magasin de l'utilisateur (LDAP, AD ou MySQL DB etc.)
  4. Si elle est vérifiée, crée un jeton d'authentification et le remet au client / appelant
  5. L'appelant envoie alors ce jeton auth + demande des paramètres spécifiques avec toutes les requêtes suivantes vers d'autres API REST métier, jusqu'à la déconnexion ou jusqu'à l'expiration du bail

De toute évidence, dans Way-2, les API REST auront besoin d'un moyen de reconnaître et d'approuver le jeton comme valide. L'API de connexion a effectué la vérification d'authentification et, par conséquent, cette clé de validation doit être approuvée par les autres API REST de votre catalogue.

Cela signifie bien entendu que la clé / jeton auth devra être stocké et partagé entre les API REST. Ce référentiel de jetons de confiance partagé peut être local / fédéré, ce qui permet aux API REST d'autres organisations de se faire mutuellement confiance.

Mais je m'égare.

Le point est, un «état» (sur l'état authentifié du client) doit être maintenu et partagé afin que toutes les API REST puissent créer un cercle de confiance. Si nous ne le faisons pas, ce qui est le Way-1, nous devons accepter qu'un acte d'authentification doit être effectué pour toutes les demandes qui arrivent.

L'authentification est un processus gourmand en ressources. Imaginez l'exécution de requêtes SQL, pour chaque requête entrante, par rapport à votre magasin d'utilisateurs pour vérifier la correspondance de uid / pwd. Ou, pour crypter et effectuer des concordances de hachage (le style AWS). Et architecturalement, chaque API REST devra effectuer cela, je suppose, en utilisant un service de connexion back end commun. Parce que, si vous ne le faites pas, vous jetez le code d'autorisation partout. Un gros désordre.

Donc plus les couches, plus de latence.

Maintenant, prenez Way-1 et appliquez-vous à HTM. Est-ce que votre utilisateur (humain) se soucie vraiment si vous devez envoyer uid / pwd / hash ou quoi que ce soit à chaque demande? Non, tant que vous ne la dérangez pas en lançant la page auth / login toutes les secondes. Bonne chance d'avoir des clients si vous le faites. Donc, ce que vous allez faire est de stocker les informations de connexion quelque part sur le côté client, dans le navigateur, dès le début, et l'envoyer avec toutes les demandes effectuées. Pour l'utilisateur (humain), elle s'est déjà connectée et une "session" est disponible. Mais en réalité, elle est authentifiée à chaque demande.

Pareil avec Way-2. Votre utilisateur (humain) ne le remarquera jamais. Donc, pas de mal fait.

Et si nous appliquons Way-1 à MTM? Dans ce cas, puisque c'est une machine, nous pouvons ennuyer le gars en lui demandant de soumettre des informations d'authentification à chaque requête. Tout le monde s'en fout! L'exécution de Way-2 sur MTM n'évoquera aucune réaction particulière; C'est une machine foutue. Ça pourrait en faire moins attention!

Donc vraiment, la question est ce qui convient à votre besoin. L'apatridie a un prix à payer. Payer le prix et passer à autre chose. Si vous voulez être un puriste, alors payez le prix pour cela aussi, et continuez.

En fin de compte, les philosophies n'ont pas d'importance. Ce qui importe vraiment, c'est la découverte d'informations, la présentation et l'expérience de consommation. Si les gens aiment vos API, vous avez fait votre travail.


128
2017-10-14 21:29



Voici une solution d'authentification RESTful vraiment et complètement:

  1. Créez une paire de clés publique / privée sur le serveur d'authentification.
  2. Distribuez la clé publique à tous les serveurs.
  3. Lorsqu'un client s'authentifie:

    3.1. émettre un jeton contenant les éléments suivants:

    • Date d'expiration
    • nom des utilisateurs (optionnel)
    • utilisateurs IP (optionnel)
    • hash d'un mot de passe (optionnel)

    3.2. Chiffrer le jeton avec la clé privée.

    3.3. Envoyez le jeton chiffré à l'utilisateur.

  4. Lorsque l'utilisateur accède à une API, il doit également transmettre son jeton d'authentification.

  5. Les serveurs peuvent vérifier que le jeton est valide en le décryptant à l'aide de la clé publique du serveur d'authentification.

C'est une authentification sans état / RESTful.

Notez que si un hash de mot de passe était inclus, l'utilisateur enverrait également le mot de passe non crypté avec le jeton d'authentification. Le serveur pouvait vérifier que le mot de passe correspondait au mot de passe utilisé pour créer le jeton d'authentification en comparant les hachages. Une connexion sécurisée utilisant quelque chose comme HTTPS serait nécessaire. Javascript du côté client pourrait gérer l'obtention du mot de passe de l'utilisateur et le stocker côté client, soit en mémoire ou dans un cookie, éventuellement crypté avec le serveur Publique clé.


46
2017-08-13 20:09



Pour être honnête avec vous, j'ai vu de bonnes réponses ici, mais quelque chose qui me dérange un peu, c'est quand quelqu'un va prendre l'ensemble du concept des Stateless à un extrême où cela devient dogmatique. Cela me rappelle ces vieux fans de Smalltalk qui ne voulaient que du pur OO et si quelque chose n'est pas un objet, alors vous vous trompez. Laisse-moi tranquille.

L'approche RESTful est censée vous faciliter la vie et réduire les frais généraux et les coûts des sessions, essayez de la suivre car c'est une bonne chose à faire, mais dès que vous suivez une discipline (n'importe quelle discipline / ligne directrice) jusqu'à l'extrême ne fournit plus l'avantage pour lequel il était destiné, alors vous le faites mal. Certaines des meilleures langues aujourd'hui ont à la fois, la programmation fonctionnelle et l'orientation de l'objet.

Si le moyen le plus simple de résoudre votre problème est de stocker la clé d'authentification dans un cookie et de l'envoyer sur l'en-tête HTTP, faites-le, n'en abusez pas. Rappelez-vous que les sessions sont mauvaises lorsqu'elles deviennent lourdes et grandes, si toute votre session consiste en une courte chaîne contenant une clé, alors quel est le problème?

Je suis ouvert à accepter les corrections dans les commentaires mais je ne vois tout simplement pas le point (jusqu'à présent) de rendre nos vies misérables simplement éviter de garder un grand dictionnaire de hachages dans notre serveur.


34
2018-03-26 23:13



Tout d'abord, un service Web RESTful est APATRIDE (ou en d'autres termes, SESSIONLESS). Par conséquent, un service RESTful n'a pas et ne devrait pas avoir un concept de session ou de cookies impliqués. La méthode d'authentification ou d'autorisation dans le service RESTful consiste à utiliser l'en-tête HTTP Authorization défini dans les spécifications HTTP RFC 2616. Chaque requête doit contenir l'en-tête HTTP Authorization et la demande doit être envoyée via une connexion HTTP (SSL). C'est la façon correcte de procéder à l'authentification et de vérifier l'autorisation des requêtes dans les services Web HTTP RESTful. J'ai implémenté un service Web RESTful pour l'application Cisco PRIME Performance Manager chez Cisco Systems. Et dans le cadre de ce service web, j'ai également mis en place une authentification / autorisation.

Rubens Gomes.


31
2017-11-26 03:06



Il ne s'agit certainement pas de "clés de session", car il est généralement utilisé pour se référer à l'authentification sans session qui est effectuée dans toutes les contraintes de REST. Chaque requête est auto-descriptive, elle contient suffisamment d'informations pour autoriser la requête par elle-même sans aucun état d'application côté serveur.

La façon la plus simple d'aborder cela est de commencer par les mécanismes d'authentification intégrés de HTTP dans RFC 2617.


21
2017-10-15 19:35



L'article "très perspicace" mentionné par @skrebel ( http://www.berenddeboer.net/rest/authentication.html ) discute d'une méthode d'authentification alambiquée mais vraiment cassée.

Vous pouvez essayer de visiter la page (qui est censée être visible seulement pour l'utilisateur authentifié) http://www.berenddeboer.net/rest/site/authenticated.html sans aucune identification de connexion.

(Désolé, je ne peux pas commenter la réponse.)

Je dirais que REST et l'authentification ne se mélangent tout simplement pas. REST signifie «sans état» mais «authentifié» est un état. Vous ne pouvez pas les avoir tous les deux au même niveau. Si vous êtes un défenseur de RESTful et désapprouvez les états, alors vous devez aller avec HTTPS (c'est-à-dire laisser le problème de sécurité à un autre niveau).


14
2018-01-19 06:45