web-dev-qa-db-fra.com

Comment sécuriser un jeton d'actualisation?

J'utilise des JWT pour authentifier les utilisateurs de mon application. Lorsqu'un utilisateur se connecte, il reçoit un jeton d'accès et un jeton d'actualisation. Pour garder le jeton d'actualisation en sécurité, je ne le stocke pas côté client, mais je l'enregistre sur le back-end avec leur compte afin qu'il ne soit pas facile d'accès. Je suis confus quant à la sécurité des jetons d'actualisation, voici la logique que je comprends lorsque je lis des ressources en ligne sur la façon d'utiliser les jetons d'actualisation:

  1. authentifier
  2. stocker le jeton d'accès + le jeton d'actualisation quelque part (dans mon cas, le jeton d'accès sur le front-end et le jeton d'actualisation sur le back-end)
  3. lors de l'exécution d'une demande d'api, valider le jeton d'accès côté api
  4. si le jeton d'accès a expiré, utilisez le jeton d'actualisation pour générer un nouveau jeton d'accès + nouveau jeton d'actualisation, renvoyez le jeton d'accès au client
  5. stocker les jetons comme avant ... et répéter

Le problème de sécurité qui m'inquiète est de savoir si quelqu'un d'autre (pirate) a mis la main sur le jeton d'accès et envoie une demande à l'API avec lui, si le jeton est expiré, l'API utilisera le jeton d'actualisation pour obtenir un nouvel accès jeton + nouveau jeton d'actualisation et renvoyez au moins le jeton d'accès au pirate.

J'ai lu cet article environ 5-6 fois et j'ai lu cet article plusieurs fois, ainsi que d'autres articles sur le sujet, ils disent tous quelque chose dans le sens de

assurez-vous de stocker le jeton d'actualisation en toute sécurité car il a une longue durée de vie, le access_token est de courte durée, donc ce n'est pas si grave

Mais selon le flux que j'ai décrit ci-dessus, peu importe si le jeton d'accès est de courte durée, le jeton d'actualisation sera utilisé pour obtenir un nouveau jeton d'accès et y avoir accès pour toujours.

Y a-t-il quelque chose qui me manque? Comment l'API pourrait-elle savoir qui envoie la demande si un pirate a mis la main sur le jeton d'accès expiré? il en enverra toujours un nouveau à l'aide du jeton d'actualisation. Suis-je censé valider d'une manière ou d'une autre qui envoie la demande?


METTRE À JOUR

Je comprends donc que lorsqu'un nouveau jeton d'accès est demandé, je dois envoyer le jeton d'actualisation, l'ID client et le secret client. Le problème que j'ai avec cela est que, comme auparavant, le pirate peut envoyer une demande à mon serveur API, le serveur obtient le jeton d'accès piraté du pirate, il verra qu'il est expiré, il enverra donc le jeton d'actualisation, avec le clientID/client secret (qui sont stockés en tant que variables d'environnement) dans l'API Auth et récupèrent un nouveau jeton d'accès/jeton d'actualisation, ce qui nous ramène au même problème.


MISE À JOUR 2

quelques questions intéressantes sur le sujet:

  1. Pourquoi OAuth v2 a-t-il à la fois des jetons d'accès et de rafraîchissement?
  2. https://security.stackexchange.com/questions/87119/how-secure-are-expiring-tokens-and-refresh-tokens

selon la deuxième question et réponse, il semble que le jeton d'actualisation ne soit pas un moyen plus sûr de maintenir l'accès, c'est simplement qu'il est plus facile de détecter un pirate parce que les jetons d'authentification/d'actualisation continuent d'être demandés et invalident les jetons de l'autre. Le problème est que cela ne se produira que si 2 utilisateurs tentent simultanément d'accéder aux ressources - si seul le pirate se trouve être actif à une période donnée, il aura un accès illimité aux données des utilisateurs d'origine jusqu'à ce que l'utilisateur d'origine essaie d'utiliser l'application et accéder aux ressources protégées

6
duxfox--

Vous ne devez pas stocker le jeton sur le serveur. Un client s'authentifie et obtient le jeton. Vous stockez le jeton dans les navigateurs dans un cookie ou localStorage. Chaque demande est autorisée avec le jeton. Si vous l'envoyez sur un canal non crypté sans SSL, il est susceptible d'être intercepté. Un pirate qui obtient le jeton leur permet de se faire passer pour l'utilisateur. Les jetons expirés ne devraient pas autoriser la réauthentification sans ressaisir les informations d'identification des utilisateurs. Les jetons expirés doivent être ignorés.

1
Adrian Brand

Il existe un bon document OAuth 2.0 pour les applications basées sur un navigateur qui décrit les meilleures pratiques pour ces applications.

Je choisirais entre garder des jetons sur le client ou le serveur. En le mélangeant (en gardant les jetons d'actualisation sur votre serveur et les jetons d'accès dans le navigateur), vous créez votre propre protocole avec ses propres vulnérabilités.

Si l'application de navigateur a besoin du jeton d'accès uniquement pour accéder à son backend, vous pouvez envisager d'utiliser votre backend en tant que client OAuth2 (qui reçoit un code d'authentification), obtenir l'identité de l'utilisateur, émettre un cookie qui maintiendra une session entre le navigateur et le backend. C'est beaucoup plus facile que d'échanger, d'actualiser et de valider des jetons OAuth2.

Si vous voulez vraiment conserver votre application de navigateur en tant que client OAuth2 qui reçoit des jetons, vous devez utiliser extension PKCE (donc le code d'authentification conservé dans les caches réseau et l'historique du navigateur ne peut pas être utilisé pour obtenir des jetons) et obtenez un nouveau jeton d'actualisation avec chaque nouveau jeton d'accès - jetez un œil au chapitre sur les jetons d'actualisation :

Les serveurs d'autorisation NE DEVRAIENT PAS émettre de jetons d'actualisation pour les applications basées sur un navigateur.

Si un serveur d'autorisation choisit d'émettre des jetons d'actualisation aux applications basées sur un navigateur, il DOIT alors émettre un nouveau jeton d'actualisation avec chaque réponse d'actualisation du jeton d'accès. Cette opération réduit le risque de fuite d'un jeton d'actualisation, car un jeton d'actualisation qui a été divulgué peut être détecté si l'attaquant et le client légitime tentent d'utiliser le même jeton d'actualisation.

Votre application de navigation peut conserver ses jetons dans sessionStorage pour survivre aux rechargements de page.

1
Ján Halaša

Dans le deuxième article que vous avez lié, il est dit que pour actualiser le jeton, vous devez publier le jeton d'actualisation et client_id et client_secret donc, fondamentalement, vous ré-authentifiez l'utilisateur lorsque vous actualisez l'accès jeton.

Pour utiliser le jeton d’actualisation, faites une demande POST au point de terminaison du jeton du service avec grant_type = refresh_token, et incluez le jeton d’actualisation ainsi que les informations d’identification du client.

0
guuus

Le jeton d'accès et le jeton d'actualisation sont destinés à être utilisés comme suit:

  1. Générez un accès expirant et actualisez le jeton lors de la connexion de l'utilisateur et envoyez-le à l'application frontale (Android, IOS, Web App).
  2. App front-end jeton d'actualisation stocké en toute sécurité dans sa base de données.
  3. L'application frontale envoie un jeton d'accès à chaque demande et JWT le vérifie sans toucher à la base de données.
  4. L'authentification fonctionne pour une durée définie du jeton d'accès.
  5. À son expiration, l'application frontale envoie un jeton d'actualisation à votre serveur, vous le vérifiez également à l'aide de JWT et vous le vérifiez également dans la base de données pour l'égalité.
  6. Le serveur génère un nouveau jeton d'accès, etc.

PS: toute la communication doit avoir lieu via HTTPS.

J'ai ma mise en œuvre basée sur la logique ci-dessus avec un jeton d'accès expirant toutes les 30 minutes et un jeton d'actualisation avec une validité d'un an.

La vérification de la mise à jour du jeton avec la base de données a également pour effet de contrôler le processus de connexion des utilisateurs et de limiter le nombre d'appareils capables d'utiliser vos applications avec le même compte.

Vous devez simplement mettre à jour le jeton d'actualisation sur le serveur chaque fois que l'utilisateur envoie à nouveau une demande de connexion.

0
Aditya T

Si vous stockez le jeton d'actualisation sur le serveur, votre serveur doit inclure un cookie de session sécurisée dans la réponse d'authentification pour identifier l'utilisateur. Vous pouvez empêcher les attaquants d'extraire des cookies de session sécurisés en définissant les cookies avec l'indicateur HttpOnly.

https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#Secure_and_HttpOnly_cookies

Le cookie ne serait pas un jeton d'actualisation. Ce serait un autre type de cookie de session. Un flux d'application dans lequel un jeton d'actualisation n'est pas renvoyé à l'utilisateur est un flux d'application d'une seule page.

https://auth0.com/docs/flows/concepts/single-page-login-flow

Dans ce flux, l'actualisation des jetons s'effectue via "l'authentification silencieuse".

https://auth0.com/docs/api-auth/tutorials/silent-authentication#initiate-a-silent-authentication-request

Une réponse d'authentification réussie si l'utilisateur a déjà une session valide dans Auth0 et aucun consentement ou autres invites ne sont nécessaires.

Nous devons donc maintenir une session en stockant un identifiant utilisateur.

0
chris.va.rao