Arquitetura para mesclar várias contas de usuário

176

Ok, eu tenho um site onde você pode se registrar e fazer login. Você também pode fazer login com sua conta do facebook, twitter ou linkedin.

É importante que os usuários tenham apenas uma conta registrada. Então, de alguma forma, quero mesclar as contas dos usuários se eles usarem métodos diferentes para fazer login. Qual é a melhor solução para resolver isso?

Por exemplo, o usuário efetua login com sua conta do Facebook. Eu uso os dados para registrar uma conta automaticamente. Devo enviar um e-mail com um nome de usuário e senha do nosso site? (Se isso estiver de acordo com a política do Facebook). Devo dar a eles uma segunda tela onde eles possam preencher um nome de usuário e senha? Mas essa não é a idéia por trás do login com sua conta do Facebook. Deve simplificar o seu procedimento para participar.

Também é possível que o usuário tenha se registrado em nosso site e na próxima vez que fizer login com sua conta do twitter. Como posso mesclar essas duas contas como uma? Qual é a melhor maneira?

Então, basicamente, minha pergunta é: eu tenho quatro maneiras diferentes pelas quais um usuário se torna membro do nosso site. Como posso garantir que todas essas quatro maneiras criem apenas uma conta se um usuário decidir usar várias maneiras? Qual é o melhor fluxo para garantir que ele não se torne um aborrecimento para o próprio usuário?


Editar:

Três anos depois de fazer essa pergunta, estou respondendo em uma série de artigos: 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
fonte
7
É claro que é melhor tentar impedir que um usuário tenha várias contas em primeiro lugar, permitindo vários métodos de login como o Stack Overflow, mas mesmo o SO pode permitir que os moderadores mesclem contas. Estou oferecendo recompensa para quem pode descrever uma arquitetura para permitir isso. Tem que haver uma solução melhor do que "update pós conjunto UserID = 2, onde UserID = 1"
David Boike
email e telefone podem ser usados ​​como chave de mesclagem, outros?
Wuaner
Olá, o link que você forneceu não parece funcionar. Ele vai apenas para a página inicial do site
vigamage
Atualizado os links. Os artigos têm 6 anos de idade.
PT

Respostas:

120

Eu estou enfrentando exatamente a mesma tarefa no momento. O design que elaborei é bastante simples, mas funciona bem.

A idéia principal é que os modelos para uma identidade de site local e de terceiros sejam mantidos isolados, mas posteriormente vinculados. Portanto, todo usuário que faz login no site tem uma identidade local que é mapeada para qualquer número de identidades de sites de terceiros.

Um registro de identidade local contém um mínimo de informações - pode até ser um único campo - apenas uma chave primária. (Para meu aplicativo, não me importo com o e-mail, o nome ou a data de nascimento do usuário. Quero apenas saber que eles são a pessoa que faz login nesta conta o tempo todo.)

As identidades de terceiros contêm informações relevantes apenas para autenticação com terceiros. Para o OAuth, isso normalmente significa um identificador de usuário (como um ID, email ou nome de usuário) e um identificador de serviço (indicando em qual site ou serviço foi autenticado). Em outras partes do aplicativo, fora do banco de dados, esse identificador de serviço é associado a um método para recuperar o identificador de usuário relevante desse serviço e é assim que a autenticação é realizada. Para o OpenID, empregamos a mesma abordagem, exceto que o método de autenticação é mais generalizado (porque quase sempre podemos executar exatamente o mesmo protocolo - exceto que usamos uma URL de identidade diferente e esse é o nosso identificador de serviço).

Por fim, mantenho um registro de quais identidades de terceiros estão emparelhadas com a identidade local. Para gerar esses registros, o fluxo fica assim:

  • Um usuário efetua login pela primeira vez usando uma identidade de terceiros. Um registro de identidade local é criado, depois um registro de identidade de terceiros e, em seguida, eles são emparelhados.
  • Em um painel de controle, é oferecida ao usuário a oportunidade de vincular uma conta efetuando login em serviços de terceiros. (Muito simples como isso funciona.)
  • No cenário em que o usuário involuntariamente cria várias contas, a solução é bastante simples. Enquanto o usuário está conectado a uma das contas, ele faz login em outra que ele usava anteriormente para acessar o site (através do recurso do painel de controle acima). O serviço da Web detecta essa colisão (que a identidade local do usuário conectado difere da identidade local que está vinculada à identidade de terceiros que acabou de fazer login) e o usuário é solicitado com uma mesclagem de conta.

Mesclar contas é uma questão de mesclar cada campo individual da identidade local (que varia de aplicativo para aplicativo e deve ser fácil se você tiver apenas alguns campos nos registros de identidade local) e garantir as identidades de terceiros vinculadas estão vinculados à identidade local resultante.

cheeken
fonte
1
Essa é uma solução muito boa (adoro a idéia de detectar automaticamente a colisão de identidade local)! Gostaria de saber se você encontrou uma maneira de fazer login automático do usuário nas contas "extras" vinculadas após o primeiro login no aplicativo. O usuário precisaria fazer login separadamente em cada conta sempre que visitar (se ainda não houver uma sessão ativa com esses provedores)?
Alexandra
@Alexandra O que você quer dizer com "contas extras"? Você está perguntando o que acontece quando o usuário efetua login no aplicativo por meio de vários autenticadores diferentes, criando uma nova identidade local para cada um?
cheeken
Eu acho que isso justifica um esclarecimento adequado e sua própria pergunta: stackoverflow.com/questions/11060368/…
Alexandra
3
Pergunta, no entanto, mas e se o usuário se registrar no site usando o mesmo endereço de e-mail? solicitamos que o e-mail já exista (o e-mail proveniente do modelo de terceiros) ou ainda os registramos no site e depois mesclamos essas contas?
usar o seguinte comando
@ user962206 muitos serviços não fornecem o endereço de e-mail 'real' de qualquer maneira por motivos de privacidade. Por exemplo, o Twitter não fornecerá nenhum endereço de e-mail, até onde eu sei, o Facebook fornecerá "[email protected]", que duvido que alguém usaria para se registrar.
Kapex
44

Costumo encontrar muitos sites mesclados com base no email como o fator de junção sobreposto.

Eu posso ver que essa é uma opção viável, mas novamente depende da sua preferência em como mesclar. O endereço de e-mail é a principal maneira que as pessoas usam para verificar algumas alterações importantes de informações em seu site, como alterar sua senha, término de serviço, saldo da conta baixo etc. É quase como o sistema de números de segurança social da web, mas com a capacidade de comunicação . Culturalmente: acho razoável supor que um email seja uma identidade bastante única nos serviços de autenticação OAuth. É verdade que os formulários de login do Facebook e do Google pedem.

Meu processo de pensamento atual.

A página de login tem 3 opções

  • Associação ao seu próprio site
  • Entrar com o Facebook
  • Entre com o google

1) Logins de usuários pela primeira vez: acionam um fluxo de registro no qual uma conta é criada e preenchida pela primeira vez.

 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) Em outro momento, o usuário volta, mas decide clicar no Login do Google

      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) Agora você mesclou a conta em que confia no email das entradas do banco de dados e as mesmas em logins externos.

Portanto, para logins subsequentes

E se você tiver logins externos primeiro e desejar que um usuário possa fazer login com uma senha posteriormente?

Eu vejo duas maneiras fáceis de fazer isso

  • Em qualquer primeiro login quando uma conta é criada a partir de uma autenticação externa, solicite uma senha para concluir a primeira entrada no aplicativo.

  • Se eles já se registraram usando o facebook ou o google primeiro, de alguma forma desejaram se registrar usando o formulário de registro do seu próprio site. Detecte se o endereço de e-mail digitado já existe, peça uma senha e envie uma confirmação por e-mail após a conclusão do registro.

Max Alexander
fonte
1
Quando você usa um esquema de autenticação externa (Facebook, Google, Twitter etc.), nunca terá acesso à senha do provedor externo. A senha no exemplo acima é a senha do seu aplicativo da web OWN.
Max Alexander
6
O Twitter não oferece o email dos usuários. Após a primeira autenticação, se o ID do usuário do Twitter não existir, solicite um e-mail e senha. Se o email e a senha existirem, vincule as contas. Caso contrário, armazene o email e a senha para autenticações subsequentes contínuas. Isso foi útil?
Max Alexander
1
Como observação lateral, agora é possível solicitar permissões para o seu aplicativo do Twitter para obter o endereço de email do usuário.
Sunil D.
2
O facebook faz as pessoas verificarem seus emails? Eu sei que o Github, por exemplo, não. Um usuário mal-intencionado pode se inscrever no Github com o nome de e-mail de outra pessoa e obter acesso à conta dele no site com essa estratégia. (API do Github faz dizer-lhe se o seu e-mail é verificado ou não - você poderia rejeitar qualquer autenticação com Github em um endereço de e-mail não verificado)
Matthew Moisen
6
Essa é uma violação de segurança se um usuário se inscrever nas mídias sociais, editar seu endereço de email nas mídias sociais, alguém pegar o mesmo endereço de email, registrado nas mídias sociais e, em seguida, efetuar login, ele será mesclado com a conta de outra pessoa. Isso é muito improvável, mas não deixa de ser uma violação. Ou eu estou esquecendo de alguma coisa.
Shane
35

Eu já passei por isso com sled.com. Existem vários problemas aqui relacionados à criação de contas e ao suporte a várias contas de terceiros para login. Alguns deles são:

  • Você precisa oferecer suporte a uma senha local e logins de terceiros?

No sled.com, decidi descartar a senha local devido ao pequeno valor agregado e ao custo adicional na proteção de um formulário de entrada de senha. Existem muitos ataques conhecidos para quebrar senhas e, se você quiser introduzir senhas, verifique se elas não são fáceis de quebrar. Você também precisa armazená-los em um hash unidirecional ou algo semelhante para impedir que eles vazem.

  • Quanta flexibilidade você deseja permitir no suporte a várias contas de terceiros?

Parece que você já escolheu os três provedores de login: Facebook, Twitter e LinkedIn. Isso é ótimo porque significa que você está usando o OAuth e trabalhando com um conjunto bem definido de fornecedores confiáveis. Não sou fã do OpenID. A questão restante é se você precisa oferecer suporte a várias contas de terceiros do mesmo provedor (por exemplo, uma conta local com duas contas do Twitter vinculadas). Suponho que não, mas se você aceitar, precisará acomodar isso em seu modelo de dados.

Para o Sled, apoiamos o login com o Facebook, Twitter e Yahoo! e em cada conta de usuário, armazene uma chave para cada um: {"_id": "djdjd99dj", "yahoo": "dj39djdj", twitter: "3723828732", "facebook": "12837287"}. Configuramos várias restrições para garantir que cada conta de terceiros possa ser vinculada apenas a uma única conta local.

Se você deseja permitir várias contas do mesmo provedor, precisará usar listas ou outras estruturas para dar suporte a isso e, com isso, todas as outras restrições para garantir a exclusividade.

  • Como vincular várias contas?

Na primeira vez em que o usuário se inscreve no seu serviço, ele primeiro acessa o provedor de terceiros e volta com uma identificação de terceiros verificada. Você, então, cria uma conta local para eles e coleta qualquer outra informação que desejar. Coletamos o endereço de e-mail e também pedimos que eles escolham um nome de usuário local (tentamos preencher previamente o formulário com o nome de usuário existente de outro provedor). Ter alguma forma de identificador local (email, nome de usuário) é muito importante para a recuperação da conta posteriormente.

O servidor sabe que esse é um primeiro login se o navegador não tiver um cookie de sessão (válido ou expirado) para uma conta existente e se a conta de terceiros usada não for encontrada. Tentamos informar ao usuário que eles não estão apenas efetuando login, mas estão criando uma nova conta para que, se já tiverem uma conta, esperemos pausar e fazer login com a conta existente.

Usamos exatamente o mesmo fluxo para vincular contas adicionais, mas quando o usuário volta de terceiros, a presença de um cookie de sessão válido é usada para diferenciar entre uma tentativa de vincular uma nova conta a uma ação de login. Permitimos apenas uma conta de terceiros de cada tipo e, se já houver uma vinculada, bloqueamos a ação. Não deve ser um problema porque a interface para vincular uma nova conta será desativada se você já tiver uma (por provedor), mas apenas por precaução.

  • Como mesclar contas?

Se um usuário tentar vincular uma nova conta de terceiros que já esteja vinculada a uma conta local, basta solicitar que eles confirmem que desejam mesclar as duas contas (supondo que você possa lidar com essa mesclagem com seu conjunto de dados - geralmente é mais fácil dizer do que feito). Você também pode fornecer a eles um botão especial para solicitar uma mesclagem, mas, na prática, tudo o que eles estão fazendo é vincular outra conta.

Esta é uma máquina de estado bastante simples. O usuário volta de terceiros com um ID de conta de terceiros. Seu banco de dados pode estar em um dos três estados:

  1. A conta está vinculada a uma conta local e nenhum cookie de sessão está presente -> Login
  2. A conta está vinculada a uma conta local e um cookie de sessão está presente -> Mesclar
  3. A conta não está vinculada a uma conta local e nenhum cookie de sessão está presente -> Inscrição
  4. A conta não está vinculada a uma conta local e um cookie de sessão está presente -> Vinculando conta adicional

    • Como executar a recuperação de contas com terceiros?

Este ainda é um território experimental. Não vi um UX perfeito para isso, pois a maioria dos serviços fornece uma senha local ao lado das contas de terceiros e, portanto, concentra-se no caso de uso "esqueci minha senha", nem em tudo o que pode dar errado.

Com o Sled, optamos por usar "Precisa de ajuda para fazer login?" e quando você clicar, peça ao usuário o email ou o nome de usuário. Procuramos em busca e, se encontrarmos uma conta correspondente, envie um e-mail para o usuário com um link que possa automaticamente registrá-lo no serviço (válido uma vez). Quando entramos, os levamos diretamente para a página de vinculação da conta, informamos que devem dar uma olhada e potencialmente vinculam contas adicionais e mostramos as contas de terceiros que já vincularam.

Eran Hammer
fonte
Esta solução é muito melhor para mim, obrigado!
Roy Shoa 16/09
2
O cookie de sessão não é bom o suficiente para identificar o usuário. E se outro usuário usar o mesmo dispositivo?
DeepBlue
23

Ambas as abordagens para mesclar contas automaticamente deixam uma vulnerabilidade bastante grande que permitiria que alguém assumisse o controle de uma conta. Ambos parecem supor que o usuário é quem ele diz ser quando oferece a opção de mesclagem para um usuário registrado.

Minha recomendação para atenuar a vulnerabilidade é solicitar que o usuário se autentique com um dos provedores de identidade conhecidos antes de executar a mesclagem para verificar a identidade do usuário.

Exemplo: o usuário A se registra com a identidade do Facebook. Algum tempo depois, eles retornam ao seu site e tentam acessar com o Windows Live ID e iniciam o processo de registro. Seu site solicitará ao usuário A ... Parece que você já se registrou no Facebook anteriormente. Faça login no Facebook (forneça o link) e poderemos mesclar seu Windows Live ID com seu perfil existente.

Outra alternativa é armazenar um segredo compartilhado (senha / pergunta pessoal) no registro inicial que o usuário deve fornecer ao mesclar identidades; no entanto, isso leva você de volta ao negócio de armazenar segredos compartilhados. Isso também significa que você precisa lidar com o cenário em que o usuário não se lembra do segredo compartilhado e do fluxo de trabalho que o acompanha.

Brad J
fonte
o que você faz se não receber um endereço de e-mail do provedor?
Fred.kassi
1

A maioria das postagens é bastante antiga e acho que o serviço gratuito de autenticação do Firebase do Google ainda não existia. Após verificar com o OAuth, você passa o token do OAuth para ele e obtém um ID de usuário exclusivo que pode ser armazenado para referência. Os provedores suportados são Google, Facebook, Twitter, GitHub e há uma opção para registrar provedores personalizados e anônimos.

Galki
fonte
Existem casos de uso em que o firebase não faz sentido. Por exemplo, sistemas de intranet que têm mais de um log em ..
Bostwick
-4

Você deve permitir o login de uma conta e, ao fazer login, dê a opção de adicionar outra conta para mesclar com ela.

Naftali tcp Neal
fonte
4
E o que acontece se o usuário não fizer isso e se encontrar com 4 contas distintas? Como você cria uma arquitetura que permite uma mesclagem nesse caso?
David Boike 29/07
Dependendo das suas necessidades, isso pode realmente ser uma sugestão válida. Eu só quero avisar aqueles que pensam que a fusão ou a vinculação de contas pode ser feita mais tarde como um exemplo posterior: se você acredita que isso é algo que você pode querer mais tarde, você deve se preparar para isso no começo com o design do banco de dados: A opção é ter um UserGroup e um UserMapping. Você pode mapear o ID do usuário do OAuth ou o ID do usuário Email e Senha para um Grupo de Usuários.
BumbleB2na