Esta es otra pregunta "¿Cómo se hace correctamente una página de contraseña olvidada"? Sin embargo, aborda explícitamente dos opciones de implementación que he encontrado recientemente.
Los enfoques comunes [1,2] que conozco se basan en un token aleatorio que solo se puede usar una vez y que tiene una validez limitada:
- Las visitas de los usuarios olvidaron la página de contraseña
- El usuario proporciona la dirección de correo electrónico (o similar)
- Si el correo electrónico está asociado con una cuenta de usuario válida
- La aplicación genera un token único y aleatorio. t es de suficiente entropía (digamos 128 bits).
- La aplicación almacena el token aleatorio t y la marca de tiempo en la que se creó junto con el usuario en la base de datos
- La aplicación envía un correo electrónico que contiene un enlace para restablecer la contraseña a la dirección de correo electrónico de los usuarios. El enlace es similar al siguiente: enlace
- El usuario hace clic en el enlace del correo electrónico
- La aplicación comprueba
- si hay un token t dentro de la base de datos para un usuario determinado
- en caso afirmativo, comprueba que sigue siendo válido en función de la marca de tiempo almacenada
- en caso afirmativo, permite al usuario acceder a la página de contraseña de restablecimiento
- El usuario establece una nueva contraseña
- Después de eso, la aplicación invalida el token t
Puedes agregar un poco más de cosas de seguridad como canales fuera de banda o preguntas de seguridad. Pero para mí, esa es la mejor práctica común que conozco.
Ahora considere un enfoque diferente. Perderemos la propiedad de un solo uso. Sin embargo, el beneficio es que la aplicación no tiene que realizar un seguimiento de los estados del token en absoluto.
En lugar de generar un token aleatorio, usaremos un HMAC de la siguiente manera:
- token = HMAC_k (correo electrónico, marca de tiempo)
k es un secreto que la aplicación conoce de suficiente entropía. El enlace de restablecimiento que se envía por correo electrónico al usuario tiene el siguiente aspecto:
Cuando el usuario accede al enlace, la aplicación lo verifica de la siguiente manera:
- calcule HMAC según los parámetros de la URL: token_calculated = HMAC_k (correo electrónico, marca de tiempo)
- compruebe si el token proporcionado como parámetro de URL y el HMAC calculado coinciden
- en caso afirmativo, compruebe si el token sigue siendo válido según la marca de tiempo
- en caso afirmativo, permita que el usuario acceda a la página de contraseña de restablecimiento
En mi opinión, la propiedad de no tener que mantener un estado del lado del servidor es más valiosa que la propiedad de un solo uso. Esto supone que se configura una validez razonable y corta de tokens en el lado del servidor, por ejemplo, de 20 a 30 minutos.
Realmente me gustaría saber qué piensan otras personas del segundo enfoque. Especialmente, si hay algún inconveniente que podría no haber notado todavía.
[1] enlace
[2] enlace