Modèle de connexion de l'API REST

181

Je crée une API REST, en suivant de près les suggestions d'apigee, en utilisant des noms et non des verbes, une version de l'API intégrée à l'url, deux chemins d'API par collection, l'utilisation de GET POST PUT DELETE, etc.

Je travaille sur le système de connexion, mais je ne suis pas sûr de la méthode REST appropriée pour connecter les utilisateurs. Je ne travaille pas sur la sécurité à ce stade, juste le schéma de connexion ou le flux. (Plus tard, nous ajouterons oAuth en 2 étapes, avec un HMAC, etc.)

Options possibles

  • Un POST à ​​quelque chose comme https://api...com/v1/login.json
  • Un PUT à quelque chose comme https://api...com/v1/users.json
  • Quelque chose que je n'ai pas pensé de ...

Quel est le style REST approprié pour la connexion des utilisateurs?

Scott Roepnack
la source
9
C'est le format de la réponse. .json indique au serveur de répondre avec json, .xml indique au serveur de répondre au format xml. Plutôt que d'en faire un paramètre facultatif derrière le?. blog.apigee.com/detail/…
Scott Roepnack
28
Jamais vu la négociation de contenu effectuée sur l'URL, uniquement dans les en-têtes. Sur l'URL, cela signifie que vous perdez les avantages de la mise en cache et plus encore.
Oded
10
@ScottRoepnack alors vous devriez considérer l' Accepten-tête HTTP.
Alessandro Vendruscolo
2
@Oded Si vous utilisiez un en- Accepttête, vous en auriez également un Vary: Accept, donc la mise en cache ne serait pas affectée. Conneg en extension a déjà été discuté ; Je suis cependant d'accord avec la réponse de Shonzilla.
cmbuckley
2
@Oded - je ne comprends pas. pourquoi perdriez-vous l'avantage de la mise en cache si vous spécifiez le type de contenu dans l'URL (soit en tant que suffixe .json dans le chemin de la requête, soit en tant que paramètre de requête type = json)? Et qui est «vous» dans ce cas? Quelle est la personne qui perd les avantages de la mise en cache? il me semble que les résultats de toute requête peuvent être mis en cache quel que soit le chemin de la requête ou les paramètres.
Cheeso

Réponses:

138

Principled Design of the Modern Web Architecture par Roy T. Fielding et Richard N. Taylor , c'est-à-dire que la séquence d'œuvres de toute la terminologie REST provient, contient la définition de l'interaction client-serveur:

Toutes les interactions REST sont sans état . Autrement dit, chaque demande contient toutes les informations nécessaires pour qu'un connecteur comprenne la demande, indépendamment des demandes qui peuvent l'avoir précédée .

Cette restriction remplit quatre fonctions, la 1ère et la 3ème sont importantes dans ce cas particulier:

  • 1er : il supprime tout besoin pour les connecteurs de conserver l'état de l'application entre les requêtes , réduisant ainsi la consommation de ressources physiques et améliorant l'évolutivité;
  • 3 ° : il permet à un intermédiaire de visualiser et de comprendre une demande de manière isolée , ce qui peut être nécessaire lorsque les services sont réorganisés dynamiquement;

Et maintenant, revenons à votre cas de sécurité. Chaque demande doit contenir toutes les informations requises et l'autorisation / l'authentification ne fait pas exception. Comment y parvenir? Envoyez littéralement toutes les informations requises par fil à chaque demande.

Le code d'authentification de message basé sur le hachage ou HMAC est l'un des exemples de cette méthode . En pratique, cela signifie ajouter un code de hachage du message actuel à chaque requête. Code de hachage calculé par la fonction de hachage cryptographique en combinaison avec une clé cryptographique secrète . La fonction de hachage cryptographique est soit prédéfinie, soit intégrée à la conception REST de code à la demande (par exemple JavaScript). La clé cryptographique secrète doit être fournie par le serveur au client en tant que ressource, et le client l'utilise pour calculer le code de hachage pour chaque demande.

Il existe de nombreux exemples d' implémentations HMAC , mais j'aimerais que vous prêtiez attention aux trois suivants:

Comment ça marche en pratique

Si le client connaît la clé secrète, il est prêt à fonctionner avec des ressources. Sinon, il sera temporairement redirigé (code de statut 307 Redirection temporaire) pour autoriser et obtenir la clé secrète, puis redirigé vers la ressource d'origine. Dans ce cas, il n'est pas nécessaire de savoir à l'avance (c'est-à-dire en dur quelque part) quelle est l'URL pour autoriser le client , et il est possible d'ajuster ce schéma avec le temps.

J'espère que cela vous aidera à trouver la bonne solution!

Akim
la source
23
Un MAC est destiné à prouver l'authenticité du message et à se protéger contre la falsification - cela n'a rien à voir avec l'authentification de l'utilisateur
année
1
Ajout d'un des exemples, comment gérer l'authentification utilisateur / client sans connaître au préalable "l' URL de connexion "
Akim
Voici encore deux beaux articles avec des exemples d'authentification sans état pour les services REST: blog.jdriven.com/2014/10/… technicalrex.com/2015/02/20/...
Vladimir Rozhkov
41

TL; DR Login pour chaque demande n'est pas un composant requis pour implémenter la sécurité API, l'authentification l'est.

Il est difficile de répondre à votre question sur la connexion sans parler de la sécurité en général. Avec certains schémas d'authentification, il n'y a pas de connexion traditionnelle.

REST ne dicte aucune règle de sécurité, mais l'implémentation la plus courante dans la pratique est OAuth avec authentification à 3 voies (comme vous l'avez mentionné dans votre question). Il n'y a pas de connexion en soi, du moins pas avec chaque demande d'API. Avec l'authentification à trois voies, vous n'utilisez que des jetons.

  1. L'utilisateur approuve le client API et accorde la permission de faire des demandes sous la forme d'un jeton de longue durée
  2. Le client Api obtient un jeton de courte durée en utilisant celui de longue durée.
  3. Le client Api envoie le jeton de courte durée avec chaque demande.

Ce schéma donne à l'utilisateur la possibilité de révoquer l'accès à tout moment. Pratiquement toutes les API RESTful accessibles au public que j'ai vues utilisent OAuth pour mettre en œuvre cela.

Je ne pense tout simplement pas que vous devriez définir votre problème (et votre question) en termes de connexion, mais plutôt penser à sécuriser l'API en général.

Pour plus d'informations sur l'authentification des API REST en général, vous pouvez consulter les ressources suivantes:

Slavo
la source
Oui, OAuth! Réponse très simple, devrait être la réponse acceptée, à mon humble avis.
Levite
26

Une grande partie de la philosophie REST est d'exploiter autant de fonctionnalités standard du protocole HTTP que possible lors de la conception de votre API. En appliquant cette philosophie à l'authentification, le client et le serveur utiliseraient les fonctionnalités d'authentification HTTP standard dans l'API.

Les écrans de connexion sont parfaits pour les cas d'utilisation des utilisateurs humains: visitez un écran de connexion, fournissez un utilisateur / mot de passe, définissez un cookie, le client fournit ce cookie dans toutes les demandes futures. On ne peut pas s'attendre à ce que les humains utilisant des navigateurs Web fournissent un identifiant et un mot de passe avec chaque requête HTTP individuelle.

Mais pour une API REST, un écran de connexion et des cookies de session ne sont pas strictement nécessaires, car chaque demande peut inclure des informations d'identification sans impacter un utilisateur humain; et si le client ne coopère à aucun moment, une 401réponse "non autorisée" peut être donnée. La RFC 2617 décrit la prise en charge de l'authentification dans HTTP.

TLS (HTTPS) serait également une option, et permettrait l'authentification du client auprès du serveur (et vice versa) dans chaque demande en vérifiant la clé publique de l'autre partie. De plus, cela sécurise le canal pour un bonus. Bien entendu, un échange de paires de clés avant la communication est nécessaire pour ce faire. (Notez qu'il s'agit spécifiquement d'identifier / authentifier l'utilisateur avec TLS. Sécuriser le canal à l'aide de TLS / Diffie-Hellman est toujours une bonne idée, même si vous n'identifiez pas l'utilisateur par sa clé publique.)

Un exemple: supposons qu'un jeton OAuth soit vos informations de connexion complètes. Une fois que le client a le jeton OAuth, il peut être fourni en tant qu'identifiant d'utilisateur dans l'authentification HTTP standard avec chaque demande. Le serveur pourrait vérifier le jeton lors de la première utilisation et mettre en cache le résultat de la vérification avec une durée de vie renouvelée à chaque demande. Toute demande nécessitant une authentification est renvoyée 401si elle n'est pas fournie.

wberry
la source
1
"puisque chaque demande peut inclure des informations d'identification sans affecter un utilisateur humain" L'authentification à trois voies et OAuth ont été inventées parce que la chose entre guillemets est mauvaise. Si vous fournissez des informations d'identification avec chaque demande sans mécanisme sur le serveur pour les révoquer, cela ne serait pas sécurisé s'il était utilisé sans SSL.
Slavo
1
Chaque fois qu'il y a un concept d'utilisateurs, quelque chose doit être transmis du client au serveur pour identifier quel utilisateur. Un jeton OAuth peut certainement servir de "justificatif" ici, au lieu d'une combinaison utilisateur / mot de passe. Sécuriser le canal avec TLS est certainement toujours une bonne chose, mais ce n'est presque pas la question. Même si vous utilisez un cookie, une sorte de jeton est toujours envoyée au serveur à chaque demande, juste avec un en-tête de cookie au lieu d'un en-tête d'authentification.
wberry
Et si vous n'utilisez pas TLS ou OAuth pour une raison quelconque, est-ce que l'envoi d'un utilisateur / mot de passe à chaque fois est vraiment pire que de l'envoyer une seule fois? Si l'attaquant peut obtenir l'utilisateur / le mot de passe, l'attaquant peut également obtenir le cookie de session.
wberry
La différence entre un cookie et un en-tête d'authentification constituant des informations d'identification est que les cookies sont toujours associés à un domaine particulier. Cela signifie que lorsque l'API reçoit un cookie, elle sait d'où il vient (a été écrit par le même domaine plus tôt). Avec un en-tête, on ne sait jamais et il faut implémenter des contrôles spécifiques pour cela. En général, je suis d'accord, ce sont tous les deux des informations d'identification, mais je pense que passer des informations d'identification n'est pas une connexion. La connexion est l'action active d'ouverture de la porte. Dans le cas de l'authentification à trois voies, seule la première approbation du client serait la connexion.
Slavo