web-dev-qa-db-fra.com

Faut-il stocker les accesstoken dans notre base de données pour oauth2?

J'ai une obligation d'implémenter la connexion Facebook et Google dans mon application Web. J'ai également besoin d'accéder à la liste d'amis Facebook/Google + d'un utilisateur. J'ai parcouru la documentation OAuth2 complète de Facebook et Google. J'ai compris le concept de base. Par exemple, disons que pour la connexion à Facebook, les étapes sont les suivantes:

  1. L'utilisateur cliquera sur le bouton "FB Login".
  2. L'utilisateur sera invité à se connecter à Facebook et à autoriser l'autorisation. Si l'utilisateur le permet, il retournera un code d'autorisation.
  3. Nous allons maintenant utiliser le code d'autorisation pour obtenir un jeton d'accès.
  4. Nous pouvons stocker le jeton d'accès en session pour démarrer une session utilisateur.
  5. Maintenant, nous pouvons utiliser le jeton d'accès pour accéder à différentes ressources utilisateur.

Maintenant, j'ai une certaine confusion après l'étape 3. Faut-il générer un jeton d'accès à chaque fois que l'utilisateur se connecte ou stocker le jeton d'accès dans notre base de données?

Si nous stockons le jeton d'accès dans notre base de données, comment nous pouvons le réutiliser lorsqu'un utilisateur arrive sur notre site après 10 jours (disons qu'il a effacé les cookies du navigateur) et cliquez à nouveau sur le bouton "Connexion FB". Parce que lorsque l'utilisateur clique à nouveau sur le bouton "Connexion FB", il obtiendra un nouveau code d'autorisation et devra recommencer le processus complet. Comment puis-je reconnaître que cet utilisateur possède déjà un jeton d'accès dans ma base de données?

Toute aide serait grandement appréciée.

90

Techniquement, vous pouvez stocker le jeton d'accès dans votre base de données et l'utiliser pour les appels d'API jusqu'à son expiration. Cela pourrait être plus difficile que sa valeur.

D'une part, comme le note Jonathan dans son commentaire ci-dessus, vous devez maintenant vous soucier de la sécurité de votre base de données et des données qu'elle contient - ces jetons donnent accès à des informations assez privilégiées sur vos utilisateurs. Bien sûr, le simple stockage du jeton dans le stockage de session peut également le placer sur le disque, selon la configuration de votre session. C'est une bonne idée de le garder crypté pendant que vous ne l'utilisez pas.

Votre scénario proposé concernant la suppression et le retour des cookies par l'utilisateur est également un problème. Vous pouvez prendre le jeton d'accès de la base de données et le coller dans leurs cookies, mais avant de le faire, vous devez vous assurer qu'ils sont bien ceux qu'ils disent être - et maintenant vous devez faire une autre couche de mots de passe juste pour leur donner l'accès au jeton qu'ils vous ont déjà donné.

Vous feriez probablement mieux de simplement refaire le flux d'autorisation à leur retour et de cliquer à nouveau sur le bouton de connexion. Ce n'est pas ça cher. Mais si c'est vraiment un spectacle pour vous, alors le stockage du jeton est une option. Vous devrez simplement faire très attention à résoudre tous les problèmes associés.

34
Bruce

J'y ai pensé et j'ai peut-être trouvé une réponse qui fonctionnera pour nous, bien que je ne puisse pas dire si cela fonctionnerait pour vous.

Dans notre environnement, la principale raison pour laquelle nous pourrions avoir besoin d'utiliser des jetons d'accès est d'opérer au nom d'un utilisateur après la fin d'un processus automatisé ou de backend, ou selon un calendrier. Dans un tel scénario, nous ne pouvons pas simplement demander à l'utilisateur de se reconnecter parce que l'utilisateur n'est pas directement impliqué dans ce flux de travail (il aurait demandé que le travail soit fait mais n'est pas là quand il se termine). Nous devons donc avoir accès au jeton d'accès d'une manière ou d'une autre.

Bien sûr, je voudrais ignorer la réautorisation lorsque cela est possible, si cela ne pose pas de problème.

Mais je n'aime pas non plus l'idée de stocker tout le nécessaire pour utiliser le jeton d'accès sur le serveur Web. Donc, même si je crypte le jeton d'accès dans la base de données, cela n'apaise pas vraiment mes craintes si la clé de cryptage est stockée sur le serveur Web. Heck, le secret client et l'ID d'application sont là aussi, donc c'est tout.

Voici donc ma solution proposée, qui nécessite quatre acteurs:

serveur Web stocke l'appid, le secret et la chaîne de connexion à la base de données (bien sûr). Lorsqu'il obtient un jeton d'application, il génère une clé de chiffrement symétrique aléatoire et chiffre le jeton d'accès. Le base de données obtient le jeton d'accès crypté et la clé de cryptage est stockée dans un cookie client. Dans le même temps, le serveur Web envoie la clé de chiffrement et l'ID utilisateur au système principal sous forme de paire.

Lorsque le client utilise le site, la réauthentification peut être évitée en utilisant le cookie client pour décrypter le jeton d'accès dans la base de données; si le cookie disparaît, la réauthentification doit se produire quoi qu'il arrive. Le système dorsal (qui aurait une surface d'attaque beaucoup plus petite que le serveur Web) a également une chaîne de connexion DB, c'est donc le seul endroit où toutes les informations nécessaires résideraient pour interagir avec les informations utilisateur; il pourrait utiliser les informations à volonté pendant la durée de vie du jeton d'accès.

Cela ne laisse au serveur Web qu'un accès transitoire à n'importe quel jeton d'accès et le jeton n'est jamais stocké sur le client. Cela me semble assez sûr, même si certains diront peut-être que c'est trop conçu. Pensées?

13
Dominic P

Je pense qu'il y a une certaine confusion sur le jeton d'accès et la façon dont il est utilisé, ce qui peut entraîner un problème de sécurité.

Il est vrai que les jetons peuvent constituer un risque pour la sécurité, mais cela dépend des informations que vous demandez au service. Une liste d'amis est plus d'informations que le prénom et le nom de famille par exemple, mais ces informations ne sont pas aussi vitales que les informations personnelles. Dans les deux cas, vous ne voulez JAMAIS exposer le jeton d'accès réel, car cela revient à exposer un mot de passe à votre application.

Je choisis de créer un "jeton" secondaire, si vous voulez, qui contient une valeur de session (par exemple, une valeur de session cryptée dans les cookies) qui identifie l'utilisateur jusqu'à son expiration. J'ai donc le jeton d'accès dans la base de données (devrait probablement être crypté, juste pour être sûr) qui peut accéder aux informations utilisateur.

Vous pouvez également récupérer l'ID de la personne via le jeton. Si vous stockez au moins cela dans la base de données, vous pouvez faire correspondre le jeton récupéré via l'ID de la personne. De cette façon, lorsque vous échangez un code pour le jeton d'accès, vous pouvez comparer les ID et trouver le bon enregistrement.

3
Mark

Beaucoup de ces réponses sont obsolètes car elles ont été écrites avant l'adoption généralisée des jetons Web JSON (JWT).

Vous devez considérer un access_token comme ayant une paire e-mail/mot de passe en main, il doit donc être stocké et transmis en toute sécurité. Un access_token ne doit pas contenir trop d'informations, juste un ID utilisateur dans la portée sub d'un JWT suffit. Étant donné que JWT empêche les modifications malveillantes de la charge utile, vous pouvez utiliser en toute sécurité la subvention et l'ID qui y sont stockés.

Le stockage d'un access_token sur un serveur peut être un peu difficile pour la plupart des applications, car vous pouvez simplement utiliser une courte expiration sur vos access_tokens, en stockant un refresh_token à la place (appels DB moins fréquents). Si vous avez besoin d'informations utilisateur, stockez-les dans un jeton ID et utilisez-les uniquement pour afficher des informations sur l'utilisateur authentifié.

Demandez à nouveau le jeton ID chaque fois que vous souhaitez actualiser ces informations et ne soumettez JAMAIS un id_token à une API.

De nos jours, les développeurs intelligents mettent en œuvre OpenID Connect pour standardiser leurs informations utilisateur et leurs autorisations d'accès en plus de OAuth 2.0 et je commencerais par là car la plupart des fournisseurs d'identification (IdP) mettent en œuvre cette spécification (par exemple Google, Facebook, Auth0, YourServiceHere).

1
SacWebDeveloper

Je recommanderais de stocker des jetons si jamais vous atteigniez votre bail maximum sur les jetons dans l'application que vous utilisez. Cependant, plutôt que la base de données, je suggère d'utiliser Redis. Si un jeton est perdu, l'application doit être configurée pour continuer à fonctionner de sorte qu'elle n'a pas besoin de persister à long terme et Redis est beaucoup plus rapide que d'utiliser la base de données et il existe également des implémentations Redis très simples qui ne devraient pas prendre longtemps se lever et courir.

1
Dean Swiatek