JWT : où stocker le token ?

c'est vrai quoi : où ça ?

a marqué ce sujet comme résolu.

Salut, Je met actuellement en place un système, très simple, d’authentification sur une appli web, avec des JWT.

D’après les ressources que j’ai trouvées, on a plusieurs choix pour stocker le token, dont : sessionStorage(ou localStorage), et cookie (httpOnly et Secure, etc.).

Ce que je comprends, c’est que le cookie, c’est mieux, parce que le sessionStorage est accessible en cas de XSS. Au contraire, le cookie n’est compromis qu’en cas de CSRF. Or, et je résume grossièrement ce que j’ai pu lire, il est plus simple de se protéger contre les CSRF que les XSS, et les XSS peuvent impliquer des CSRF.

Cependant, j’ai l’impression que le passage du JWT dans un header Authorization (Bearer token), est répandue, et je trouve des exemples dans pas mal de documentations officielles.

Précision : je fais une application avec une API .NET et un front Angular. Ca n’est pas tellement important, sauf parce qu’Angular est censé (mais je ne sais pas à quel point ça doit jouer sur notre approche des ces questions) protéger contre le XSS, sauf bypass explicite.

Ce que mes recherches tendent à me montrer, c’est surtout qu’il n’y a pas de solution simple, et qu’il faut combiner des protections concernant les XSS et CSRF et une faible durée de vie des tokens. Eventuellement aussi,un refresh et rotation des refresh tokens, comme expliqué ici : https://auth0.com/blog/refresh-tokens-what-are-they-and-when-to-use-them/

Mes questions : Est-ce que je comprends bien les données du problème ? Est-ce que quelqu’un a de l’expérience / des ressources à ce sujet, au-delà de ce que l’on trouve en cherchant "naïvement" ? Est-ce qu’on s’en fiche parce que le véritable enjeu est de se protéger contre les attaques XSS et CSRF ?

J’ai trouvé plein de trucs déjà, dont je vous épargne les liens : tutoriaux généraux et spécifiques à .NET-Angular, explications théoriques, sujets Stack Overflow, pages OWASP. J’ai aussi cherché un peu sur Zds, et trouvé ce sujet qui posait des questions proches.

Pour l’instant, j’en reste à stocker le token dans le sessionStorage, mais je sens bien au fond de moi que c’est mal !

Merci d’avance pour vos réponses !

Hello,

Tu as effectivement compris que le principal était de se prémunir des failles courantes plus que de choisir où stocker ton token.

L’avantage des cookies est que tu as rarement besoin d’implémenter une logique pour l’envoyer avec tes requêtes au backend, la navigateur faisant la plupart du boulot pour toi.

Le localStorage ou sessionStorage vont nécessiter un peu plus de logique côté client mais sont plus simples à manipuler (en tout cas sans une lib pour lire/écrire les cookies).

Angular a effectivement une approche où par défaut les injections sont protégées… jusqu’au jour où une faille sera trouvée et toutes les versions pas à jour auront une brèche ouverte. Autant ne pas trop compter dessus.

Les CSRF tu peux assez facilement les limiter avec une bonne CSP, et surtout les cookies peuvent être limités à un domaine.

En somme, il n’y a pas de solution parfaite. Le compromis est donc de savoir ce que tu as besoin de faire avec ton token : si tu la partages avec plusieurs domaines tu peux décider de sacrifier un peu de sécurité pour te simplifier la vie… mais il faudra être conscient du risque. ;)

Par contre en effet utilise des jetons à courte durée de vie et les renouveler est une bonne pratique pour les cas d’usage où c’est faisable de façon réaliste (typiquement un front qui se connecte régulièrement à un backend).

C’est un des problèmes de la sécurité : les bonnes solutions pour se protéger créent souvent pas mal de frictions ailleurs… et les approches simples sont souvent peu sécurisées. :D

Merci pour ta réponse :)

Le localStorage ou sessionStorage vont nécessiter un peu plus de logique côté client mais sont plus simples à manipuler (en tout cas sans une lib pour lire/écrire les cookies).

viki53

Ce qui m’a poussé à stocker le token dans le sessionStorage, c’est que l’approche présentée dans la documentation .NET correspond à un Bearer token. Ensuite les annotations attendent le token dans le header correspondant, et non dans un cookie.
Or, si je ne m’abuse, il n’est pas possible d’envoyer le token dans un header si on le stocke dans un cookie httponly, par définition. Est-ce que je me trompe ? Si j’ai raison, dans tous les cas je dois écrire un peu de logique d’un côté ou de l’autre.

C’est un des problèmes de la sécurité : les bonnes solutions pour se protéger créent souvent pas mal de frictions ailleurs… et les approches simples sont souvent peu sécurisées. :D

viki53

C’est bien ce qu’il me semblait :)

Bon, je continue d’y réfléchir, et j’en parle à des collègues, voir s’ils ont des opinions fortes à ce sujet. Si quelque chose d’intéressant se dégage, j’alimenterai ce topic.

D’une manière générale, un JWT est rarement utilisé seul, dans le sens où il ne fait pas partie d’un protocole bien défini (example : OIDC, OAuth 2, etc).

La bonne pratique, alors, est d’utiliser autant que possible des bibliothèques bien connues et de qualité pour gérer ce protocole. C’est typiquement le genre de chose qu’on veut éviter au maximum de réimplémenter, parce que la moindre erreur peut se solder par une faille de sécurité critique.

J’ai beaucoup plus l’habitude de travailler côté back, et je te confirme que la plupart des API REST que j’ai pu voir passer s’attendent à voir le jeton d’authentification (JWT ou non, d’ailleurs) envoyé en tant que Authorization: Bearer <token>. C’est un cas d’usage que les bonnes bibliothèques de gestion réseau et d’authentification devraient gérer facilement, tout comme elles devraient gérer le renouvellement automatique du JWT à l’aide du refresh token.

La bonne pratique, alors, est d’utiliser autant que possible des bibliothèques bien connues et de qualité pour gérer ce protocole. C’est typiquement le genre de chose qu’on veut éviter au maximum de réimplémenter, parce que la moindre erreur peut se solder par une faille de sécurité critique.

Justement, j’avais cette volonté de laisser les choses comme elles sont côté .NET, et le scheme par défaut correspond à un bearer token. Mais ça me gênait d’avoir de la logique javascript pour le gérer côté Angular, et en plus de le stocker dans un endroit comme le sessionStorage.

J’ai beaucoup plus l’habitude de travailler côté back, et je te confirme que la plupart des API REST que j’ai pu voir passer s’attendent à voir le jeton d’authentification (JWT ou non, d’ailleurs) envoyé en tant que Authorization: Bearer <token>. C’est un cas d’usage que les bonnes bibliothèques de gestion réseau et d’authentification devraient gérer facilement, tout comme elles devraient gérer le renouvellement automatique du JWT à l’aide du refresh token.

SpaceFox

Ca confirme mon impression. Je vais rester comme ça pour le moment, on est en début de projet, et continuer d’y réfléchir.

Merci :)

Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte