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:
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:
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
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.
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.
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.
Le jeton d'accès et le jeton d'actualisation sont destinés à être utilisés comme suit:
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.
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".
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.