web-dev-qa-db-fra.com

Dois-je stocker des jetons dans des cookies ou un stockage local ou une session?

Désolé, c'est peut-être une question que beaucoup d'autres ont posée, mais je suis vraiment confus parce que certaines références ont de nombreuses façons différentes.

J'utilise React SPA, Express, Express-session, Passport, JWT

donc je suis confus au sujet des cookies, de la session et du JWT/Passport.

De nombreux sites Web utilisent des cookies pour stocker des jetons de panier. Jusqu'à présent, j'ai stocké des données de panier basées sur l'ID de session sans ajouter de cookies.

Ainsi, lorsque les utilisateurs visitent mon site Web, je l'associe à leur req.sessionID, puis récupérez les données dans la base de données, comme les paniers d'achat et la session utilisateur.

donc ma question est de savoir si j'ai besoin de stocker des cookies? parce que je peux y accéder via req.sessionID pour obtenir les données nécessaires.

Et le second

J'ai effectué l'authentification à l'aide d'un passport-google-oauth20. Une fois la connexion établie, les données sont enregistrées dans la session. et pour l'envoyer au client je dois l'envoyer via la requête URL ?token='sdsaxas'.

dans ce cas, je reçois beaucoup de divergences d'opinion. quelqu'un l'a enregistré dans le stockage local et quelqu'un l'a enregistré dans des cookies en le convertissant en jeton à l'aide de JWT.

 jwt.sign(
        payload,
        keys.jwt.secretOrPrivateKey, 
        {
            expiresIn:keys.jwt.expiresIn // < i dont know what is this expired for cookies or localstorage ?
        }, (err, token) => {

            res.redirect(keys.Origin.url + "?token=" + token);
        });

la conclusion est que tout est lié à la session, donc je peux tout faire avec sessionID? sans cookies ni stockage local

Seulement en récupérant une ou chaque page, actualisez et récupérez les données, puis enregistrées dans redux car j'utilise React SPA

25
Faris Dewantoro

Cette réponse est basée sur l'approche sans état et ne parle donc pas de la gestion de session traditionnelle

Vous avez posé deux questions totalement différentes:

  1. Panier - qui est plus lié à la fonctionnalité commerciale
  2. OAuth 2 & JWT - qui est lié à la sécurité et à l'authentification

En tant qu'utilisateur d'un site Web de commerce électronique, je m'attends à ce que tout article que j'ajoute à mon panier depuis mon appareil mobile lors de la navette vers mon lieu de travail, soit disponible dans le panier lorsque je me connecte au site Web depuis mon PC après être arrivé à la maison. Par conséquent, les données du panier doivent être enregistrées dans la base de données principale et liées à mon compte d'utilisateur.

En ce qui concerne l'authentification à l'aide de OAuth 2.0, le jeton d'accès JWT et/ou le jeton d'actualisation doivent être stockés quelque part sur le périphérique client, de sorte qu'une fois que l'utilisateur s'authentifie en fournissant des informations de connexion, il n'a pas besoin de fournir à nouveau ses informations d'identification pour naviguer sur le site Web. Dans ce contexte, le stockage local du navigateur, le stockage de session et les cookies sont tous des options valides. Cependant, notez qu'ici le cookie n'est lié à aucune session côté serveur. En d'autres termes, le cookie ne stocke aucun identifiant de session. Le cookie est simplement utilisé comme stockage pour le jeton d'accès qui est transmis au serveur à chaque demande http et le serveur valide ensuite le jeton à l'aide de la signature numérique pour s'assurer qu'il n'est pas falsifié et qu'il n'est pas expiré.

Bien que les trois options de stockage pour les jetons d'accès et/ou d'actualisation soient populaires, le cookie semble être l'option la plus sécurisée lorsqu'il est utilisé correctement.

Pour mieux comprendre cela, je vous recommande de lire this et this avec la spécification OAuth 2.0.

Mise à jour le 16 février 2019

J'ai dit plus tôt que les cookies semblaient être les options les plus sécurisées. Je voudrais clarifier davantage le point ici.

La raison pour laquelle je pense que le navigateur localStorage et sessionStorage n'offre pas une sécurité suffisante pour stocker les jetons d'authentification est la suivante:

  1. Si XSS se produit, le script malveillant peut facilement lire les jetons à partir de là et les envoyer à un serveur distant. Là-bas, le serveur distant ou l'attaquant n'aurait aucun problème à se faire passer pour l'utilisateur victime.

  2. localStorage et sessionStorage ne sont pas partagés entre les sous-domaines. Donc, si nous avons deux SPA exécutés sur des sous-domaines différents, nous n'obtiendrons pas la fonctionnalité SSO car le jeton stocké par une application ne sera pas disponible pour l'autre application au sein de l'organisation. Il existe certaines solutions utilisant iframe, mais celles-ci ressemblent plus à des solutions de contournement qu'à une bonne solution. Et lorsque l'en-tête de réponse X-Frame-Options Est utilisé pour éviter les attaques de détournement de clics avec iframe, toute solution avec iframe est hors de question.

Ces risques peuvent cependant être atténués en utilisant une empreinte digitale (comme mentionné dans OWASP JWT Cheat Sheet ) qui à son tour nécessite un cookie.

L'idée de l'empreinte digitale est de générer une chaîne d'octets aléatoire cryptographiquement forte. La chaîne Base64 de la chaîne brute sera ensuite stockée dans un cookie HttpOnly, Secure, SameSite avec le préfixe de nom __Secure-. Les valeurs appropriées pour les attributs de domaine et de chemin doivent être utilisées conformément aux exigences de l'entreprise. Un hachage SHA256 de la chaîne sera également transmis dans une revendication de JWT. Ainsi, même si une attaque XSS envoie le jeton d'accès JWT à un serveur distant contrôlé par un attaquant, il ne peut pas envoyer la chaîne d'origine dans le cookie et, par conséquent, le serveur peut rejeter la demande en raison de l'absence du cookie. Le cookie étant HttpOnly ne peut pas être lu par les scripts XSS.

Par conséquent, même lorsque nous utilisons localStorage et sessionStorage, nous devons utiliser un cookie pour le sécuriser. En plus de cela, nous ajoutons la restriction de sous-domaine comme mentionné ci-dessus.

Maintenant, la seule préoccupation concernant l'utilisation d'un cookie pour stocker JWT est l'attaque CSRF. Puisque nous utilisons le cookie SameSite, CSRF est atténué car les demandes intersites (AJAX ou simplement via des hyperliens) ne sont pas possibles. Si le site est utilisé dans un ancien navigateur ou dans d'autres navigateurs moins populaires qui ne prennent pas en charge le cookie SameSite, nous pouvons toujours atténuer CSRF en utilisant en outre un cookie CSRF avec une valeur aléatoire cryptographiquement forte telle que chaque AJAX lit la valeur du cookie et ajoute la valeur du cookie dans un en-tête HTTP personnalisé (sauf les requêtes GET et HEAD qui ne sont pas censées faire de modifications d'état). Étant donné que CSRF ne peut rien lire en raison de la même politique d'origine et qu'il est basé sur l'exploitation des méthodes HTTP dangereuses comme POST, PUT et DELETE, ce cookie CSRF atténuera le risque CSRF. Cette approche d'utilisation du cookie CSRF est utilisée par tous les frameworks SPA modernes. L'approche Angular est mentionnée ici .

De plus, comme le cookie est httpOnly et Secured, le script XSS ne peut pas le lire. Ainsi, XSS est également atténué.

Il peut également être utile de mentionner que XSS et l'injection de script peuvent être encore atténués en utilisant l'en-tête de réponse content-security-policy Approprié.

Autres approches d'atténuation du CSRF

  1. Variable d'état (Auth0 l'utilise) - Le client générera et transmettra à chaque demande un nonce aléatoire cryptographiquement fort auquel le serveur fera écho avec sa réponse permettant au client de valider le nonce. C'est expliqué dans doc Auth .
  2. Vérifiez toujours l'en-tête du référent et acceptez les demandes uniquement lorsque le référent est un domaine approuvé. Si l'en-tête du référent est absent ou un domaine non mis en liste blanche, rejetez simplement la demande. Lors de l'utilisation du référent SSL/TLS est généralement présent. Les pages de destination (qui sont principalement informatives et ne contiennent pas de formulaire de connexion ou de contenu sécurisé peuvent être peu détendues et permettre des demandes avec un en-tête de référent manquant)
  3. La méthode HTTP TRACE doit être bloquée sur le serveur car elle peut être utilisée pour lire le cookie httpOnly
  4. Définissez également l'en-tête Strict-Transport-Security: max-age =; includeSubDomains pour autoriser uniquement les connexions sécurisées pour empêcher tout homme du milieu d'écraser les cookies CSRF d'un sous-domaine
31
Saptarshi Basu

HTTP est un protocole sans état. Lisez cette réponse pour plus de détails, mais cela signifie essentiellement que les serveurs HTTP, tels que votre serveur Web, ne stockent aucune information sur les clients au-delà de la durée de vie d'une demande. Il s'agit d'un problème pour les applications Web, car cela signifie que vous ne vous souvenez pas de l'utilisateur connecté.

Les cookies ont été inventés comme solution à cela. Les cookies sont des données textuelles que le client et le serveur envoient dans les deux sens sur demande tous. Ils vous permettent de maintenir efficacement les données sur l'état des applications, en faisant en sorte que le client et le serveur conviennent de ce dont ils se souviennent chaque fois qu'ils communiquent.

Cela signifie, fondamentalement, que vous ne pouvez pas avoir de session sans cookie . Il y a doit être un cookie qui stocke au moins l'ID de session, afin que vous puissiez savoir quel utilisateur est actuellement connecté à votre application en recherchant la session . C'est ce que fait express-session: la documentation pour la méthode principale session note explicitement que l'ID de session est stocké dans un cookie.

donc ma question est de savoir si j'ai besoin de stocker des cookies? parce que je peux y accéder via req.sessionID pour obtenir les données nécessaires.

Vous n'avez pas besoin de stocker les cookies. express-session le fera pour vous. Votre application dans son ensemble le fait besoin de stocker un cookie; sans lui, vous n'auriez pas de req.sessionID pour rechercher.

0
Effective Robot