¿Es seguro este flujo de autenticación sin contraseña?

5

Me gustaría implementar un flujo de autenticación sin contraseña para mi aplicación móvil que solo requiere que un usuario haga clic en un enlace en su correo electrónico para iniciar sesión. Similar a cómo Slack maneja la autenticación. Usaré node y jwt para esta implementación.

Creo que se me ha ocurrido un diseño seguro, pero estoy seguro de que me estoy perdiendo algo. Me encantaría alguna crítica de la comunidad.

Aquí vamos:

  • El usuario abre la aplicación móvil.
  • Verificamos si el usuario tiene un token en su almacenamiento local.
  • Si lo hacen, agregamos ese token a sus encabezados y lo enviamos a la página de inicio de la aplicación.
  • De lo contrario, les pedimos que ingresen su correo electrónico para comenzar
  • Cuando hacen clic en "Enviar", POSTAMOS que email address al punto final requestMagicLink en nuestro servidor.
  • El servidor comprueba la base de datos de un usuario con ese email address
  • Si encontramos un usuario con ese correo electrónico, tomamos el id de ese usuario
  • Si el usuario no existe, creamos un nuevo usuario y obtenemos ese id
  • Usamos JWT para generar un token con el id , y nuestro secret que caduca después de 1 hour
  • Enviamos ese token al usuario a través de un enlace en un correo electrónico.
  • Al hacer clic, ese enlace envía una solicitud GET a nuestro servidor en el punto final magicLogin con el token en un parámetro de consulta
  • Verificamos que el token sea correcto al usar JWT y nuestro secret .
  • Si falla la verificación, redirigimos al usuario a la pantalla donde le pedimos que comience su correo electrónico.
  • Si tiene éxito, generamos un nuevo token JWT usando su id , y nuestro secret ese doesn't have an expiration , luego lo devolvemos al usuario en los parámetros de una URL que los redirige a una página de éxito en nuestra aplicación.
  • La aplicación toma el token del parámetro y lo almacena en el almacenamiento local hasta que el usuario elija cerrar sesión y el usuario se redirige a la página de inicio.
  • Todas las solicitudes a la api ahora contienen el token en los encabezados, y el usuario está listo.

EDITAR (añadiendo pensamiento adicional): Algo que estoy considerando para hacerlo más seguro: ¿Qué pasa si dividimos el token en 2 partes y enviamos la mitad al dispositivo móvil y la otra mitad al correo electrónico? De esa manera, solo el usuario con acceso a ese correo electrónico Y el acceso a ese dispositivo específico podrán autenticarse.

    
pregunta klinore 17.11.2018 - 19:03
fuente

3 respuestas

3

El concepto principal de su flujo (enlaces mágicos) es una de las alternativas de autenticación sin contraseña más conocidas. El consenso general parece ser que la seguridad de tales esquemas (como se ha señalado en los comentarios) no es peor que la de un sistema que permite los mecanismos de restablecimiento de correo electrónico de "contraseña olvidada". Esto tiene sentido teniendo en cuenta que el punto de falla ahora está en la parte del correo electrónico.

Los servidores de correo electrónico generalmente no están cifrados y el correo puede terminar almacenado en ubicaciones inseguras, como el cliente de correo del usuario. Tampoco tendrá control sobre la seguridad con la que el usuario configura su cuenta de correo electrónico. También podría ser útil (ya que a menudo se compara con él) recordar lo difícil es implementar un restablecimiento de contraseña de forma segura. Al final, si esto debería preocuparle o no, depende realmente de su modelo de amenaza y del valor de los datos de su aplicación.

Las fuentes que puedo encontrar que admiten enlaces mágicos y otros esquemas sin contraseña son principalmente de proveedores que tienen un gran interés en impulsar sus propias implementaciones de este sistema (por ejemplo, Auth0 , okta ) y hay algunos nombres importantes que ya lo admiten, como amazon-cognito. También puedes echar un vistazo a preguntas similares de esta pila:

Autenticación sin contraseña en aplicaciones web - ¿Qué tan seguro es?

Inicio de sesión sin contraseña por correo electrónico: consideraciones de seguridad

En cuanto a su implementación personalizada, hay varias preocupaciones que vale la pena mencionar:

  • No cree usuarios siempre que no haya una dirección de correo electrónico existente. Los puntos finales y los formularios web se envían regularmente como correo no deseado y encontrará su base de datos llena de basura.
  • Puede que no sea necesario enviar un token en el correo electrónico y, en su lugar, simplemente enviar un enlace directamente. Solo asegúrese de que la URL del enlace se genere de forma aleatoria y que, nuevamente, la caducidad esté configurada para deshabilitar el uso.
  • Como se mencionó anteriormente, los correos electrónicos pueden comprometerse fácilmente, por lo que debe establecer una caducidad más corta para mitigar. En la mayoría de los casos, sus usuarios accederán a su correo electrónico directamente de todas formas, así que lo mantendré en el rango de 5 a 10 minutos.
  • Después de iniciar sesión, el JWT también debe tener una caducidad, incluso si es larga. Realmente no quieres que los tokens sean válidos indefinidamente.

Para ser honesto, no recomendaría configurarlo usted mismo si puede evitarlo; Intente encontrar bibliotecas que ya admitan esta funcionalidad.

    
respondido por el AlphaD 21.11.2018 - 06:20
fuente
2

Entonces, lo que intentas hacer es implementar un nuevo "protocolo de seguridad". Tengo un mal presentimiento sobre esto porque creo que esto requiere más investigación y control de calidad que una pregunta en stackexchange. Los nuevos protocolos (Auth2) o algoritmos (AES) requieren mucho tiempo y esfuerzo en la investigación antes de que generalmente se consideren como "aprobados" o "seguros".

En general, creo que el correo no es la mejor manera de compartir tokens de acceso. Usted dice que crea un token con un secreto, envía un enlace con este token como un parámetro de consulta a una dirección de correo electrónico y, cuando el usuario hace clic en este enlace, se considera que está autenticado. ¿Enviaría también una contraseña de texto simple a un usuario y luego la colocaría por medio de un parámetro de consulta a través del cable? Espero que no lo hagas porque eso es realmente una mala práctica, pero si te entiendo bien, quieres hacer exactamente esto: envía el "ticket" que proporciona al usuario acceso a tu aplicación en texto sin cifrar por correo. Incluso si está cifrado, no es una buena práctica.

Además, no debe "crear" automáticamente el nuevo usuario si recibe un POST al requestMagicLink-endpoit con una dirección de correo desconocida: esto le da a un atacante la oportunidad de enviar correo basura a su db con direcciones de correo de usuarios que no lo hacen. No quiero sus direcciones de correo en tu aplicación ;-)

Algunas otras trampas en las que pienso espontáneamente:

  • Enviar correos siempre es complicado: los piratas informáticos pueden enviar correos electrónicos falsos a sus usuarios o capturar y leer correos enviados porque los correos no están encriptados.
  • La redirección siempre es complicada: los piratas informáticos pueden comprometer un sistema mal implementado para redirigir a los usuarios a un sitio web comprometido bajo su control
  • Mantenga la vida útil del proceso lo más breve posible: si el usuario no hizo clic en el enlace del correo después de 10 minutos, rechácelo
  • Nunca envíe datos privados a través de un parámetro de consulta, ni en solicitudes GET ni en ningún otro método
  • Posibilidad de ataques de repetición cuando un token se puede usar varias veces

Le recomendaría que utilice los protocolos y métodos de mejores prácticas para la autenticación, que se utilizan y verifican durante años en lugar de escribir su propio mecanismo solo para evitar que su usuario ingrese una contraseña. De lo contrario, si realmente desea ir por este camino, debe hacer negocios con profesionales y dedicar mucho tiempo y esfuerzo para garantizar la seguridad de su mecanismo.

    
respondido por el Alex 20.11.2018 - 14:51
fuente
1

No coloque tokens / secretos de acceso en el almacenamiento local

Al poner el token de acceso en el almacenamiento local, se podrá acceder a él a través de JavaScript. Esto significa que el token puede ser robado con XSS ( Cross-Site Scripting ). Además, la autenticación solo funcionará si JavaScript está habilitado.

Una extensión de navegador malintencionada podría extraer el token de acceso y enviarlo a un atacante. Esto es especialmente importante si, como usted dice, el token de acceso no caduca.

Para evitar el riesgo de XSS, es mejor usar cookies para dichos tokens con el conjunto de marcas HttpOnly . (También querrá usar el indicador Secure y forzar HTTPS para todas las conexiones)

NOTA: Cuando use cookies en lugar de almacenamiento local, debe considerar y protéjase contra los ataques CSRF ( Cross-Site Request Forgery ).

Recursos útiles:

respondido por el Tobias Bergkvist 25.11.2018 - 18:41
fuente

Lea otras preguntas en las etiquetas