Projete para autenticação do Facebook em um aplicativo iOS que também acesse um serviço da Web seguro

402

Objetivo: permitir que um usuário se autentique com o Facebook em um aplicativo iOS que exija acesso a um serviço da Web protegido em execução.

Pressupostos: existe um sistema de autenticação (e registro) nativo para os usuários que optam por não usar o Facebook para fazer login.

Detalhes:

  • Suponha que queremos oferecer a opção de um usuário entrar no Facebook sem criar uma conta / credencial separada para o nosso sistema.
  • Como suportamos nosso próprio mecanismo de autenticação nativo (nome de usuário e senha), temos nossos próprios IDs de usuário e emitimos um token de autenticação que é usado para interações subseqüentes após a validação inicial da credencial.

Estou surpreso que o Facebook não tenha as melhores práticas para isso na documentação dos desenvolvedores. Toda a documentação existente está assumindo que você está criando a autenticação do FB em um site ou um aplicativo móvel autônomo sem serviço que exija autenticação.

Aqui estão meus pensamentos iniciais sobre como isso seria projetado, mas quero validação sobre se está correto.

  1. Cliente abre o login do Facebook no iOS
  2. O usuário da interface do usuário faz login com credenciais do Facebook e obtém o token de acesso
  3. O aplicativo iOS passa o token de acesso ao nosso servidor
  4. Nosso servidor conversa com a API gráfica do FB usando o token de acesso para (a) validar o token e (b) obter o ID do usuário do FB para esse token de acesso.

    Por exemplo, nosso servidor chamaria https://graph.facebook.com/me/?access_token=XYZ, que retornaria informações de perfil em um objeto JSON

  5. Supondo que seja válido, nosso servidor extrai o ID do usuário do objeto JSON e verifica se o usuário já possui uma conta. Nesse caso, emitimos nosso próprio tíquete de autenticação ao cliente para usar nessa sessão. Se o usuário não tiver uma conta, criamos uma nova com o ID do usuário do Facebook, atribuímos nosso próprio UserID e emitimos nosso tíquete de autenticação.

  6. O cliente passa o tíquete de autenticação novamente nas interações subseqüentes que precisam de autenticação.

Parece a abordagem certa para mim, mas não tenho certeza se estou perdendo algo insanamente básico e seguindo o caminho errado (complicado).

TMC
fonte
11
Como isso foi resolvido? Também estou olhando para passar o token de acesso e girar o usuário no servidor. Parece acadêmico, mas estou perguntando.
precisa
Esta foi a minha implementação usando trilhos e conceber: stackoverflow.com/questions/7232490/...
Matt
Por que não passar o auth_hash inteiro em vez de fazer duas chamadas para a API do FB (uma do dispositivo iOS e uma vez do servidor)?
bsiddiqui
11
E se você quiser fazer login a partir de um dispositivo diferente (o que significa que você não possui seu tíquete de autenticação)? E se você acabou de receber um novo tíquete de autenticação, o que impede alguém de seqüestrar o ID / token do Facebook no caminho e usá-lo em seu próprio dispositivo?
Amitloaf 17/04
Por curiosidade, na etapa 5, por que emitir seu próprio tíquete de autenticação? Você não pode usar o token de acesso do Facebook para todas as chamadas subseqüentes do servidor? Sei que exigiria uma chamada do servidor para a API do Facebook para cada chamada de aplicativo -> servidor, e não apenas a primeira.
Anders

Respostas:

80

Eu mesmo lidei com isso, e aqui está a parte que me mordeu:

Na sua etapa 5 ... É possível que um usuário se registre em uma conta com você totalmente separado do ID do Facebook, certo? Em outra ocasião, eles acessam o Facebook ... E você acabou de criar uma segunda conta e perder a primeira.

É necessário que haja uma maneira de fazer login no seu serviço da Web, faça login no facebook e capture a associação entre o ID do facebook e a conta local.

Além disso, seu plano parece sólido.

Atualização : o Facebook adicionou um documento descrevendo esse cenário AQUI

Dan Ray
fonte
7
Sim, eu considerei isso e você está no local. Planejamos mesclar contas se for o mesmo endereço de e-mail; caso contrário, criaremos outra maneira de mesclá-las.
TMC
Qual biblioteca de servidores você está usando no servidor para fazer a solicitação?
TimLeung 3/03
7
@ TimLeung - Meu entendimento é que um token de acesso incorpora o ID do aplicativo e que você não pode ter um token de acesso SEM um ID do aplicativo inserido nele.
Dan Ray
11
@ TimLeunge: estamos usando a API do Graph para solicitações com o token de acesso do usuário.
TMC
29

Use https para transmitir o token de autenticação ao seu servidor, conforme declarado pelo Facebook

Compartilhamento de tokens de acesso

Nossas políticas de dados proíbem explicitamente qualquer compartilhamento de um token de acesso para seu aplicativo com qualquer outro aplicativo. No entanto, permitimos que os desenvolvedores compartilhem tokens entre uma implementação nativa e uma implementação de servidor do mesmo aplicativo (por exemplo, usando o mesmo ID do aplicativo), desde que a transferência ocorra usando HTTPS.

zoomcrypt
fonte
16

Um problema que vejo com essa estratégia é que alguém pode fornecer um token de acesso obtido para um aplicativo do facebook diferente. Até onde eu sei, não há como verificar se o token de acesso é para o seu aplicativo, então você continuará usando-o.

Não parece muito prejudicial, no entanto. Geralmente, as pessoas / aplicativos tentam proteger os tokens de acesso, em vez de compartilhá-los.

Uma possível exploração disso seria, para alguém criar seu próprio site ou aplicativo móvel, obter tokens de acesso para seus usuários e tentar autenticá-los usando sua API. Se isso for bem-sucedido (o usuário tem uma conta no Facebook em seu site), o site malicioso poderá usar sua API representando o usuário.

É um tiro no escuro, mas acho que poderia funcionar.

Editar: Parece que existe uma maneira de validar o token de acesso, afinal. Veja a resposta de @Daaniel na pergunta Obtenha o ID do aplicativo no token de acesso do usuário (ou verifique o aplicativo de origem para um token) .

ivant
fonte
Envio appsecret_proofdeve evitar isso (ver aqui )
Tony
@ Tony, você pode explicar como appsecret_proofajuda aqui? Tanto quanto eu entendo, serve para provar ao Facebook que o servidor conhece a chave secreta. No entanto, ivant estava se referindo a um aplicativo mal-intencionado que obtinha tokens e os enviava para sua API. O servidor pode verificar o ID do aplicativo, mas ele pode ser facilmente falsificado por um aplicativo mal-intencionado. Então ... como alguém poderia mitigar isso?
YSK
3
Você pode verificar se o token foi gerado por seu aplicativo através de https://graph.facebook.com/app/?access_token=[user_access_token]que retorna o ID de aplicativo e, em seguida, comparando os ids de aplicativos
Nader Alexan
4

sua solução funciona totalmente.

Talvez uma alternativa: por que não receber o e-mail do cliente a partir da solicitação inicial de serviço social e enviar para o seu serviço web? O serviço da Web pode apenas armazenar o email, e talvez um provedor social também. Entendo que seu serviço da web não poderá validar a origem do email, mas não existe uma relação de alta confiança entre o serviço da web e o cliente? Se houver, parece que você pode depender do e-mail vindo do lugar certo. Alguém, por favor, deixe-me saber que coisa óbvia que estou perdendo, que torna a abordagem por e-mail boba ...

Hamsterdam
fonte
3
Eu poderia facilmente descobrir como o cliente está conversando com o servidor. Então eu poderia simplesmente enviar e-mails para ele até receber um hit. Há sempre precisa haver alguma forma de verificação
Chris
5
Alta confiança e cliente? Nunca na mesma frase, por favor. Exceto a frase anterior, é claro.
EralpB