Há muitas perguntas feitas aqui, e parece que, embora as perguntas sejam feitas no contexto do Node e do passport.js, as perguntas reais são mais sobre fluxo de trabalho do que como fazer isso com uma tecnologia específica.
Vamos usar a configuração de exemplo do @Keith, modificada um pouco para aumentar a segurança:
- O servidor da Web em
https://example.com
serve um aplicativo cliente Javascript de página única
- O serviço da web RESTful em
https://example.com/api
fornece suporte ao servidor para aplicativo rich client
- Servidor implementado no Node e no passport.js.
- O servidor possui um banco de dados (qualquer tipo) com uma tabela "users".
- Nome de usuário / senha e Facebook Connect são oferecidos como opções de autenticação
- O Rich Client faz solicitações REST em
https://example.com/api
- Pode haver outros clientes (aplicativos de telefone, por exemplo) que usam o serviço da Web em,
https://example.com/api
mas não conhecem o servidor da Web em https://example.com
.
Observe que estou usando HTTP seguro. Na minha opinião, isso é obrigatório para qualquer serviço disponível ao ar livre, pois informações confidenciais como senhas e tokens de autorização estão passando entre o cliente e o servidor.
Autenticação de nome de usuário / senha
Vamos ver como a autenticação antiga simples funciona primeiro.
- O usuário se conecta a
https://example.com
- O servidor serve um aplicativo Javascript avançado que renderiza a página inicial. Em algum lugar da página existe um formulário de login.
- Muitas das seções deste aplicativo de página única não foram preenchidas com dados devido ao fato de o usuário não estar conectado. Todas essas seções têm um ouvinte de evento em um evento de "login". Tudo isso é coisa do lado do cliente, o servidor não conhece esses eventos.
- O usuário digita seu login e senha e pressiona o botão Enviar, que aciona um manipulador Javascript para registrar o nome de usuário e a senha nas variáveis do lado do cliente. Em seguida, esse manipulador aciona o evento "login". Novamente, isso é tudo ação do lado do cliente, as credenciais ainda não foram enviadas para o servidor .
- Os ouvintes do evento "login" são chamados. Agora, cada um deles precisa enviar uma ou mais solicitações à API RESTful
https://example.com/api
para obter os dados específicos do usuário a serem renderizados na página. Todas as solicitações enviadas ao serviço da Web incluirão o nome de usuário e a senha, possivelmente na forma de autenticação HTTP Basic , pois o serviço RESTful não tem permissão para manter o estado do cliente de uma solicitação para a próxima. Como o serviço da Web está em HTTP seguro, a senha é criptografada com segurança durante o trânsito.
- O serviço da Web
https://example.com/api
recebe um monte de solicitações individuais, cada uma com informações de autenticação. O nome de usuário e a senha em cada solicitação são verificados no banco de dados do usuário e, se encontrados corretamente, a função solicitada é executada e os dados são retornados ao cliente no formato JSON. Se o nome de usuário e a senha não corresponderem, um erro será enviado ao cliente na forma de um código de erro HTTP 401.
- Em vez de forçar os clientes a enviar nome de usuário e senha com todas as solicitações, você pode ter uma função "get_access_token" em seu serviço RESTful que pega o nome de usuário e a senha e responde com um token, que é algum tipo de hash criptográfico exclusivo e com alguma validade data associada a ele. Esses tokens são armazenados no banco de dados com cada usuário. Em seguida, o cliente envia o token de acesso em solicitações subsequentes. O token de acesso será validado no banco de dados, em vez do nome de usuário e senha.
- Aplicativos clientes que não são navegadores, como aplicativos de telefone, fazem o mesmo que acima, eles solicitam que o usuário insira suas credenciais e os envie (ou um token de acesso gerado a partir deles) com todas as solicitações ao serviço da web.
O ponto importante deste exemplo é que os serviços da Web RESTful requerem autenticação com cada solicitação .
Uma camada adicional de segurança nesse cenário adicionaria autorização de aplicativo cliente, além da autenticação do usuário. Por exemplo, se você tiver os aplicativos cliente da Web, iOS e Android usando o serviço da Web, poderá desejar que o servidor saiba qual dos três é o cliente de uma determinada solicitação, independentemente de quem é o usuário autenticado. Isso pode permitir que seu serviço da web restrinja determinadas funções a clientes específicos. Para isso, você pode usar chaves e segredos da API. Consulte esta resposta para obter algumas idéias sobre isso.
Autenticação do Facebook
O fluxo de trabalho acima não funciona para a conexão com o Facebook porque o login via Facebook possui terceiros, o próprio Facebook. O procedimento de login exige que o usuário seja redirecionado para o site do Facebook, onde as credenciais são inseridas fora do nosso controle.
Então, vamos ver como as coisas mudam :.
- O usuário se conecta a
https://example.com
- O servidor serve um aplicativo Javascript avançado que renderiza a página inicial. Em algum lugar da página, existe um formulário de login que inclui o botão "Login com o Facebook".
- O usuário clica no botão "Login with Facebook", que é apenas um link que redireciona para (por exemplo)
https://example.com/auth/facebook
.
- A
https://example.com/auth/facebook
rota é tratada pelo passport.js (consulte a documentação )
- Tudo o que o usuário vê é que a página muda e agora eles estão em uma página hospedada no Facebook, onde precisam fazer login e autorizar nosso aplicativo da web. Isso está completamente fora do nosso controle.
- O usuário se conecta ao Facebook e dá permissão para a nossa aplicação, de modo Facebook agora redireciona para a URL de retorno que nós configurado na configuração passport.js, que seguindo o exemplo na documentação é
https://example.com/auth/facebook/callback
- O manipulador passport.js da
https://example.com/auth/facebook/callback
rota invocará a função de retorno de chamada que recebe o token de acesso do Facebook e algumas informações do usuário do Facebook, incluindo o endereço de e-mail do usuário.
- Com o email, podemos localizar o usuário em nosso banco de dados e armazenar o token de acesso do Facebook.
- A última coisa que você faz no retorno de chamada do Facebook é redirecionar de volta para o aplicativo rich client, mas desta vez precisamos passar o nome de usuário e o token de acesso ao cliente para que ele possa usá-los. Isso pode ser feito de várias maneiras. Por exemplo, variáveis Javascript podem ser adicionadas à página por meio de um mecanismo de modelo do servidor, ou um cookie pode ser retornado com essas informações. (obrigado a @RyanKimber por apontar os problemas de segurança ao passar esses dados no URL, como sugeri inicialmente).
- Portanto, agora iniciamos o aplicativo de página única mais uma vez, mas o cliente tem o nome de usuário e o token de acesso.
- O aplicativo cliente pode acionar o evento "login" imediatamente e permitir que as diferentes partes do aplicativo solicitem as informações necessárias no serviço da web.
- Todas as solicitações enviadas para
https://example.com/api
incluirão o token de acesso do Facebook para autenticação ou o próprio token de acesso do aplicativo gerado a partir do token do Facebook por meio de uma função "get_access_token" na API REST.
- Os aplicativos que não são de navegador têm um pouco mais de dificuldade aqui, porque o OAuth requer um navegador da Web para efetuar login. Para fazer login em um aplicativo de telefone ou desktop, você precisará iniciar um navegador para redirecionar para o Facebook e, pior ainda, É necessário que o navegador transmita o token de acesso do Facebook de volta ao aplicativo por meio de algum mecanismo.
Espero que isso responda à maioria das perguntas. É claro que você pode substituir o Facebook pelo Twitter, Google ou qualquer outro serviço de autenticação baseado em OAuth.
Eu estaria interessado em saber se alguém tem uma maneira mais simples de lidar com isso.
passport-facebook
. Depois que você começar a trabalhar, o próximo passo é começar a entender como o Passport funciona e como ele armazena credenciais. Conectá-lo ao Restify ( veja aqui uma versão atualizada da mencionada) seria uma das últimas etapas (ou você pode implementar a interface REST no Express).