¿Cómo debo diseñar un servicio web RESTful para usar un tercero (es decir, Google, Facebook, Twitter) para la autenticación?

25

Para mi trabajo, tenemos un buen servicio web RESTful que hemos desarrollado y que utilizamos para manejar un par de sitios web que tenemos. Básicamente, el servicio web le permite crear y trabajar con tickets de soporte, y el sitio web es responsable del front-end. Cualquier solicitud de servicio web utiliza un encabezado de autenticación que utilizamos para validar al usuario y su contraseña para cada llamada.

Este año buscamos expandir nuestras opciones de inicio de sesión para que los usuarios en el sitio web puedan iniciar sesión a través de Google, Twitter y Facebook (posiblemente otros). Sin embargo, tengo muchos problemas para descubrir cómo diseñar esto para que el servicio web pueda usar los proveedores de autenticación de terceros para garantizar que los usuarios sean quienes dicen ser. ¿Existe alguna práctica recomendada sobre cómo hacer esto?

Actualmente estamos pensando en que el sitio web maneje la autenticación de los propios usuarios y luego use una nueva llamada setSessionId que registre su sesión actual con el back-end del servicio web. Cada solicitud adicional al servicio web pasará ese ID de sesión y lo validará. Esto parece estar bien, pero tengo la sensación en el fondo de mi cabeza de que no estoy pensando en esto y toda mi búsqueda en el foro y la lectura de las especificaciones de Openid y Oauth me confunde aún más. ¿Algún consejo sobre cómo abordar esto?

Ralph Callaway
fuente
nada realmente malo con lo que estás sugiriendo. Me resulta más fácil mirar el código de ejemplo de integración de Openid que las especificaciones reales de Oauth y Openid ...
Spaceman
¿Qué idioma / plataforma estás usando? No es necesario reinventar la rueda, ya que existen marcos para ayudarlo sustancialmente. :)
RobM
@Rob El servicio web está alojado en Salesforce.com, pero se accede a él a través de un proxy que, hasta el momento, es Node.js. Dicho esto, parece que la pregunta general se aplicaría a todas las plataformas. Y sí, espero usar un marco en lugar de reinventar la rueda, solo que no estoy seguro de qué rueda usar.
Ralph Callaway
@Ralph Sí, la pregunta general es independiente de la plataforma, pero tiene implicaciones prácticas, ya que la plataforma generalmente reducirá bastante las opciones de tu marco. Entonces, ¿tiene una aplicación front-end personalizada que utiliza node.js para un repositorio de datos y servicio web alojado en salesforce? ¿Necesita almacenar información de usuario / identidad en el back-end, o solo autenticación y autorización para acciones en el front-end?
RobM
@RobM sí, queremos almacenar la información del usuario en el backend, es decir, correo electrónico, nombre, apellido, más lo que sea necesario para validar futuras llamadas de los consumidores del servicio web una vez que hayan sido autenticados.
Ralph Callaway

Respuestas:

14

Parece que hay dos objetivos:

  1. Fácil para que los usuarios finales se autentiquen con sus cuentas sociales existentes
  2. Fácil para desarrolladores que usan su servicio web

Al autorizar a las personas a usar recursos en su sitio, OAuth2 es un mecanismo preferido debido a la popularidad y disponibilidad de las bibliotecas de los clientes.

1. Fácil para que los usuarios finales se autentiquen con sus cuentas sociales existentes

El usuario final visita un sitio que usa su API y elige iniciar sesión. Se envían a su página de inicio de sesión de OAuth. Su página de inicio de sesión muestra un mensaje de nombre de usuario y contraseña normal para las cuentas administradas en su sitio y un conjunto de botones de autenticación social donde pueden hacer clic para iniciar sesión a través de un sitio como Facebook. Cuando el usuario elige Facebook, lo redirige a Facebook para aprobar la elección (iniciando el flujo de autenticación de Facebook). Cuando el usuario final completa el inicio de sesión en Facebook, se lo redirige a su sitio.

Cuando el usuario es redirigido a su sitio desde Facebook, guarda la información de ese usuario en un registro de usuario en su base de datos y luego genera una nueva sesión para ese usuario. Inmediatamente redirige al usuario final a su sitio descendente original con oauth access_token, completando el flujo original de oauth.

2. Fácil para los desarrolladores que utilizan su servicio web

Si usted es el proveedor de la autorización, debe crear una interfaz simple para que los desarrolladores dependan de la cual no cambia cada vez que agrega un nuevo proveedor de autenticación ascendente que no implementa perfectamente oauth. Es por eso que creo que debe implementar un sitio de proveedor OAuth2 y ese sitio debe ser un consumidor de los sitios de autenticación social.

Para el desarrollador que usa su API de descanso agradable, no estarán al tanto de la interacción de Facebook a menos que elija darles una pista a través de la publicación de captura de sesión (por ejemplo).

TL; DR

Haga que los consumidores de sus API como usted implementen OAuth2 y oculte las complejidades de la autenticación social. Puede, durante su flujo de oauth para sus sitios aguas abajo, activar un flujo de oauth adicional con facebook.

Imagen porque imagen == palabras * 1000:

ingrese la descripción de la imagen aquí

¿Podemos llamar a esto oauth2-piggy-back?

Paso a paso

  1. El usuario final visita el sitio que usa su API
  2. El usuario final se envía a su sitio para autorizar o registrarse (oauth2)
  3. El usuario final elige la autenticación social, hace clic en el botón de inicio de sesión de Facebook
  4. Su sitio establece una cookie o la establece stateen Facebook oauth para saber de dónde vino el usuario
  5. El usuario final es redirigido a Facebook y acepta la conexión en el sitio de Facebook
  6. Usuario final redirigido a su sitio para completar el proceso de autenticación de Facebook
  7. Busca o crea el usuario en su base de datos
  8. Creas una nueva sesión en tu servidor
  9. Redirige al usuario a su sitio original con su token de sesión
James Sullivan
fuente
5

Cómo hacerlo extensible

Primero debe notar que todas estas API usan el mismo mecanismo para iniciar sesión. Todas usan OAuth para su autenticación. Debe aprovechar esto comenzando con una biblioteca general de OAuth. No use sus propias bibliotecas para la autenticación, estas serán inutilizables para otros proveedores. Si te acostumbras a OAuth2, es bastante fácil agregar más proveedores.

Desafortunadamente, necesita dos de ellos, porque Twitter aún no ha subido al tren de OAuth2.

OAuth necesita que cree una interfaz para la parte que autentica. Los tokens se intercambiarán de servidor a servidor. Cree un punto de entrada, que pueda manejar toda la comunicación.

El token debe almacenarse en una tabla separada de su cuenta, esto se debe a que pueden ser múltiples tokens y múltiples perfiles vinculados. Algunos servicios le dan dos tokens, uno de ellos es un token de actualización.

Ahora diseña una interfaz, que encapsula la otra funcionalidad que necesita. Yo personalmente configuraría un servicio REST separado para esto. De esta manera, puede extender fácilmente la autenticación a otros lugares.
Algunos servicios utilizan JSON para comunicarse, otros utilizan XML, etc. Para el usuario frontal, debe unificarlos a todos. Este es un proceso bastante doloroso, pero es posible derivar algunos puntos comunes aquí.

Otro problema aquí es que no todos los servicios ofrecen la misma funcionalidad. Esto puede significar que sus servicios no pueden proporcionar la API completa como usted especificó. Debe tener una estrategia aquí, que permita que la aplicación baje de categoría con gracia.

Todo esto asegurará que pueda agregar fácilmente nuevos proveedores de terceros.

Problemas de token

Los tokens están limitados en el tiempo, por lo que necesita un par de trabajos cron, que pueden verificar si el token todavía es utilizable, de lo contrario, debe eliminarlo. También puede actualizar un token mediante este mecanismo.

A veces sucede que un usuario retrae el token. Prepárate para esto.

Almacenamiento de datos

Si tiene este diseño, debe pensar en los datos que necesita. Esto se debe en parte a su interfaz recién creada. Diseñe algunas tablas para esto y observe si los datos son realmente recuperables. Algunos servicios no le permiten obtener muchos datos. También debe tener en cuenta que cuantos más datos necesite, más pesados ​​serán los mensajes de privacidad. Por lo tanto, sea modesto en sus necesidades, de lo contrario los usuarios no lo usarán.

Para una verificación adicional, puede almacenar los perfiles en una tabla separada pero vinculada a sus usuarios. Esto le proporcionará mucha más información sobre alguien.

Consulte también sus leyes locales, para algunos datos necesita precauciones adicionales.

Lo último No cometa la culpa de no crear una cuenta en sus propios servicios. Si se excluye al usuario de Facebook, no podrá iniciar sesión en su servicio. Esta es una situación que no quieres crear. Esto a menudo se pasa por alto.

Edgar Klerks
fuente
1

Definitivamente, elegiría la solución que parece que ya ha descubierto: implementar la autenticación de terceros en su sitio web orientado al cliente y luego asociar esos tokens de autenticación de terceros con las cuentas de usuario de su sitio web, y finalmente activar su llamada setSessionID en iniciar sesión.

Dependiendo de la arquitectura de su sitio web, puede ser muy útil usar una biblioteca como EveryAuth o Passport .

Rex
fuente
1

Mis dos centavos: nunca antes había hecho algo así ni sé cómo funcionan los mecanismos de inicio de sesión de FB, Twitter o Google, pero surgieron algunos problemas en mi cabeza tan pronto como leí tu pregunta:

  • Inicios de sesión múltiples: ¿Qué sucede si inicio sesión con mi cuenta de Facebook un día y mi cuenta de Google al día siguiente? O al mismo tiempo? ¿Trata estas dos cuentas como cuentas únicas y separadas o debería tener algún método para asociar las dos y permitirme acceder a mis tickets de cualquier manera?
  • Confiar en identificadores externos: ¿Qué sucede cuando Facebook o Twitter deciden cambiar la apariencia de sus identificadores de cuenta? Para ilustrar, si BazLogin representa una cuenta única que usa el código {4382-af56} pero decide que a partir de ahora las cuentas tendrán 12 dígitos porque 8 no fueron suficientes, ¿cómo puede saber {1234-4382-af56} de {font>4382 -af56}?

Podemos lidiar con estos dos problemas eligiendo asociar las cuentas externas con una cuenta interna, no solo una ID de sesión. Entonces, un inicio de sesión externo podría ser solo una puerta de entrada a la creación de una cuenta interna. Si me autentico con más de un método de inicio de sesión, podría decirme que ya he iniciado sesión. Si un proveedor de autenticación externo cambia algo en lo que confiamos, podríamos pedirle al usuario que proporcione el nombre y la contraseña de su cuenta interna y cree un nueva asociación para futuros inicios de sesión.

No estoy seguro de haber abordado los problemas que tenía en mente, pero realmente no mencionó ninguna preocupación concreta. Espero que mi respuesta haya sido útil, de cualquier manera.

idoby
fuente