Generando un token firmado. Desde el nombre de usuario o la identificación y una marca de tiempo, se genera un token firmado con una clave secreta. Este es el enlace enviado al usuario. Cuando el usuario envía, el token se descifra y el usuario y la marca de tiempo se recuperan y validan.
Está hablando de claves secretas, tokens "firmados" y "descifrado" (y más adelante, "sal") de una manera muy flexible que sugiere que es probable que implemente este error. Lo que querría usar en este caso es un código de autenticación de mensaje , por ejemplo HMAC-SHA256 , que es casi seguro que sus bibliotecas criptográficas ya admiten.
Es muy sabio estar atento a los ataques de repetición. Su idea de enviar el hash con sal de la contraseña actual como contexto, aunque no es bueno si se toma literalmente, va por buen camino. Lo que te falta es que no necesitas poner el hash en la URL porque ya lo estás almacenando ; todo lo que necesita poner en la URL es información que le permita a su servidor recuperar el hash de contraseña con sal cuando se haga clic en la URL de restablecimiento. El nombre de usuario para el que está restableciendo la contraseña probablemente haría el truco.
Aquí hay un bosquejo de una posible solución. Primero, necesitas un secret_key
seguro. Una forma de hacer esto que puede ahorrarle muchos dolores de cabeza es usar claves efímeras , en lugar de tener una clave a largo plazo que se use durante mucho tiempo y que un atacante aún pueda hacer lo que haga. en cambio, es cuando se inicia el servicio de restablecimiento de contraseña:
- Selecciona un
secret_key
de 128 bits al azar. Esto solo se guardará en la memoria, nunca lo escriba en el disco o en la red.
- Seleccione un único
startup_uuid
. Usaría un número aleatorio o UUID.
Esto significa que el secret_key
solo es válido durante la vida útil de un proceso de servicio de restablecimiento de la clave: cada vez que se reinicia, la clave se descarta y se genera una nueva. La ventaja de esto es que su servicio es mucho más resistente contra el robo de llaves. La desventaja es que los enlaces de restablecimiento generados antes de un reinicio no se validarán: el propósito de startup_uuid
es detectar ese caso y manejarlo de manera amigable.
Cuando se le solicita una URL de restablecimiento de contraseña para username
, el servicio de restablecimiento de contraseña hace esto:
- Elija una fecha y hora de caducidad para el enlace de restablecimiento, por ejemplo, 15 minutos después de la hora actual.
- Busque la entrada de la contraseña
username
de la solicitud y recupere su hash de contraseña actual con sal.
- Construya un mensaje delimitado inequívoco
reset_data
con los siguientes campos en algún orden fijo:
- El proceso del servidor '
startup_uuid
;
- El nombre de usuario de la solicitud;
- La marca de tiempo de caducidad seleccionada;
- Hash de contraseña actual del usuario.
- calcular
reset_token = HMAC-SHA256(secret_key, reset_data)
- Construya una URL de restablecimiento con estos valores como parámetros. ( NOTA: el hash de la contraseña es no un parámetro en la URL de restablecimiento)
- El nombre de usuario;
- La marca de tiempo de inicio del servidor;
- La marca de tiempo de caducidad;
- El
reset_token
.
- Devuelve esa URL construida.
Cuando reciba una solicitud en el punto final de la URL para restablecer la contraseña:
- Si el
startup_uuid
de la solicitud no es igual al del servidor, entonces el servicio se ha reiniciado desde que se generó el enlace. Ya no tenemos el antiguo secret_key
y, por lo tanto, no podemos verificar esa solicitud. El usuario tendrá que rehacer el proceso de restablecimiento de contraseña.
- Si la hora actual es posterior al valor de fecha y hora de caducidad de la URL, el enlace caducará, así que no lo acepte.
- Busque el hash de contraseña con sal para el nombre de usuario de la solicitud.
- Construya un mensaje delimitado inequívoco
reset_data
como arriba.
- Verifique que este mensaje
reset-data
coincida con el reset_token
que se incluye en la URL. Asegúrese de hacerlo de manera segura con una comparación de igualdad de tiempo constante.
- Si la verificación tiene éxito, siga adelante y restablezca la contraseña del usuario.
Este protocolo tiene estas virtudes:
- Las claves secretas son efímeras y solo se guardan en la memoria, por lo que incluso si alguien roba una clave, solo es bueno hasta el próximo reinicio.
- El hash de la contraseña que se restablecerá se usa como entrada para HMAC. Si un usuario intenta restablecer una contraseña que ya se ha restablecido o modificado, la verificación del token de restablecimiento fallará.
- A diferencia de su propuesta, la contraseña con hash nunca se revela.