Où enregistrer un JWT dans une application basée sur un navigateur et comment l'utiliser
J'essaie d'implémenter JWT dans mon système d'authentification et j'ai quelques questions. Pour stocker le jeton, je pourrais utiliser les cookies, mais il est également possible d'utiliser localStorage
ou sessionStorage
.
Quel serait le meilleur choix?
J'ai lu que JWT protège le site de CSRF. Cependant, je ne peux pas imaginer comment cela fonctionnerait en supposant que je sauvegarde le jeton JWT dans le stockage des cookies.
Comment protégerait-il alors de CSRF?
Mise à Jour 1
J'ai vu quelques exemples d'utilisation comme le suivant:
curl -v -X POST -H "Authorization: Basic VE01enNFem9FZG9NRERjVEJjbXRBcWJGdTBFYTpYUU9URExINlBBOHJvUHJfSktrTHhUSTNseGNh"
Comment puis-je implémenter cela lorsque je fais une demande au serveur à partir du navigateur? J'ai également vu que certains implémentent le jeton dans L'URL:
http://exmple.com?jwt=token
Si je faisais une demande via AJAX, je pourrais définir un en-tête comme jwt: [token]
et ensuite je pourrais lire le jeton de l'en-tête.
Mise à Jour 2
J'ai installé L'extension Google Chrome du client REST avancé et j'ai pu passer le jeton en tant qu'en-tête personnalisé. Est-il possible de définir ces données d'en-tête via Javascript lors d'une requête GET sur le serveur?
3 réponses
Oeil à ce site web: https://auth0.com/blog/2014/01/07/angularjs-authentication-with-cookies-vs-token/
Si vous souhaitez les stocker, vous devez utiliser localStorage ou sessionStorage si disponible ou cookies. Vous devez également utiliser L'en-tête Authorization, mais au lieu du schéma de base, utilisez celui du porteur:
curl -v -X POST -H "Authorization: Bearer YOUR_JWT_HERE"
Avec JS, vous pouvez utiliser le code suivant:
<script type='text/javascript'>
// define vars
var url = 'https://...';
// ajax call
$.ajax({
url: url,
dataType : 'jsonp',
beforeSend : function(xhr) {
// set header if JWT is set
if ($window.sessionStorage.token) {
xhr.setRequestHeader("Authorization", "Bearer " + $window.sessionStorage.token);
}
},
error : function() {
// error handler
},
success: function(data) {
// success handler
}
});
</script>
Choisir le stockage est plus sur les compromis que d'essayer de trouver un meilleur choix définitif. Passons par quelques options:
Option 1 - Stockage Web (localStorage
ou sessionStorage
)
Avantages
- le navigateur n'inclura automatiquement rien du stockage Web dans les requêtes HTTP, ce qui le rend Non vulnérable à CSRF
- N'est accessible que par Javascript s'exécutant dans le même domaine que celui qui a créé les données
- permet d'utiliser le plus approche sémantiquement correcte pour passer les informations D'identification d'authentification de jeton dans HTTP (l'en-tête
Authorization
avec un schémaBearer
) - Il est très facile de sélectionner les requêtes qui doivent contenir l'authentification
Contre
- ne peut pas être accessible par Javascript s'exécutant dans un sous-domaine de celui qui a créé les données (une valeur écrite par
example.com
ne peut pas être lue parsub.example.com
) - ⚠ ️ est vulnérable à XSS
- pour effectuer des requêtes authentifiées, vous ne pouvez utilisez les API du navigateur/bibliothèque qui vous permettent de personnaliser la requête (passez le jeton dans l'en-tête
Authorization
)
Utilisation
Vous tirez parti du navigateur localStorage
ou sessionStorage
API pour stocker puis récupérer le jeton lors de l'exécution des demandes.
localStorage.setItem('token', 'asY-x34SfYPk'); // write
console.log(localStorage.getItem('token')); // read
Option 2-cookie HTTP uniquement
Avantages
- C'est Pas vulnérable à XSS
- le navigateur inclut automatiquement le jeton dans toute requête qui répond au cookie spécification (domaine, chemin et durée de vie)
- le cookie peut être créé dans un domaine de premier niveau et utilisé dans des requêtes effectuées par des sous-domaines
Contre
- ⚠ ️ Il est vulnérable à CSRF
- vous devez être conscient et toujours considérer l'utilisation possible des cookies dans les sous-domaines
- cerise choisir les requêtes qui devraient inclure le cookie est faisable mais messier
- Vous pouvez (encore) rencontrer quelques problèmes avec de petites différences dans la façon dont les navigateurs traiter les cookies
- ⚠ ️ si vous ne faites pas attention, vous pouvez mettre en œuvre une stratégie d'atténuation CSRF qui est vulnérable à XSS
- le côté serveur doit valider un cookie pour l'authentification au lieu de l'en-tête
Authorization
plus approprié
Utilisation
Vous n'avez pas besoin de faire quoi que ce soit côté client car le navigateur s'occupera automatiquement des choses pour vous.
Option 3-cookie Javascript accessible ignoré par côté serveur
Avantages
- C'est pas vulnérables à CSRF (parce qu'il est ignoré par le serveur)
- le cookie peut être créé dans un domaine de premier niveau et utilisé dans des requêtes effectuées par des sous-domaines
- permet d'utiliser l'approche la plus sémantiquement correcte pour passer des informations D'authentification de jeton dans HTTP (l'en-tête
Authorization
avec un schémaBearer
) - Il est un peu facile de choisir les requêtes qui devraient contenir authentification
Contre
- ⚠ ️ Il est vulnérable à XSS
- Si vous ne faites pas attention au chemin où vous définissez le cookie, le cookie est automatiquement inclus par le navigateur dans les requêtes, ce qui ajoutera des frais généraux inutiles
- pour effectuer des requêtes authentifiées, vous ne pouvez utiliser que les API du navigateur / bibliothèque qui vous permettent de personnaliser la requête (passez le jeton dans l'en-tête
Authorization
)
Utilisation
Vous tirez parti de la navigateur document.cookie
API pour stocker puis récupérer le jeton lors de l'exécution des demandes. Cette API n'est pas aussi fine que le stockage Web (vous obtenez tous les cookies), vous avez donc besoin d'un travail supplémentaire pour analyser les informations dont vous avez besoin.
document.cookie = "token=asY-x34SfYPk"; // write
console.log(document.cookie); // read
Remarques Supplémentaires
Cela peut sembler une option étrange, mais cela a le bel avantage que vous pouvez avoir du stockage disponible pour un domaine de premier niveau et tous les sous-domaines qui sont quelque chose que le stockage Web ne vous donnera pas. Cependant, il est plus complexe d' mettre.
Conclusion-Notes Finales
Mon recommandation pour les scénarios les plus courants, serait d'aller avec l'Option 1, principalement parce que:
- Si vous créez une application Web, vous devez gérer XSS; toujours, indépendamment de l'endroit où vous stockez vos jetons
- Si vous n'utilisez pas L'authentification basée sur les cookies, CSRF ne devrait même pas apparaître sur votre radar, donc c'est une chose de moins à craindre
Notez également que le cookie basé sur les options sont également très différentes, car les cookies de L'Option 3 sont utilisés uniquement comme un mécanisme de stockage, donc c'est presque comme si c'était un détail d'implémentation du côté client. Cependant, L'Option 2 signifie une façon plus traditionnelle de traiter l'authentification; pour une lecture plus approfondie de cette chose cookies vs token, vous pouvez trouver cet article intéressant: Cookies vs Tokens: the Definitive Guide .
Enfin, aucune des options ne le mentionne, mais L'utilisation de HTTPS est obligatoire bien sûr, ce qui les cookies moyens devraient être créés de manière appropriée pour prendre cela en considération.
Cet article de blog a une excellente comparaison côte à côte du stockage du navigateur par rapport aux cookies et s'attaque à toutes les attaques potentielles dans chaque cas. https://stormpath.com/blog/where-to-store-your-jwts-cookies-vs-html5-web-storage/
La réponse / spoiler plus courte: cookies et Ajouter un jeton xsrf dans le jwt. Explication détaillée dans le billet de blog.