Como devo arquitetar um serviço da web RESTful para usar terceiros (por exemplo, Google, Facebook, Twitter) para autenticação?

25

Para o meu trabalho, temos um bom serviço web RESTful que construímos que usamos para dirigir alguns sites que temos. Basicamente, o serviço da web permite criar e trabalhar com tíquetes de suporte, e o site é responsável pelo front-end. Quaisquer solicitações de serviço da web usam um cabeçalho de autenticação que usamos para validar o usuário e sua senha para cada chamada.

Este ano, pretendemos expandir nossas opções de login para que os usuários do site possam efetuar login via Google, Twitter e Facebook (possivelmente outros). No entanto, estou tendo muitos problemas para descobrir como arquitetar isso para que o serviço da Web possa usar os provedores de autenticação de terceiros para garantir que os usuários sejam quem eles dizem que são. Existem práticas recomendadas por aí para fazer isso?

Atualmente, estamos pensando em ter o site para autenticar os próprios usuários e, em seguida, usar uma nova chamada setSessionId que registra sua sessão atual com o back-end do serviço da web. Cada solicitação adicional ao serviço da Web passará esse sessionId e o validará. Parece bom, mas tenho a sensação de que não estou pensando nisso e todo o meu fórum navegando e lendo oauth e especificações abertas está apenas me confundindo mais. Alguma dica de como lidar com isso?

Ralph Callaway
fonte
nada realmente errado com o que você está sugerindo. Acho que é mais fácil olhar para código de exemplo de integração OpenID do que o OAuth real e especificações OpenID ...
astronauta
Qual idioma / plataforma você está usando? Você não precisa reinventar a roda, pois existem estruturas para ajudá-lo substancialmente. :)
RobM
@Rob O serviço da web está hospedado no Salesforce.com, mas é acessado por meio de um proxy que, no momento em que este documento foi escrito, é Node.js. Dito isto, parece que a pergunta geral se aplicaria a todas as plataformas. E sim, eu espero usar uma estrutura em vez de reinventar a roda, apenas não sei qual roda usar.
Ralph Callaway
@ Ralph Sim, a questão geral é independente da plataforma, mas tem implicações práticas, já que a plataforma geralmente restringe bastante suas opções de estrutura. Então, você criou um aplicativo front-end personalizado usando o node.js em um repositório de dados e serviços da Web hospedado pelo salesforce? Você precisa armazenar informações de usuário / identidade no back-end ou apenas autenticação e autorização em ações no front-end?
RobM
@RobM sim, queremos armazenar informações do usuário no back-end, como e-mail, nome, sobrenome e mais tudo o que for necessário para validar chamadas futuras dos consumidores de serviços da web depois de autenticados.
Ralph Callaway

Respostas:

14

Parece que existem dois objetivos:

  1. Fácil para os usuários finais se autenticarem com suas contas sociais existentes
  2. Fácil para desenvolvedores que usam seu serviço da web

Autorizar as pessoas a usar recursos em seu site faz do OAuth2 um mecanismo preferido devido à popularidade e disponibilidade das bibliotecas clientes.

1. Fácil para os usuários finais se autenticarem com suas contas sociais existentes

O usuário final visita um site que usa sua API e escolhe fazer login. Eles são enviados para sua página de login do OAuth. Sua página de login mostra um nome de usuário e senha normais para as contas gerenciadas em seu site e um conjunto de botões de autenticação social nas quais eles podem clicar para fazer login em um site como o Facebook. Quando o usuário escolhe o Facebook, você os redireciona para o Facebook para aprovar a escolha (iniciando o fluxo de autenticação do Facebook). Quando o usuário final conclui o login no Facebook, ele é redirecionado de volta ao seu site.

Quando o usuário é redirecionado de volta para o seu site a partir do Facebook, você salva as informações desse usuário em um registro do usuário no banco de dados e gera uma nova sessão para esse usuário. Você redireciona imediatamente o usuário final para o site downstream original com o oauth access_token, concluindo o fluxo oauth original.

2. Fácil para desenvolvedores que usam seu serviço da web

Se você é o provedor de autorização, deve criar uma interface simples para os desenvolvedores dependerem do que não muda toda vez que você adiciona um novo provedor de autenticação upstream que não implementa oauth perfeitamente. É por isso que acredito que você deve implementar um site de provedor OAuth2 e esse site deve ser consumidor dos sites de autenticação social.

Para o desenvolvedor que usa sua API de descanso agradável, ele não estará ciente da interação do Facebook, a menos que você opte por dar uma dica na postagem de captura de sessão (por exemplo).

TL; DR

Torne os consumidores de suas APIs como você implementando o OAuth2 e ocultando as complexidades de autenticação social. Você pode, durante o fluxo de oauth dos sites downstream, disparar um fluxo de oauth adicional com o facebook.

Imagem porque imagem == palavras * 1000:

insira a descrição da imagem aqui

Podemos chamar isso de oauth2-piggy-back?

Fluxo passo a passo

  1. O usuário final visita o site que usa sua API
  2. O usuário final é enviado ao seu site para autorizar ou se inscrever (oauth2)
  3. O usuário final escolhe a autenticação social, clica no botão de login do facebook
  4. Seu site define um cookie ou oauth stateno facebook para saber de onde o usuário veio
  5. Usuário final redirecionado para o Facebook e aceita conexão no site do facebook
  6. Usuário final redirecionado ao seu site para concluir o processo de autenticação do facebook
  7. Você procura ou cria o usuário no seu banco de dados
  8. Você cria uma nova sessão no seu servidor
  9. Você redireciona o usuário de volta ao site original com seu token de sessão
James Sullivan
fonte
5

Como torná-lo extensível

Primeiro, observe que todas essas APIs usam o mesmo mecanismo para efetuar login. Todas elas usam OAuth para autenticação. Você precisa aproveitar isso começando com uma biblioteca geral do OAuth. Não use suas próprias bibliotecas para autenticação, pois elas serão inutilizáveis ​​para outros provedores. Se você pegar o jeito do OAuth2, é muito fácil adicionar mais provedores.

Infelizmente, você precisa de dois deles, porque o twitter ainda não pulou na onda do OAuth2.

O OAuth precisa que você crie uma interface para a parte de autenticação. Os tokens serão trocados de servidor para servidor. Crie um ponto de entrada, capaz de lidar com toda a comunicação.

O token deve ser armazenado em uma tabela separada da sua conta, pois podem ser vários tokens e vários perfis vinculados. Alguns serviços oferecem dois tokens, um deles é um token de atualização.

Agora você cria uma interface que encapsula as outras funcionalidades necessárias. Pessoalmente, eu configuraria um serviço REST separado para isso. Dessa forma, você pode estender facilmente a autenticação para outros lugares.
Alguns serviços usam JSON para se comunicar, outros usam XML etc. Para o usuário inicial, você precisa unificar todos eles. Este é um processo bastante doloroso, mas é possível derivar alguns motivos comuns aqui.

Outro problema aqui é que nem todos os serviços oferecem a mesma funcionalidade. Isso pode significar que seus serviços não podem fornecer a API completa conforme você especificou. Você precisa ter uma estratégia aqui, que permita que o aplicativo faça o downgrade gracioso.

Isso garante que você pode adicionar novos fornecedores de terceiros com facilidade.

Problemas de token

Os tokens são limitados no tempo, portanto, você precisa de algumas tarefas cron, que podem verificar se o token ainda é utilizável; caso contrário, você deve excluí-lo. Você também pode atualizar um token por esse mecanismo.

Às vezes acontece que um usuário retrai o token. Esteja pronto para isso.

Armazenamento de dados

Se você possui esse design, precisa pensar nos dados necessários. Isso ocorre em parte da sua interface recém-criada. Crie algumas tabelas para isso e verifique se os dados são realmente recuperáveis. Alguns serviços não permitem que você pegue muitos dados. Você também deve levar em consideração que, quanto mais dados forem necessários, mais pesadas serão as mensagens de privacidade. Portanto, seja modesto em suas necessidades, caso contrário, os usuários não o usarão.

Para verificação extra, você pode armazenar os perfis em uma tabela separada, mas vinculada aos seus usuários. Isso fornecerá muito mais informações sobre alguém.

Verifique também as leis locais, para alguns dados, você precisa de precauções extras.

Última coisa: não cometa a falha em não criar uma conta em seus próprios serviços. Se o usuário for banido do facebook, ele não poderá efetivamente fazer login no seu serviço. Esta é uma situação que você não deseja criar. Isso geralmente é esquecido.

Edgar Klerks
fonte
1

Definitivamente, eu escolheria a solução que parece que você já descobriu: implementando a autenticação de terceiros no site voltado para o cliente e associando esses tokens de autenticação de terceiros às contas de usuário do site e, finalmente, acionando sua chamada setSessionID entrar.

Dependendo da arquitetura do site, você pode achar muito útil usar uma biblioteca como EveryAuth ou Passport .

Rex
fonte
1

Meus dois centavos: nunca fiz nada assim antes e nem sei como funcionam os mecanismos de login do FB, Twitter ou Google, mas alguns problemas surgiram na minha cabeça assim que li sua pergunta:

  • Vários logins: o que acontece se eu entrar na minha conta do Facebook um dia e minha conta do Google no dia seguinte? Ou simultaneamente? Você trata essas duas contas como contas únicas e separadas ou deve ter algum método para associá-las e permitir que eu acesse meus tickets de qualquer maneira?
  • Confiando em identificadores externos: o que acontece quando o Facebook ou o Twitter decidem mudar a aparência de seus identificadores de conta? Para ilustrar, se o BazLogin representa uma conta exclusiva usando o código {4382-af56}, mas decide que a partir de agora as contas terão 12 dígitos porque 8 não foram suficientes, como informar {1234-4382-af56} de {0000-4382 -af56}?

Podemos lidar com esses dois problemas escolhendo associar as contas externas a uma conta interna, não apenas a um ID de sessão. Então, um login externo pode ser apenas um gateway para a criação de uma conta interna. Se eu me autenticar com mais de um método de login, você pode me dizer que já estou logado. Se um provedor de autenticação externo alterar algo em que confiamos, poderíamos solicitar ao usuário que forneça o nome e a senha da conta interna e crie um nova associação para logins futuros.

Não sei se resolvi os problemas que você tinha em mente, mas você realmente não mencionou nenhuma preocupação concreta. Espero que minha resposta tenha sido útil, de qualquer maneira.

idobia
fonte