Stockage local ou cookies? Stockage sécurisé des JWT sur le client

JWT (JSON Web Token) est un merveilleux standard basĂ© sur JSON pour crĂ©er des jetons d'accĂšs couramment utilisĂ©s pour l'authentification dans les applications client-serveur. Lors de l'utilisation de ces jetons, la question se pose de savoir comment les stocker en toute sĂ©curitĂ© dans le front-end de l'application. Ce problĂšme doit ĂȘtre rĂ©solu immĂ©diatement aprĂšs la gĂ©nĂ©ration du jeton sur le serveur et le transfert du cĂŽtĂ© client de l'application. Le matĂ©riel, dont nous publions aujourd'hui la traduction, est consacrĂ© Ă  l'analyse des avantages et des inconvĂ©nients de l'utilisation du stockage local du navigateur ( ) et des cookies pour stocker les JWT.







localStorage



Types de jetons



  • Les jetons d'accĂšs sont gĂ©nĂ©ralement des JWT de courte durĂ©e signĂ©s par le serveur. Ils sont inclus dans chaque requĂȘte HTTP qu'un client fait Ă  un serveur. Les jetons sont utilisĂ©s pour autoriser les demandes.
  • Les jetons d'actualisation sont gĂ©nĂ©ralement des jetons de longue durĂ©e stockĂ©s dans une base de donnĂ©es et utilisĂ©s pour obtenir un nouveau jeton d'accĂšs lorsque le jeton prĂ©cĂ©dent expire.


OĂč exactement les jetons doivent-ils ĂȘtre stockĂ©s sur le client?



Il existe 2 façons courantes de stocker des jetons sur le client: le stockage du navigateur local et les cookies. Il y a beaucoup de débats sur la meilleure méthode. La plupart des gens se tournent vers les cookies en raison de leur meilleure sécurité.



Comparons le stockage local et les cookies. Notre comparaison est basée principalement sur ce matériel et sur les commentaires qui y sont associés.



Stockage local



▍Avantages



Le principal avantage du stockage local est qu'il est pratique Ă  utiliser.



  • Travailler avec le stockage local est trĂšs pratique, du JavaScript pur est utilisĂ© ici. Si votre application n'a pas de backend et que vous comptez sur des API tierces, vous ne pourrez peut-ĂȘtre pas toujours demander Ă  ces API de dĂ©finir des cookies spĂ©cifiques pour votre site.
  • En utilisant le stockage local, il est pratique de travailler avec des API qui nĂ©cessitent de placer un jeton d'accĂšs dans l'en-tĂȘte de la demande. Par exemple - comme suit: Authorization Bearer ${access_token}.


▍ InconvĂ©nients



Le principal inconvénient du stockage local est sa vulnérabilité aux attaques XSS.



  • Lors d'une attaque XSS, un attaquant peut exĂ©cuter son code JavaScript sur votre site. Cela signifie qu'un attaquant peut accĂ©der au jeton d'accĂšs stockĂ© dans localStorage.
  • La source de l'attaque XSS peut ĂȘtre un code JavaScript tiers inclus dans votre site. Cela peut ĂȘtre quelque chose comme React, Vue, jQuery, script Google Analytics, etc. Dans les conditions modernes, il est presque impossible de dĂ©velopper un site qui n'inclut pas de bibliothĂšques tierces.


Biscuits



▍Avantages



Le principal avantage des cookies est qu'ils ne sont pas accessibles depuis JavaScript. En conséquence, ils ne sont pas aussi vulnérables aux attaques XSS que le stockage local.



  • Si vous utilisez un indicateur HttpOnlyet des cookies sĂ©curisĂ©s, cela signifie que JavaScript ne peut pas accĂ©der Ă  ces fichiers. Autrement dit, mĂȘme si un attaquant peut exĂ©cuter son code sur votre page, il ne pourra pas lire le jeton d'accĂšs Ă  partir du cookie.
  • Les cookies sont automatiquement envoyĂ©s dans chaque requĂȘte HTTP au serveur.


▍ InconvĂ©nients



Selon les circonstances spĂ©cifiques, il peut arriver que les jetons contenus dans les cookies ne puissent pas ĂȘtre stockĂ©s.



  • La taille des cookies est limitĂ©e Ă  4 Ko. Par consĂ©quent, si vous utilisez des JWT volumineux, les stocker dans des cookies ne fonctionnera pas pour vous.
  • Il existe des scĂ©narios dans lesquels vous ne pouvez pas transmettre de cookies Ă  votre serveur API. Il est Ă©galement possible que certaines API nĂ©cessitent de placer un jeton dans l'en-tĂȘte Authorization. Dans ce cas, vous ne pourrez pas stocker de jetons dans les cookies.


Attaques XSS



Le stockage local est vulnĂ©rable aux attaques XSS car il est trĂšs facile de travailler avec JavaScript. Par consĂ©quent, un attaquant peut accĂ©der au jeton et l'utiliser Ă  son avantage. Cependant, bien que les cookies HttpOnly ne soient pas accessibles Ă  partir de JavaScript, cela ne signifie pas que vous ĂȘtes protĂ©gĂ© contre les attaques XSS en utilisant des cookies pour voler un jeton d'accĂšs.



Si un attaquant peut exĂ©cuter son code JS dans votre application, cela signifie qu'il peut simplement envoyer une requĂȘte Ă  votre serveur, et le jeton sera automatiquement inclus dans cette requĂȘte. Un tel schĂ©ma de travail n'est tout simplement pas si pratique pour l'attaquant, car il ne peut pas lire le contenu du jeton. Mais les attaquants en ont rarement besoin. De plus, avec ce schĂ©ma de travail, il peut ĂȘtre plus rentable pour un attaquant d'attaquer le serveur en utilisant l'ordinateur de la victime, plutĂŽt que le sien.



Cookies et attaques CSRF



Les attaques CSRF sont des attaques dans lesquelles un utilisateur est contraint d'une maniÚre ou d'une autre à faire une demande spéciale. Par exemple, le site accepte les demandes de changement d'adresse e-mail:



POST /email/change HTTP/1.1
Host: site.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 50
Cookie: session=abcdefghijklmnopqrstu

email=myemail.example.com


Dans une telle situation, un attaquant peut crĂ©er un formulaire avec un champ cachĂ© pour saisir une adresse e-mail Ă  laquelle envoyer une requĂȘte POST https://site.com/email/change. Dans ce cas, les cookies de session seront automatiquement inclus dans une telle demande.



Cependant, cette menace peut ĂȘtre facilement protĂ©gĂ©e en utilisant l'attribut SameSitedans l'en-tĂȘte de rĂ©ponse et les jetons anti-CSRF .



Sous-totaux



Bien que les cookies ne soient pas complÚtement à l'abri des attaques, la meilleure façon de stocker des jetons est, dans la mesure du possible, de les choisir localStorage. Pourquoi?



  • Le stockage local et les cookies sont tous deux vulnĂ©rables aux attaques XSS, mais il sera plus difficile pour un attaquant d'attaquer si les cookies HttpOnly sont utilisĂ©s.
  • Les cookies sont vulnĂ©rables aux attaques CSRF, mais le risque de telles attaques peut ĂȘtre attĂ©nuĂ© en utilisant l'attribut SameSiteet les jetons anti-CSRF .


Les cookies peuvent ĂȘtre utilisĂ©s mĂȘme lorsque vous devez utiliser un en-tĂȘte Authorization: Bearerou lorsque le JWT est supĂ©rieur Ă  4 Ko. Ceci est Ă©galement conforme aux directives OWASP: «Ne stockez pas les ID de session dans le stockage local, car les donnĂ©es correspondantes sont toujours disponibles Ă  partir de JavaScript. Les cookies peuvent aider Ă  attĂ©nuer vos risques avec HttpOnly. "



Utilisation de cookies pour stocker des jetons OAuth 2.0



ÉnumĂ©rons briĂšvement les façons de stocker les jetons:



  • MĂ©thode 1: stocker les jetons dans le stockage local. Cette mĂ©thode est sensible aux attaques XSS.
  • MĂ©thode 2: stockage des jetons dans les cookies HttpOnly. Cette mĂ©thode est sensible aux attaques CSRF, mais le risque de telles attaques peut ĂȘtre attĂ©nuĂ©. Cette option de stockage de jetons est lĂ©gĂšrement mieux protĂ©gĂ©e contre les attaques XSS que la premiĂšre.
  • MĂ©thode 3: stockez les jetons d'actualisation dans les cookies HttpOnly et accĂ©dez aux jetons en mĂ©moire. Cette façon de stocker les jetons est plus sĂ»re en termes d'attaques CSRF et lĂ©gĂšrement mieux protĂ©gĂ©e contre les attaques XSS.


Ci-dessous, nous examinerons de plus prÚs la troisiÚme méthode de stockage des jetons, car elle, des trois répertoriées, semble la plus intéressante.



Pourquoi le stockage du jeton d'actualisation dans un cookie HttpOnly est-il plus sûr en termes d'attaques CSRF?



Un attaquant pourrait crĂ©er un formulaire qui accĂšde /refresh_token. Un nouveau jeton d'accĂšs est renvoyĂ© en rĂ©ponse Ă  cette demande. Mais l'attaquant ne peut pas lire la rĂ©ponse s'il utilise un formulaire HTML. Afin d'empĂȘcher un attaquant d'exĂ©cuter avec succĂšs des requĂȘtes de rĂ©cupĂ©ration ou AJAX et de lecture des rĂ©ponses, la politique CORS du serveur d'autorisation doit ĂȘtre configurĂ©e correctement, Ă  savoir, afin que le serveur ne rĂ©ponde pas aux requĂȘtes provenant de sites Web non autorisĂ©s.



Comment le configurez-vous?



Étape 1: renvoyer le jeton d'accùs et le jeton d'actualisation lors de l'authentification de l'utilisateur



Une fois que l'utilisateur s'est authentifié, le serveur d'authentification renvoie access_token(jeton d'accÚs) et refresh_token(jeton d'actualisation). Le jeton d'accÚs sera inclus dans le corps de la réponse et le jeton d'actualisation dans le cookie.



Voici ce que vous devez utiliser pour configurer des cookies pour stocker des jetons d'actualisation:



  • Flag HttpOnly- pour empĂȘcher JavaScript de lire le jeton.
  • Un indicateur secure=truequi entraĂźnera la transmission des donnĂ©es uniquement via HTTPS.
  • Le drapeau SameSite=strictdoit ĂȘtre utilisĂ© chaque fois que possible pour se protĂ©ger contre les attaques CSRF. Cette approche ne peut ĂȘtre utilisĂ©e que si le serveur d'autorisation appartient au mĂȘme site que l'interface du systĂšme. Si ce n'est pas le cas, le serveur d'autorisation doit dĂ©finir les en-tĂȘtes CORS sur le backend ou utiliser d'autres mĂ©thodes pour garantir que la demande avec le jeton d'actualisation ne peut ĂȘtre effectuĂ©e que par un site Web autorisĂ©.


Étape 2: stocker le jeton d'accĂšs en mĂ©moire



Le stockage du jeton d'accĂšs en mĂ©moire signifie que le jeton, dans le code du frontend, est Ă©crit dans une variable. Cela signifie bien sĂ»r que le jeton sera perdu si l'utilisateur ferme l'onglet oĂč le site est ouvert ou actualise la page. C'est pourquoi nous avons un jeton d'actualisation.



Étape 3: obtenir un nouveau jeton d'accùs à l'aide du jeton d'actualisation



Si le jeton d'accĂšs est perdu ou non valide, vous devez contacter le point de terminaison /refresh_token. Dans ce cas, le jeton d'actualisation, qui, Ă  l'Ă©tape 1, a Ă©tĂ© enregistrĂ© dans le cookie, sera inclus dans la demande. Vous recevrez ensuite un nouveau jeton d'accĂšs que vous pourrez utiliser pour effectuer des requĂȘtes API.



Tout cela signifie que les JWT peuvent ĂȘtre plus grands que 4 Ko, et qu'ils peuvent ĂȘtre placĂ©s dans l'en-tĂȘte Authorization.



RĂ©sultat



Ce que nous avons couvert ici devrait vous donner quelques informations de base sur le stockage des JWT sur le client et comment rendre votre projet plus sécurisé.



Comment stockez-vous JWT sur le client?






All Articles