Cette question a été abordée, sous une forme légèrement différente, longuement, ici:
Authentification RESTful
Mais cela résout le problème du côté serveur. Examinons cela du côté client. Avant de faire cela, cependant, il y a un prélude important:
Javascript Crypto est sans espoir
L'article de Matasano à ce sujet est célèbre, mais les leçons qu'il contient sont assez importantes:
https://www.nccgroup.trust/us/about-us/newsroom-and-events/blog/2011/august/javascript-cryptography-considered-harmful/
Résumer:
- Une attaque man-in-the-middle peut remplacer trivialement votre code crypto par
<script>
function hash_algorithm(password){ lol_nope_send_it_to_me_instead(password); }</script>
- Une attaque man-in-the-middle est triviale contre une page qui sert n'importe quelle ressource via une connexion non SSL.
- Une fois que vous avez SSL, vous utilisez de toute façon une vraie crypto.
Et pour ajouter un corollaire à moi:
- Une attaque XSS réussie peut aboutir à ce qu'un attaquant exécute du code sur le navigateur de votre client, même si vous utilisez SSL - donc même si vous avez chaque trappe abattue, la cryptographie de votre navigateur peut toujours échouer si votre attaquant trouve un moyen d'exécuter tout code javascript sur le navigateur de quelqu'un d'autre.
Cela rend beaucoup de schémas d'authentification RESTful impossibles ou stupides si vous avez l'intention d'utiliser un client JavaScript. Regardons!
Authentification HTTP de base
Tout d'abord, HTTP Basic Auth. Le plus simple des schémas: passez simplement un nom et un mot de passe à chaque demande.
Bien sûr, cela nécessite absolument SSL, car vous transmettez un nom et un mot de passe encodés en Base64 (réversiblement) à chaque demande. Quiconque écoute sur la ligne peut extraire trivialement le nom d'utilisateur et le mot de passe. La plupart des arguments "Basic Auth is unsecure" proviennent d'un endroit de "Basic Auth over HTTP" qui est une idée horrible.
Le navigateur fournit un support d'authentification HTTP de base intégré, mais il est laid comme un péché et vous ne devriez probablement pas l'utiliser pour votre application. Cependant, l'alternative consiste à cacher le nom d'utilisateur et le mot de passe en JavaScript.
C'est la solution la plus RESTful. Le serveur ne nécessite aucune connaissance de l'état et authentifie chaque interaction individuelle avec l'utilisateur. Certains amateurs de REST (principalement des hommes de paille) insistent sur le fait que le maintien de toute sorte d'état est une hérésie et moussera à la bouche si vous pensez à une autre méthode d'authentification. Il existe des avantages théoriques à ce type de conformité aux normes - il est pris en charge par Apache prêt à l'emploi - vous pouvez stocker vos objets sous forme de fichiers dans des dossiers protégés par des fichiers .htaccess si votre cœur le souhaite!
Le problème ? Vous mettez en cache côté client un nom d'utilisateur et un mot de passe. Cela donne à evil.ru une meilleure solution: même les vulnérabilités les plus élémentaires de XSS pourraient amener le client à transmettre son nom d'utilisateur et son mot de passe à un serveur malveillant. Vous pouvez essayer d'atténuer ce risque en hachant et en salant le mot de passe, mais rappelez-vous: JavaScript Crypto est sans espoir . Vous pouvez atténuer ce risque en le laissant à la prise en charge de l'authentification de base du navigateur, mais .. laid comme un péché, comme mentionné précédemment.
HTTP Digest Auth
L'authentification Digest est-elle possible avec jQuery?
Une authentification plus "sécurisée", c'est un défi de hachage de demande / réponse. Sauf que JavaScript Crypto est sans espoir , il ne fonctionne que sur SSL et vous devez toujours mettre en cache le nom d'utilisateur et le mot de passe côté client, ce qui le rend plus compliqué que HTTP Basic Auth mais pas plus sécurisé .
Authentification de requête avec des paramètres de signature supplémentaires.
Une autre authentification plus "sécurisée", où vous cryptez vos paramètres avec des données nonce et de synchronisation (pour vous protéger contre les attaques répétées et de synchronisation) et envoyez le. L'un des meilleurs exemples de cela est le protocole OAuth 1.0, qui est, pour autant que je sache, un moyen assez efficace pour implémenter l'authentification sur un serveur REST.
http://tools.ietf.org/html/rfc5849
Oh, mais il n'y a pas de clients OAuth 1.0 pour JavaScript. Pourquoi?
JavaScript Crypto est désespéré , rappelez-vous. JavaScript ne peut pas participer à OAuth 1.0 sans SSL, et vous devez toujours stocker le nom d'utilisateur et le mot de passe du client localement - ce qui le place dans la même catégorie que Digest Auth - c'est plus compliqué que HTTP Basic Auth mais ce n'est pas plus sécurisé .
Jeton
L'utilisateur envoie un nom d'utilisateur et un mot de passe, et en échange obtient un jeton qui peut être utilisé pour authentifier les demandes.
Ceci est légèrement plus sécurisé que HTTP Basic Auth, car dès que la transaction de nom d'utilisateur / mot de passe est terminée, vous pouvez supprimer les données sensibles. Il est également moins RESTful, car les jetons constituent un "état" et rendent l'implémentation du serveur plus compliquée.
SSL toujours
Le hic, cependant, est que vous devez toujours envoyer ce nom d'utilisateur et ce mot de passe initiaux pour obtenir un jeton. Les informations sensibles touchent toujours votre JavaScript compromis.
Pour protéger les informations d'identification de votre utilisateur, vous devez toujours garder les attaquants hors de votre JavaScript, et vous devez toujours envoyer un nom d'utilisateur et un mot de passe sur le câble. SSL requis.
Expiration du jeton
Il est courant d'appliquer des stratégies de jeton telles que «hé, lorsque ce jeton existe depuis trop longtemps, jetez-le et faites-vous authentifier à nouveau». ou "Je suis pratiquement sûr que la seule adresse IP autorisée à utiliser ce jeton est XXX.XXX.XXX.XXX
". Beaucoup de ces politiques sont de très bonnes idées.
Firesheeping
Cependant, l'utilisation d'un jeton sans SSL est toujours vulnérable à une attaque appelée «sidejacking»: http://codebutler.github.io/firesheep/
L'attaquant n'obtient pas les informations d'identification de votre utilisateur, mais il peut toujours prétendre être votre utilisateur, ce qui peut être assez mauvais.
tl; dr: L'envoi de jetons non chiffrés via le câble signifie que les attaquants peuvent facilement attraper ces jetons et prétendre être votre utilisateur. FireSheep est un programme qui rend cela très simple.
Une zone séparée et plus sécurisée
Plus l'application que vous exécutez est grande, plus il est difficile de garantir absolument qu'elle ne pourra pas injecter du code qui modifie la façon dont vous traitez les données sensibles. Faites-vous entièrement confiance à votre CDN? Vos annonceurs? Votre propre base de code?
Commun pour les détails de la carte de crédit et moins commun pour le nom d'utilisateur et le mot de passe - certains implémenteurs conservent la `` saisie de données sensibles '' sur une page distincte du reste de leur application, une page qui peut être étroitement contrôlée et verrouillée le mieux possible, de préférence une qui est difficile à hameçonner avec les utilisateurs.
Cookie (signifie simplement Token)
Il est possible (et courant) de placer le jeton d'authentification dans un cookie. Cela ne change aucune des propriétés d'auth avec le jeton, c'est plus une chose pratique. Tous les arguments précédents s'appliquent toujours.
Session (signifie toujours juste Token)
L'authentification de session n'est qu'une authentification par jeton, mais avec quelques différences qui la font paraître quelque chose de légèrement différent:
- Les utilisateurs commencent avec un jeton non authentifié.
- Le backend maintient un objet «état» qui est lié au jeton d'un utilisateur.
- Le jeton est fourni dans un cookie.
- L'environnement d'application résume les détails loin de vous.
Hormis cela, cependant, ce n'est pas différent de Token Auth, vraiment.
Cela s'éloigne encore plus d'une implémentation RESTful - avec les objets d'état, vous allez de plus en plus loin sur le chemin du RPC ordinaire sur un serveur avec état.
OAuth 2.0
OAuth 2.0 examine le problème de "Comment le logiciel A donne-t-il au logiciel B l'accès aux données de l'utilisateur X sans que le logiciel B ait accès aux informations de connexion de l'utilisateur X".
L'implémentation est tout simplement un moyen standard pour un utilisateur d'obtenir un jeton, puis pour un service tiers d'aller "oui, cet utilisateur et ce jeton correspondent, et vous pouvez obtenir certaines de leurs données maintenant".
Fondamentalement, cependant, OAuth 2.0 n'est qu'un protocole symbolique. Il présente les mêmes propriétés que les autres protocoles de jetons - vous avez toujours besoin de SSL pour protéger ces jetons - il modifie simplement la façon dont ces jetons sont générés.
OAuth 2.0 peut vous aider de deux manières:
- Fourniture d'authentification / d'informations à des tiers
- Obtention de l'authentification / des informations des autres
Mais en fin de compte, vous utilisez simplement ... des jetons.
Retour à votre question
Ainsi, la question que vous posez est "dois-je stocker mon jeton dans un cookie et faire en sorte que la gestion automatique des sessions de mon environnement s'occupe des détails, ou dois-je stocker mon jeton en Javascript et gérer moi-même ces détails?"
Et la réponse est: faites tout ce qui vous rend heureux .
La chose à propos de la gestion automatique des sessions, cependant, c'est qu'il y a beaucoup de magie qui se passe dans les coulisses pour vous. Il est souvent plus agréable de contrôler vous-même ces détails.
J'ai 21 ans donc SSL est oui
L'autre réponse est: utilisez https pour tout ou les brigands voleront les mots de passe et les jetons de vos utilisateurs.