70 votes

REST et variantes d'authentification

Je travaille actuellement sur une bibliothèque REST pour .net, et j'aimerais avoir des avis sur un point en suspens que j'ai : REST et l'authentification.

Voici un exemple d'une interface RESTful utilisée avec la bibliothèque :

[RestRoot("/user")]
public interface IUserInterface
{
  [RestPut("/")]
  void Add(User user);

  [RestGet("/")]
  int[] List();

  [RestGet("/get/{id}")]
  User Get(int id);

  [RestDelete("/delete/{id}")]
  void Delete(int id);
}

Le code du serveur se contente alors d'implémenter l'interface et les clients peuvent obtenir la même interface par le biais d'une fabrique. Ou si le client n'utilise pas la bibliothèque, une requête HTTP standard fonctionne également.

Je sais qu'il existe les principaux moyens d'utiliser l'authentification de base HTTP ou d'envoyer un jeton aux demandes nécessitant des utilisateurs authentifiés.

La première méthode (HTTP Basic Auth), présente les problèmes suivants (en partie spécifiques aux navigateurs web) :

  • Le mot de passe est transmis à chaque demande - même avec SSL, cela donne une sorte de "mauvais pressentiment".
  • Comme le mot de passe est transmis avec un en-tête de demande, il serait facile pour un attaquant local de regarder les en-têtes transmis pour obtenir le mot de passe.
  • Le mot de passe est disponible dans la mémoire des navigateurs.
  • Pas de moyen standard pour faire expirer les "sessions" des utilisateurs.
  • La connexion avec un navigateur interrompt l'aspect et la convivialité d'une page.

Les questions relatives à la deuxième méthode sont davantage axées sur la mise en œuvre et l'utilisation des bibliothèques :

  • Chaque URI de demande qui nécessite une authentification doit avoir un paramètre pour le jeton, ce qui est très répétitif.
  • Il y a beaucoup plus de code à écrire si l'implémentation de chaque méthode doit vérifier si un jeton est valide.
  • L'interface deviendra moins spécifique, par ex. [RestGet("/get/{id}")] vs. [RestGet("/get/{id}/{token}")] .
  • Où mettre le jeton : à la fin de l'URI ? après la racine ? ailleurs ?

Mon idée était de passer le jeton en tant que paramètre de l'URL comme suit http:/server/user/get/1234?token=token_id .

Une autre possibilité serait d'envoyer le paramètre en tant qu'en-tête HTTP, mais cela compliquerait l'utilisation avec les clients HTTP ordinaires, je suppose.

Le jeton est renvoyé au client sous la forme d'un en-tête HTTP personnalisé ("X-Session-Id") à chaque demande.

Ceci pourrait alors être complètement abstrait de l'interface, et toute implémentation nécessitant une authentification pourrait simplement demander à quel utilisateur appartient le jeton (s'il est donné).

Pensez-vous que cela violerait trop REST ou avez-vous une meilleure idée ?

64voto

laz Points 12212

J'ai tendance à croire que les détails de l'authentification doivent figurer dans l'en-tête, et non dans l'URI. Si vous comptez sur un jeton placé dans l'URI, chaque URI de votre application devra être encodé pour inclure le jeton. Cela aurait également un impact négatif sur la mise en cache. Les ressources dont le jeton change constamment ne pourront plus être mises en cache. Les informations relatives aux ressources doivent figurer dans l'URI, pas les données relatives à l'application telles que les informations d'identification.

Il semble que vous devez cibler les navigateurs web en tant que client ? Si c'est le cas, vous pouvez utiliser Authentification d'accès HTTP Digest ou l'émission aux clients de leurs propres certificats SSL pour les identifier et les authentifier de manière unique. Par ailleurs, je ne pense pas que les cookies de session soient nécessairement une mauvaise chose. Surtout lorsqu'on a affaire à un navigateur. Tant que vous isolez le code de gestion des cookies et que vous faites en sorte que le reste de l'application n'en dépende pas, tout va bien. La clé est de ne stocker que l'identité de l'utilisateur dans la session, rien d'autre. N'abusez pas de l'état de la session côté serveur.

Si vous ciblez des clients autres que le navigateur, vous pouvez adopter plusieurs approches. J'ai eu de la chance avec l'utilisation de l'application Amazon's Authentification S3 mécanisme.

Tout cela est bien sûr très subjectif. La pureté et le respect de REST à la lettre peuvent parfois s'avérer peu pratiques. Tant que vous minimisez et isolez ces comportements, le cœur de votre application peut toujours être RESTful. Je recommande vivement Services Web RESTful comme une grande source d'informations et d'approches REST.

15voto

LiorH Points 4623

Je suis d'accord avec workmad3, si la durée de vie de la session doit être maintenue, vous devriez créer une ressource de session. Poster sur cette ressource avec les informations d'identification de l'utilisateur (soit une authentification de base, soit des informations d'identification dans le corps du message) renverra un identifiant de session unique. La suppression de /session/{id} déconnectera l'utilisateur.

Si vous voulez contrôler le temps d'expiration de la session. Lors de la création d'une nouvelle session (post on session resource), le serveur place un cookie dans la réponse (en utilisant l'en-tête standard set-cookie). Le cookie contiendra le délai d'expiration. La chaîne du cookie doit être cryptée sur le serveur, de sorte que seul le serveur peut ouvrir ce cookie. Chaque demande ultérieure au serveur enverra le cookie de session dans l'en-tête cookie. (cela sera fait automatiquement pour vous si votre client est un navigateur). Le serveur doit "renouveler" le cookie pour chaque demande, c'est-à-dire créer un nouveau cookie avec un nouveau délai d'expiration (prolonger le délai de la session). N'oubliez pas d'effacer le cookie lorsque l'utilisateur demande la suppression de la ressource de la session.

Si vous voulez que votre application soit plus sécurisée, vous pouvez stocker l'IP du client dans le cookie lui-même, de sorte que lorsqu'une requête arrive, le serveur peut valider qu'elle a été envoyée par le client "original". Mais n'oubliez pas que cette solution peut être problématique lorsque des proxies sont impliqués, car le serveur pourrait "voir" toutes les demandes comme provenant du même client.

4voto

workmad3 Points 12974

Le reste de l'authentification que j'ai vu traite les sessions comme une ressource REST pour la création, la destruction, etc. et l'ID de session est ensuite transmis dans les deux sens. Ceux que j'ai vus ont tendance à utiliser le cookie de session pour cela, car c'est la seule façon de le sécuriser. Si vous passez l'identifiant de session dans l'URL, vous n'avez aucun moyen d'authentifier réellement qu'il provient du bon client.

L'authentification est cependant un problème délicat avec REST, car elle exige qu'une certaine forme d'état soit conservée en dehors de l'URL, ce qui enfreint les principes de REST selon lesquels l'URL est tout ce qui est nécessaire pour représenter l'état.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X