Aquí se hacen muchas preguntas, y parece que a pesar de que las preguntas se hacen en el contexto de Node and passport.js, las preguntas reales se refieren más al flujo de trabajo que a cómo hacerlo con una tecnología en particular.
Usemos la configuración de ejemplo @Keith, modificada un poco para mayor seguridad:
- El servidor web
https://example.com
sirve una aplicación de cliente Javascript de una sola página
- El servicio web RESTful
https://example.com/api
proporciona soporte de servidor a la aplicación de cliente enriquecido
- Servidor implementado en Node y passport.js.
- El servidor tiene una base de datos (de cualquier tipo) con una tabla de "usuarios".
- Nombre de usuario / contraseña y Facebook Connect se ofrecen como opciones de autenticación
- El cliente rico realiza solicitudes REST en
https://example.com/api
- Puede haber otros clientes (aplicaciones telefónicas, por ejemplo) que usan el servicio web en
https://example.com/api
pero no conocen el servidor web en https://example.com
.
Tenga en cuenta que estoy usando HTTP seguro. En mi opinión, esto es imprescindible para cualquier servicio que esté disponible al aire libre, ya que la información confidencial como las contraseñas y los tokens de autorización se transfieren entre el cliente y el servidor.
Autenticación de nombre de usuario / contraseña
Veamos primero cómo funciona la autenticación antigua simple.
- El usuario se conecta a
https://example.com
- El servidor sirve una rica aplicación Javascript que representa la página inicial. En la página hay un formulario de inicio de sesión.
- Muchas de las secciones de esta aplicación de una sola página no se han rellenado con datos debido a que el usuario no ha iniciado sesión. Todas estas secciones tienen un detector de eventos en un evento de "inicio de sesión". Todo esto es del lado del cliente, el servidor no conoce estos eventos.
- El usuario ingresa su nombre de usuario y contraseña y presiona el botón Enviar, que activa un controlador de Javascript para registrar el nombre de usuario y la contraseña en las variables del lado del cliente. Entonces este controlador activa el evento "login". Nuevamente, esta es toda acción del lado del cliente, las credenciales aún no se enviaron al servidor .
- Se invoca a los oyentes del evento "login". Cada uno de estos ahora debe enviar una o más solicitudes a la API RESTful
https://example.com/api
para obtener los datos específicos del usuario para representar en la página. Cada solicitud que envíen al servicio web incluirá el nombre de usuario y la contraseña, posiblemente en forma de autenticación HTTP básica , ya que el servicio RESTful no puede mantener el estado del cliente de una solicitud a la siguiente. Dado que el servicio web está en HTTP seguro, la contraseña se cifra de forma segura durante el tránsito.
- El servicio web en
https://example.com/api
recibe un montón de solicitudes individuales, cada una con información de autenticación. El nombre de usuario y la contraseña en cada solicitud se comparan con la base de datos del usuario y, si se encuentra correcta, la función solicitada se ejecuta y los datos se devuelven al cliente en formato JSON. Si el nombre de usuario y la contraseña no coinciden, se envía un error al cliente en forma de un código de error 401 HTTP.
- En lugar de obligar a los clientes a enviar un nombre de usuario y una contraseña con cada solicitud, puede tener una función "get_access_token" en su servicio RESTful que toma el nombre de usuario y la contraseña y responde con un token, que es una especie de hash criptográfico que es único y tiene cierta caducidad. fecha asociada a ella. Estos tokens se almacenan en la base de datos con cada usuario. Luego, el cliente envía el token de acceso en solicitudes posteriores. El token de acceso se validará con la base de datos en lugar del nombre de usuario y contraseña.
- Las aplicaciones cliente que no son del navegador, como las aplicaciones del teléfono, hacen lo mismo que antes, le piden al usuario que ingrese sus credenciales y luego las envía (o un token de acceso generado a partir de ellas) con cada solicitud al servicio web.
El punto importante de este ejemplo es que los servicios web RESTful requieren autenticación con cada solicitud .
Una capa adicional de seguridad en este escenario agregaría la autorización de la aplicación del cliente además de la autenticación del usuario. Por ejemplo, si tiene el cliente web, las aplicaciones iOS y Android que usan el servicio web, es posible que desee que el servidor sepa cuál de los tres es el cliente de una solicitud determinada, independientemente de quién sea el usuario autenticado. Esto puede permitir que su servicio web restrinja ciertas funciones a clientes específicos. Para esto, puede usar claves y secretos de API, consulte esta respuesta para obtener algunas ideas al respecto.
Autenticación de Facebook
El flujo de trabajo anterior no funciona para Facebook Connect porque el inicio de sesión a través de Facebook tiene un tercero, el propio Facebook. El procedimiento de inicio de sesión requiere que el usuario sea redirigido al sitio web de Facebook donde las credenciales se ingresan fuera de nuestro control.
Así que veamos cómo cambian las cosas:
- El usuario se conecta a
https://example.com
- El servidor sirve una rica aplicación Javascript que representa la página inicial. En la página hay un formulario de inicio de sesión que incluye un botón "Iniciar sesión con Facebook".
- El usuario hace clic en el botón "Iniciar sesión con Facebook", que es solo un enlace que lo redirige (por ejemplo)
https://example.com/auth/facebook
.
- La
https://example.com/auth/facebook
ruta es manejada por passport.js (ver la documentación )
- Todo lo que el usuario ve es que la página cambia y ahora está en una página alojada en Facebook donde necesita iniciar sesión y autorizar nuestra aplicación web. Esto está completamente fuera de nuestro control.
- El usuario inicia sesión en Facebook y da permiso a nuestra aplicación, por lo que Facebook ahora redirige a la URL de devolución de llamada que configuramos en la configuración de passport.js, que siguiendo el ejemplo en la documentación es
https://example.com/auth/facebook/callback
- El controlador passport.js para la
https://example.com/auth/facebook/callback
ruta invocará la función de devolución de llamada que recibe el token de acceso de Facebook y cierta información del usuario de Facebook, incluida la dirección de correo electrónico del usuario.
- Con el correo electrónico podemos ubicar al usuario en nuestra base de datos y almacenar el token de acceso de Facebook con él.
- Lo último que hace en la devolución de llamada de Facebook es redirigir nuevamente a la aplicación de cliente enriquecido, pero esta vez necesitamos pasar el nombre de usuario y el token de acceso al cliente para que pueda usarlos. Esto se puede hacer de varias maneras. Por ejemplo, las variables de Javascript se pueden agregar a la página a través de un motor de plantillas del lado del servidor, o bien se puede devolver una cookie con esta información. (gracias a @RyanKimber por señalar los problemas de seguridad al pasar estos datos en la URL, como sugerí inicialmente).
- Así que ahora comenzamos la aplicación de una sola página una vez más, pero el cliente tiene el nombre de usuario y el token de acceso.
- La aplicación cliente puede desencadenar el evento de "inicio de sesión" inmediatamente y dejar que las diferentes partes de la aplicación soliciten la información que necesitan del servicio web.
- Todas las solicitudes enviadas
https://example.com/api
incluirán el token de acceso de Facebook para autenticación, o el token de acceso propio de la aplicación generado a partir del token de Facebook a través de una función "get_access_token" en la API REST.
- Las aplicaciones que no son del navegador lo tienen un poco más difícil aquí, porque OAuth requiere un navegador web para iniciar sesión. Para iniciar sesión desde un teléfono o una aplicación de escritorio, deberá iniciar un navegador para redirigir a Facebook, y lo que es peor, usted necesita una forma para que el navegador pase el token de acceso de Facebook a la aplicación a través de algún mecanismo.
Espero que esto responda la mayoría de las preguntas. Por supuesto, puede reemplazar Facebook con Twitter, Google o cualquier otro servicio de autenticación basado en OAuth.
Me interesaría saber si alguien tiene una forma más sencilla de lidiar con esto.
passport-facebook
. Después de que funcione, el siguiente paso es comenzar a comprender cómo funciona Passport y cómo almacena las credenciales. Conectarlo a Restify ( vea aquí una versión actualizada de la que menciona) sería uno de los últimos pasos (o podría implementar la interfaz REST en Express).