Diseño para la autenticación de Facebook en una aplicación iOS que también accede a un servicio web seguro

402

Objetivo: permitir que un usuario se autentique con Facebook en una aplicación de iOS que requiere acceso a un servicio web protegido que estoy ejecutando.

Suposiciones: existe un sistema de autenticación (y registro) nativo para aquellos usuarios que optan por no usar Facebook para iniciar sesión.

Detalles:

  • Supongamos que queremos ofrecer la opción para que un usuario inicie sesión con Facebook sin crear una cuenta / credencial separada para nuestro sistema.
  • Debido a que admitimos nuestro propio mecanismo de autenticación nativo (nombre de usuario y contraseña), tenemos nuestras propias ID de usuario y emitimos un token de autenticación que se utiliza para las interacciones posteriores después de la validación de credencial inicial.

Me sorprende que Facebook no tenga las mejores prácticas para esto en su documentación para desarrolladores. Toda la documentación existente supone que está incorporando la autenticación FB en un sitio web o una aplicación móvil independiente sin servicio que requiera autenticación.

Aquí están mis pensamientos iniciales sobre cómo se diseñaría esto, pero quiero validar si es correcto.

  1. El cliente muestra el inicio de sesión de Facebook iOS
  2. El usuario de la interfaz de usuario inicia sesión con credenciales de Facebook y obtiene token de acceso
  3. La aplicación iOS pasa el token de acceso a nuestro servidor
  4. Nuestro servidor se comunica con la API de gráficos FB utilizando el token de acceso para (a) validar el token y (b) obtener la ID de usuario de FB para ese token de acceso.

    por ejemplo, nuestro servidor llamaría a https://graph.facebook.com/me/?access_token=XYZ que devolvería información de perfil en un objeto JSON

  5. Suponiendo que sea válido, nuestro servidor extrae la ID de usuario del objeto JSON y verifica si el usuario ya tiene una cuenta. Si es así, emitimos nuestro propio boleto de autenticación al cliente para usar en esa sesión. Si el usuario no tiene una cuenta, creamos una nueva con la ID de usuario de Facebook, asignamos nuestra propia ID de usuario única y emitimos nuestro ticket de autenticación.

  6. El cliente luego devuelve el ticket de autenticación en las interacciones posteriores que necesitan autenticación.

Este parece ser el enfoque correcto para mí, pero no estoy seguro de si me estoy perdiendo algo increíblemente básico y estoy yendo por el camino equivocado (complicado).

TMC
fuente
1
¿Cómo se resolvió esto? Estoy buscando pasar el token de acceso también y activar al usuario en el servidor. Parece académico, pero estoy preguntando.
Chris Van Buskirk
Esta fue mi implementación utilizando rieles y diseño: stackoverflow.com/questions/7232490/…
Matt
¿Por qué no pasar todo el auth_hash en lugar de tener que hacer dos llamadas a la API de FB (una desde el dispositivo iOS y otra desde el servidor)?
bsiddiqui
1
¿Qué sucede si desea iniciar sesión desde un dispositivo diferente (lo que significa que no tiene su ticket de autenticación)? Y si acaba de recibir un nuevo boleto de autenticación, ¿qué impide que alguien secuestra la identificación / token de Facebook en el camino y la use en su propio dispositivo?
Amitloaf
Por curiosidad, en el paso 5, ¿por qué emitir su propio ticket de autenticación? ¿No podría usar el token de acceso de Facebook para cada llamada posterior al servidor? Me doy cuenta de que requeriría una llamada del servidor a la API de Facebook para cada aplicación -> llamada del servidor en lugar de solo la primera.
Anders

Respuestas:

80

Acabo de lidiar con esto yo mismo, y aquí está la parte que me mordió:

En su paso 5 ... Es posible que un usuario se registre para una cuenta con usted completamente separada de su ID de Facebook, ¿verdad? Luego, en otro momento, inician sesión con Facebook ... Y acabas de crearles una segunda cuenta y perdiste la primera.

Debe haber una manera de iniciar sesión en su servicio web, luego iniciar sesión en Facebook y capturar la asociación entre la identificación de Facebook y la cuenta local.

Aparte de eso, su plan suena sólido.

Actualización : Facebook ha agregado un documento que describe tal escenario AQUÍ

Dan Ray
fuente
77
Sí, lo he considerado y estás en el clavo. Planeamos fusionar cuentas si es la misma dirección de correo electrónico, y si no, crearemos otra forma de fusionarlas.
TMC
¿Qué biblioteca de servidor está utilizando en el lado del servidor para realizar la solicitud?
TimLeung
77
@TimLeung: entiendo que un token de acceso incrusta la ID de la aplicación y que no se puede tener un token de acceso SIN una ID de aplicación integrada.
Dan Ray
1
@TimLeunge: Estamos utilizando la API Graph para solicitudes con el token de acceso del usuario.
TMC
29

Use https para transmitir el token de autenticación a su servidor, como lo indica Facebook

Compartir tokens de acceso

Nuestras políticas de datos prohíben explícitamente compartir un token de acceso para su aplicación con cualquier otra aplicación. Sin embargo, sí permitimos que los desarrolladores compartan Tokens entre una implementación nativa y una implementación de servidor de la misma aplicación (es decir, usando la misma ID de aplicación) siempre que la transferencia se realice usando HTTPS.

zoomcrypt
fuente
16

Un problema que puedo ver con esta estrategia es que alguien puede darle un token de acceso obtenido para una aplicación de Facebook diferente. Hasta donde yo sé, no hay forma de verificar que el token de acceso sea para su aplicación, por lo que simplemente deberá seguir usándolo.

Sin embargo, no suena muy dañino. En general, las personas / aplicaciones intentan proteger los tokens de acceso, en lugar de compartirlos.

Una posible hazaña de esto sería que alguien cree su propio sitio o aplicación móvil, obtenga tokens de acceso para sus usuarios e intente autenticarlos, utilizando su API. Si esto tiene éxito (el usuario tiene una cuenta de Facebook en su sitio), el sitio malicioso podrá usar su API para hacerse pasar por el usuario.

Es un poco arriesgado, pero creo que podría funcionar.

Editar: parece que hay una manera de validar el token de acceso después de todo. Vea la respuesta de @Daaniel en la pregunta Obtenga la identificación de la aplicación del token de acceso del usuario (o verifique la aplicación de origen para un token) .

ivant
fuente
El envío appsecret_proofdebería evitar esto (ver aquí )
Tony
@ Tony, ¿puedes explicar cómo appsecret_proofayuda aquí? Según tengo entendido, sirve para demostrarle a Facebook que el servidor conoce la clave secreta. Sin embargo, ivant se refería a una aplicación maliciosa que obtenía tokens y luego los enviaba a su API. El servidor puede verificar la identificación de la aplicación, pero una aplicación maliciosa puede suplantarla fácilmente. Entonces ... ¿cómo se mitigaría esto?
YSK
3
Puede verificar que el token se generó para su aplicación a través del https://graph.facebook.com/app/?access_token=[user_access_token]cual se devuelve la identificación de la aplicación y luego se comparan los identificadores de la aplicación
Nader Alexan
4

Su solución funciona totalmente.

Tal vez una alternativa: ¿por qué no simplemente recibir el correo electrónico del cliente desde la solicitud inicial del servicio social y enviarlo a su servicio web? El servicio web podría simplemente almacenar el correo electrónico, y quizás también un proveedor social. Entiendo que su servicio web no podrá validar de dónde proviene el correo electrónico, pero ¿no existe una relación de alta confianza entre su servicio web y su cliente? Si lo hay, parece que puede depender del correo electrónico proveniente del lugar correcto. Alguien, por favor, hágame saber qué cosa obvia me estoy perdiendo que hace que el enfoque basado en correo electrónico sea tonto ...

Amsterdam
fuente
3
Podría averiguar fácilmente cómo el cliente está hablando con el servidor. Entonces podría enviarle correos electrónicos hasta que reciba un golpe. Siempre debe haber alguna forma de verificación
Chris
55
Alta confianza y cliente? Nunca en la misma oración, por favor. Excepto la oración anterior, por supuesto.
EralpB