Architecture pour fusionner plusieurs comptes d'utilisateurs ensemble

176

D'accord, j'ai un site Web sur lequel vous pouvez vous inscrire et vous connecter. Vous pouvez également vous connecter avec votre compte facebook, twitter ou linkedin.

Il est important que les utilisateurs n'aient qu'un seul compte enregistré. Donc, d'une manière ou d'une autre, je souhaite fusionner les comptes des utilisateurs s'ils utilisent différentes méthodes pour se connecter. Quelle est la meilleure solution pour résoudre ce problème?

Par exemple, l'utilisateur se connecte avec son compte Facebook. J'utilise les données pour créer automatiquement un compte pour lui. Dois-je envoyer un e-mail avec un nom d'utilisateur et un mot de passe de notre site Web? (Si cela est conforme à la politique de Facebook). Dois-je leur donner un deuxième écran où ils peuvent remplir un nom d'utilisateur et un mot de passe? Mais ce n'est pas l'idée derrière la connexion avec votre compte Facebook. Cela devrait simplifier votre procédure de participation.

Il est également possible que l'utilisateur se soit enregistré sur notre site Web et la prochaine fois qu'il se connecte avec son compte Twitter. Comment fusionner ces 2 comptes en un seul? Quelle est la meilleure façon?

Donc, fondamentalement, ma question est la suivante: j'ai 4 façons différentes pour un utilisateur de devenir membre de notre site Web. Comment puis-je m'assurer que ces 4 méthodes ne créent qu'un seul compte si un utilisateur décide d'utiliser plusieurs méthodes? Quel est le meilleur flux pour s'assurer que cela ne devienne pas un problème pour l'utilisateur lui-même?


Éditer:

3 ans après avoir posé cette question, je donne moi-même la réponse dans une série d'articles: https://www.peternijssen.nl/social-network-authentication-setup/
https://www.peternijssen.nl/social- network-authentication-google /
https://www.peternijssen.nl/social-network-authentication-merging-accounts/
https://www.peternijssen.nl/social-network-authentication-twitter-facebook/

PT
la source
7
Bien sûr, il est préférable d'essayer d'empêcher un utilisateur d'avoir plusieurs comptes en premier lieu en autorisant plusieurs méthodes de connexion comme Stack Overflow, mais même SO a la possibilité pour les modérateurs de fusionner des comptes. J'offre des primes à quiconque peut décrire une architecture pour permettre cela. Il doit y avoir une meilleure solution que "update post set UserID = 2 where UserID = 1"
David Boike
l'email et le téléphone peuvent être utilisés comme clé de fusion, d'autres?
Wuaner
Bonjour, le lien que vous avez fourni ne semble pas fonctionner. Il va à la page d'accueil du site uniquement
vigamage
Mise à jour des liens. Les articles ont cependant 6 ans.
PT

Réponses:

120

Je suis confronté à la même tâche pour le moment. Le design que j'ai élaboré est plutôt simple, mais cela fonctionne bien.

L'idée centrale est que les modèles d'identité de site local et les identités de site tiers restent isolés, mais sont ensuite liés. Ainsi, chaque utilisateur qui se connecte au site a une identité locale qui correspond à un nombre quelconque d'identités de site tiers.

Un enregistrement d'identité local contient un minimum d'informations - il peut même s'agir d'un seul champ - juste une clé primaire. (Pour ma candidature, je me fiche de l'adresse e-mail, du nom ou de la date de naissance de l'utilisateur - je veux juste savoir que c'est la personne qui s'est connectée à ce compte depuis le début.)

Les identités de tiers contiennent des informations pertinentes uniquement pour l'authentification auprès d'un tiers. Pour OAuth, cela signifie généralement un identifiant d'utilisateur (comme un identifiant, un e-mail ou un nom d'utilisateur) et un identifiant de service (indiquant avec quel site ou service a été authentifié). Dans d'autres parties de l'application, en dehors de la base de données, cet identifiant de service est associé à une méthode pour récupérer l'identifiant d'utilisateur pertinent à partir de ce service, et c'est ainsi que l'authentification est effectuée. Pour OpenID, nous utilisons la même approche, sauf que la méthode d'authentification est plus généralisée (car nous pouvons presque toujours exécuter exactement le même protocole - sauf que nous utilisons une URL d'identité différente, et c'est notre identifiant de service).

Enfin, je garde une trace de quelles identités tierces sont associées à quelle identité locale. Pour générer ces enregistrements, le flux ressemble à ceci:

  • Un utilisateur se connecte pour la première fois en utilisant une identité tierce. Un enregistrement d'identité local est créé, puis un enregistrement d'identité tiers, puis ils sont appariés.
  • Dans un panneau de contrôle, l'utilisateur a la possibilité de lier un compte en se connectant à des services tiers. (Comment cela fonctionne assez simple.)
  • Dans le scénario où l'utilisateur crée involontairement plusieurs comptes, la solution est assez simple. Alors que l'utilisateur est connecté sur l'un des comptes, il se connecte à un autre qu'il utilisait auparavant pour se connecter au site (via la fonction du panneau de contrôle ci-dessus). Le service Web détecte cette collision (que l'identité locale de l'utilisateur connecté diffère de l'identité locale qui est liée à l'identité tierce qui vient de se connecter) et l'utilisateur est invité à une fusion de compte.

La fusion de comptes consiste à fusionner chaque champ individuel de l'identité locale (qui variera d'une application à l'autre, et devrait être facile si vous n'avez que quelques champs dans vos documents d'identité locaux), puis à garantir les identités tierces liées. sont liées à l'identité locale résultante.

joue
la source
1
C'est une très bonne solution (j'adore l'idée de détecter automatiquement la collision d'identité locale)! Je me demande si vous avez trouvé un moyen de connecter automatiquement l'utilisateur aux comptes "supplémentaires" qui sont liés après la première connexion à l'application. L'utilisateur devrait-il se connecter séparément à chaque compte à chaque visite (s'il n'y a pas déjà de session active avec ce fournisseur)?
Alexandra
@Alexandra Qu'entendez-vous par «comptes supplémentaires»? Demandez-vous ce qui se passe lorsque l'utilisateur se connecte à l'application via plusieurs authentificateurs différents, créant une nouvelle identité locale avec chacun?
cheeken
Je suppose que cela justifie une clarification appropriée et sa propre question: stackoverflow.com/questions/11060368/...
Alexandra
3
Question cependant, mais que se passe-t-il si l'utilisateur s'inscrit sur le site en utilisant la même adresse e-mail? leur demandons-nous que l'e-mail existe déjà (l'e-mail provenant du modèle tiers) ou nous les enregistrons toujours sur le site, puis nous avons fusionné ces comptes?
user962206
@ user962206 de nombreux services ne vous fourniront pas la «vraie» adresse e-mail de toute façon pour des raisons de confidentialité. Par exemple, Twitter ne vous donnera aucune adresse e-mail, pour autant que je sache, Facebook donnera "[email protected]" que je doute que quelqu'un utilise pour l'enregistrement.
kapex
45

J'ai tendance à trouver de nombreux sites qui fusionnent en fonction du courrier électronique comme facteur de chevauchement.

Je peux voir que c'est une option viable, mais encore une fois, cela dépend de votre préférence sur la façon de fusionner. L'adresse e-mail est le principal moyen utilisé par les gens pour vérifier certains changements importants d'informations sur votre site, comme le changement de mot de passe, la résiliation du service, le solde du compte est faible, etc. C'est presque comme le système de numéro de sécurité sociale du Web, mais avec la capacité de communication . Culturellement: je pense qu'il est raisonnable de supposer qu'un e-mail est une identité assez unique dans les services d'authentification OAuth. Certes, c'est ce que demandent les formulaires de connexion pour Facebook et Google.

Mon processus de réflexion actuel.

La page de connexion a 3 options

  • Adhésion à votre propre site
  • Se connecter avec Facebook
  • Connectez-vous avec google

1) Connexion utilisateur pour la première fois: déclenchez un flux d'enregistrement où un compte est créé et rempli pour la première fois.

 if the user logins using Facebook (or whatever 3rd party login)
      1) call the Facebook api asking for their information (email, name, etc...) 
      2) create an account membership entry in your database somewhat like this 

         Table = Users
         [ UserId   |       Email             | Password ]
         [    23     | "[email protected]" |  *null*  ]

      3) create an external auths entry like so
         *ProviderUserId is the unique id of that user on the provider's site

         Table = ExternalAuths
         [ ExternalAuthId  |  User_UserId   | ProviderName |   ProviderUserId  ]
         [    56           |      23        |   Facebook   |  "max.alexander.9"]

 if the user wants to create an account with your own registration it would just be this           

         Table = Users
         [ UserId   |       Email           |   Password  ]
         [    23     | [email protected] |  myCoolPwd  ]

2) À un autre moment, l'utilisateur revient mais décide de cliquer sur Google Login

      1) call the Google api asking for their information (email, name, etc...) 

      2) once you get the email, match it up to the userId entry with the existing email 

      3) create an additional External auth entry as such

         Table = ExternalAuths
         [ ExternalAuthId  |  User_UserId   | ProviderName |   ProviderUserId  ]
         [    56           |      23        |   Facebook   |  "max.alexander.9"]
         [    57           |      23        |    Google    |  "1234854368"     ]

3) Maintenant que vous avez fusionné sur le compte pour lequel vous faites confiance, les e-mails de vos entrées de base de données sont les mêmes que ceux auxquels vous faites confiance à partir des connexions externes.

Donc pour les connexions suivantes

Alors, que faire si vous avez d'abord des connexions externes et que vous souhaitez ensuite qu'un utilisateur puisse se connecter avec un mot de passe plus tard?

Je vois deux façons simples de le faire

  • Lors de toute première connexion lorsqu'un compte est créé à partir d'une authentification externe, demandez-leur un mot de passe pour terminer leur première entrée dans votre application

  • S'ils se sont déjà enregistrés en utilisant Facebook ou Google en premier, ils voulaient en quelque sorte s'inscrire en utilisant le formulaire d'inscription de votre propre site. Détectez si l'adresse e-mail qu'ils ont saisie existe déjà, demandez-leur un mot de passe et envoyez-leur un e-mail de confirmation une fois l'enregistrement terminé.

Max Alexander
la source
1
Lorsque vous utilisez un schéma d'authentification externe (Facebook, Google, Twitter, etc.), vous n'aurez jamais accès au mot de passe du fournisseur externe. Le mot de passe dans l'exemple ci-dessus est le mot de passe de votre propre application Web.
Max Alexander
6
Twitter ne propose pas de courrier électronique aux utilisateurs. Ainsi, après leur première authentification, si le Twitter UserId n'existe pas, demandez-lui un email et un mot de passe. Si l'e-mail et le mot de passe existent, associez les comptes. Si ce n'est pas le cas, stockez l'e-mail et le mot de passe pour des authentifications ultérieures transparentes. Cela a-t-il été utile du tout?
Max Alexander
1
En remarque, il est désormais possible de demander des autorisations pour votre application Twitter afin d'obtenir l'adresse e-mail de l'utilisateur.
Sunil D.
2
Facebook oblige-t-il les gens à vérifier leur e-mail? Je sais que Github, par exemple, ne le fait pas. Un utilisateur malveillant pourrait s'inscrire à Github avec le nom de messagerie de quelqu'un d'autre, puis accéder à son compte sur votre site avec cette stratégie. (L'API de Github vous indique si leur adresse e-mail est vérifiée ou non - vous pouvez refuser toute authentification avec Github sur une adresse e-mail non vérifiée)
Matthew Moisen
7
Il s'agit d'une faille de sécurité si un utilisateur s'inscrit via les réseaux sociaux, modifie son adresse e-mail dans les réseaux sociaux, quelqu'un d'autre prend la même adresse e-mail, s'inscrit sur les réseaux sociaux, puis se connecte, il sera fusionné avec le compte de quelqu'un d'autre. C'est très improbable mais une brèche néanmoins. Ou est-ce que je manque quelque chose.
Shane
35

J'ai vécu ça avec sled.com. Il y a plusieurs problèmes ici en ce qui concerne la création de comptes et la prise en charge de plusieurs comptes tiers pour la connexion. Certains d'entre eux sont:

  • Avez-vous besoin de prendre en charge à la fois un mot de passe local et des connexions tierces?

Pour sled.com, j'ai décidé de supprimer le mot de passe local en raison de la faible valeur qu'il ajoute et du coût supplémentaire lié à la sécurisation d'un formulaire de saisie de mot de passe. Il existe de nombreuses attaques connues pour casser des mots de passe et si vous prévoyez d'introduire des mots de passe, vous devez vous assurer qu'ils ne sont pas faciles à casser. Vous devez également les stocker dans un hachage à sens unique ou quelque chose de similaire pour éviter qu'ils ne fuient.

  • Quelle flexibilité souhaitez-vous autoriser pour prendre en charge plusieurs comptes tiers?

Il semble que vous ayez déjà choisi les trois fournisseurs de connexion: Facebook, Twitter et LinkedIn. C'est génial car cela signifie que vous utilisez OAuth et que vous travaillez avec un ensemble bien défini de fournisseurs de confiance. Je ne suis pas fan d'OpenID. La question restante est de savoir si vous devez prendre en charge plusieurs comptes tiers du même fournisseur (par exemple, un compte local avec deux comptes Twitter liés). Je suppose que non, mais si vous le faites, vous devrez intégrer cela dans votre modèle de données.

Pour Sled, nous prenons en charge la connexion avec Facebook, Twitter et Yahoo! et dans chaque compte utilisateur, stockez une clé pour chacun: {"_id": "djdjd99dj", "yahoo": "dj39djdj", twitter: "3723828732", "facebook": "12837287"}. Nous avons mis en place un certain nombre de contraintes pour nous assurer que chaque compte tiers ne peut être lié qu'à un seul compte local.

Si vous prévoyez d'autoriser plusieurs comptes du même fournisseur tiers, vous devrez utiliser des listes ou d'autres structures pour prendre en charge cela, et avec cela, toutes les autres restrictions pour garantir l'unicité.

  • Comment lier plusieurs comptes?

La première fois que l'utilisateur s'inscrit à votre service, il se rend d'abord chez le fournisseur tiers et revient avec un identifiant tiers vérifié. Vous créez ensuite un compte local pour eux et collectez toutes les autres informations que vous souhaitez. Nous recueillons leur adresse e-mail et leur demandons également de choisir un nom d'utilisateur local (nous essayons de pré-remplir le formulaire avec leur nom d'utilisateur existant de l'autre fournisseur). Avoir une certaine forme d'identifiant local (e-mail, nom d'utilisateur) est très important pour la récupération du compte plus tard.

Le serveur sait qu'il s'agit d'une première connexion si le navigateur n'a pas de cookie de session (valide ou expiré) pour un compte existant et que le compte tiers utilisé n'est pas trouvé. Nous essayons d'informer l'utilisateur qu'il ne se connecte pas simplement, mais qu'il crée un nouveau compte afin que s'il a déjà un compte, il se mettra en pause et se connectera avec son compte existant à la place.

Nous utilisons exactement le même flux pour lier des comptes supplémentaires, mais lorsque l'utilisateur revient du tiers, la présence d'un cookie de session valide est utilisée pour différencier une tentative de lier un nouveau compte à une action de connexion. Nous n'autorisons qu'un seul compte tiers de chaque type et s'il y en a déjà un lié, bloquez l'action. Cela ne devrait pas poser de problème car l'interface pour lier un nouveau compte est désactivée si vous en avez déjà un (par fournisseur), mais juste au cas où.

  • Comment fusionner des comptes?

Si un utilisateur tente de lier un nouveau compte tiers déjà lié à un compte local, vous lui demandez simplement de confirmer qu'il souhaite fusionner les deux comptes (en supposant que vous puissiez gérer une telle fusion avec votre ensemble de données - souvent plus facile à dire que fait). Vous pouvez également leur fournir un bouton spécial pour demander une fusion, mais en pratique, tout ce qu'ils font est de lier un autre compte.

C'est une machine à états assez simple. L'utilisateur revient du tiers avec un identifiant de compte tiers. Votre base de données peut être dans l'un des trois états suivants:

  1. Le compte est lié à un compte local et aucun cookie de session n'est présent -> Connexion
  2. Le compte est lié à un compte local et un cookie de session est présent -> Fusionner
  3. Le compte n'est pas lié à un compte local et aucun cookie de session n'est présent -> Inscription
  4. Le compte n'est pas lié à un compte local et un cookie de session est présent -> Lier un compte supplémentaire

    • Comment effectuer la récupération de compte avec des fournisseurs tiers?

C'est encore un territoire expérimental. Je n'ai pas vu une expérience utilisateur parfaite pour cela, car la plupart des services fournissent à la fois un mot de passe local à côté des comptes tiers et se concentrent donc sur le cas d'utilisation "oublié mon mot de passe", pas sur tout ce qui peut mal tourner.

Avec Sled, nous avons choisi d'utiliser "Besoin d'aide pour vous connecter?" et lorsque vous cliquez, demandez à l'utilisateur son adresse e-mail ou son nom d'utilisateur. Nous recherchons et si nous trouvons un compte correspondant, envoyez à cet utilisateur un lien qui peut automatiquement le connecter au service (bon pour une fois). Une fois arrivés, nous les dirigeons directement vers la page d'association de comptes, leur disons qu'ils devraient jeter un coup d'œil et éventuellement associer des comptes supplémentaires, et leur montrer les comptes tiers qu'ils ont déjà liés.

Marteau d'Eran
la source
Cette solution est bien meilleure pour moi, merci!
Roy Shoa
2
Le cookie de session n'est pas assez bon pour identifier l'utilisateur. Et si un autre utilisateur utilise le même appareil?
DeepBlue
23

Les deux approches pour la fusion automatique des comptes laissent une vulnérabilité assez grande qui permettrait à quelqu'un de prendre en charge un compte. Ils semblent tous deux faire l'hypothèse que l'utilisateur est celui qu'ils prétendent être lorsqu'ils offrent l'option de fusion à un utilisateur qui s'enregistre.

Ma recommandation pour atténuer la vulnérabilité est de demander à l'utilisateur de s'authentifier auprès de l'un des fournisseurs d'identité connus avant d'effectuer la fusion pour vérifier l'identité de l'utilisateur.

Exemple: l'utilisateur A s'enregistre avec l'identité Facebook. Quelque temps plus tard, ils retournent sur votre site et tentent d'accéder avec Windows Live ID et démarrent le processus d'enregistrement. Votre site demandera à l'utilisateur A avec ... Il semble que vous vous êtes déjà inscrit sur Facebook. Veuillez vous connecter avec Facebook (fournir le lien) et nous pourrons fusionner votre identifiant Windows Live avec votre profil existant.

Une autre alternative consiste à stocker un secret partagé (mot de passe / question personnelle) sur l'enregistrement initial que l'utilisateur doit fournir lors de la fusion des identités, mais cela vous ramène à l'entreprise de stockage des secrets partagés. Cela signifie également que vous devez gérer le scénario dans lequel l'utilisateur ne se souvient pas du secret partagé et du flux de travail qui l'accompagne.

Brad J
la source
que faites-vous si vous ne recevez pas d'adresse e-mail du fournisseur?
fred.kassi
1

La plupart des publications sont assez anciennes et je suppose que le service gratuit d' authentification Firebase de Google n'était pas encore disponible. Après la vérification avec OAuth, vous lui transmettez le jeton OAuth et obtenez un identifiant d'utilisateur unique que vous pouvez stocker pour référence. Les fournisseurs pris en charge sont Google, Facebook, Twitter, GitHub et il existe une option pour enregistrer des fournisseurs personnalisés et anonymes.

galki
la source
Il existe des cas d'utilisation où Firebase n'a pas de sens. Par exemple, les systèmes intranet qui ont plus d'une connexion ..
Bostwick
-4

Vous devez autoriser la connexion à partir d' un compte, puis une fois connecté, donnez la possibilité d'ajouter un autre compte à fusionner avec lui.

Naftali alias Neal
la source
4
Et que se passe-t-il si l'utilisateur ne fait pas cela et se retrouve avec 4 comptes distincts? Comment créer une architecture permettant une fusion dans ce cas?
David Boike
Selon vos besoins, cela peut en fait être une suggestion valable. Je veux juste avertir ceux qui pensent que la fusion ou la liaison de comptes pourrait être faite plus tard comme après: si vous pensez que c'est quelque chose que vous voudrez peut-être plus tard, vous voudrez vous préparer à cela au début avec la conception de votre base de données: Un L'option est d'avoir un UserGroup et un UserMapping. Vous pouvez mapper l'ID utilisateur OAuth ou l'ID utilisateur E-mail et mot de passe à un groupe d'utilisateurs.
BumbleB2na