web-dev-qa-db-fra.com

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 des 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 contre CSRF. Cependant, je ne peux imaginer comment cela fonctionnerait en supposant que j'enregistre le jeton JWT dans le stockage des cookies.

Comment pourrait-il alors se protéger du CSRF?

mise à jour 1
J'ai vu quelques exemples d'utilisation comme suit:

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 alors je pourrais définir un en-tête comme jwt: [token] puis je pouvais lire le jeton depuis l'en-tête.

mise à jour 2

J'ai installé Advanced REST Client Google Chrome extension and was able to pass the token as a custom header. Est-il possible de définir ces données d'en-tête via Javascript lorsque faire une requête GET au serveur?

37
zero_coding

Regardez 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 des cookies. Vous devez également utiliser l'en-tête Authorization, mais au lieu du schéma Basic, utilisez celui Bearer:

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>
22
Florent Morselli

Choisir le stockage est plus une question de compromis que d'essayer de trouver le meilleur choix définitif. Passons en revue 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
  • Accessible uniquement par Javascript exécuté dans le même domaine que celui qui a créé les données
  • Permet d'utiliser l'approche la plus sémantiquement correcte pour transmettre les informations d'authentification de jeton dans HTTP (l'en-tête Authorization avec un schéma Bearer)
  • Il est très facile de sélectionner les demandes qui doivent contenir l'authentification

Les inconvénients

  • Non accessible par Javascript exécuté dans un sous-domaine de celui qui a créé les données (une valeur écrite par example.com ne peut pas être lu par sub.example.com)
  • ⚠️ Est vulnérable à XSS
  • Afin d'effectuer des demandes authentifiées, vous ne pouvez utiliser que des API de navigateur/bibliothèque qui vous permettent de personnaliser la demande (passez le jeton dans l'en-tête Authorization)

Usage

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

  • Il n'est pas vulnérable à XSS
  • Le navigateur inclut automatiquement le jeton dans toute demande qui répond aux spécifications des cookies (domaine, chemin et durée de vie)
  • Le cookie peut être créé dans un domaine de premier niveau et utilisé dans les demandes effectuées par des sous-domaines

Les inconvénients

  • ⚠️ Il est vulnérable au CSRF
  • Vous devez être conscient et toujours considérer l'utilisation possible des cookies dans les sous-domaines
  • Cherry picking les demandes qui devraient inclure le cookie est faisable mais plus compliqué
  • Vous pouvez (encore) rencontrer certains problèmes avec de petites différences dans la façon dont les navigateurs traitent 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 le plus approprié

Usage

Vous n'avez rien à faire côté client car le navigateur s'occupe automatiquement des choses pour vous.

Option 3 - Cookie accessible par Javascript ignoré par côté serveur

Avantages

  • Il n'est pas vulnérable à CSRF ( car il est ignoré par le serveur )
  • Le cookie peut être créé dans un domaine de premier niveau et utilisé dans les demandes effectuées par des sous-domaines
  • Permet d'utiliser l'approche la plus sémantiquement correcte pour transmettre les informations d'authentification de jeton dans HTTP (l'en-tête Authorization avec un schéma Bearer)
  • Il est assez facile de sélectionner les demandes qui doivent contenir l'authentification

Les inconvénients

  • ⚠️ Il est vulnérable à XSS
  • Si vous ne faites pas attention au chemin où vous placez le cookie, le cookie est automatiquement inclus par le navigateur dans les requêtes, ce qui ajoutera des frais généraux inutiles
  • Afin d'effectuer des demandes authentifiées, vous ne pouvez utiliser que des API de navigateur/bibliothèque qui vous permettent de personnaliser la demande (passez le jeton dans l'en-tête Authorization)

Usage

Vous tirez parti du 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

Notes complémentaires

Cela peut sembler une option étrange, mais cela a l'avantage de vous permettre d'avoir du stockage disponible pour un domaine de premier niveau et tous les sous-domaines, ce que le stockage Web ne vous donnera pas. Cependant, sa mise en œuvre est plus complexe.


Conclusion - Notes finales

Ma 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, c'est donc une chose de moins à s'inquiéter

Notez également que les options basées sur les cookies sont également très différentes, pour l'option 3, les cookies sont utilisés uniquement comme mécanisme de stockage, c'est donc presque comme s'il s'agissait d'un détail d'implémentation côté client. Cependant, l'option 2 signifie une manière plus traditionnelle de gérer l'authentification; pour une lecture plus approfondie de cette chose cookies vs jetons, 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 signifierait que les cookies devraient être créés de manière appropriée pour prendre cela en considération.

83
João Angelo

Cet article de blog propose une excellente comparaison côte à côte du stockage du navigateur par rapport aux cookies et s'attaque à chaque attaque potentielle dans chaque cas. https://stormpath.com/blog/where-to-store-your-jwts-cookies-vs-html5-web-storage/

La réponse la plus courte/spoiler: les cookies et ajouter un jeton xsrf dans le jwt. Explication détaillée dans le billet de blog.

10
Carlos Arrastia