My one time reset password link is like this with a token http://url.com/token. The payload of the token contains a password (hashed)
When the user request forgot password, then this token is generated like this
jwt.sign({ password, email }, secret, {expiresIn: "1d"})
When the user clicks the link and fills out the reset form. The password reset request is sent to the server and in the body contains the token
from the url and the new password.
jwt.verify(req.body.token, secret)
Then I just checked if the hashed password in the database matches the one shown in the jwt payload. If it does, I will change the password in the database. If it doesnt,the one time link has been used already so I error (returns 400 error).
While this works, is there a security issue with putting the password into the jwt ?
How else would I check if the one time link has been used?
CodePudding user response:
I would definitely refrain from sending the old password hash in the JWT. If someone were to get access to a bunch of these, they could use them to try to brute-force hack your authentication.
What I would do is have a separate table for password reset requests. So every time someone asks for a reset link
- You create a new password reset request entry in your DB with the reset token
- If there already was an existing password reset request for that user in your DB, you delete it
- The user submits the reset request with their new password and the token
- You query your password reset request table and verify that the token they provided matches the token in your DB (i.e. because you only keep the most up-to-date one, you know that it is the correct one)
- You action the password change and delete the password reset request from the DB
Good luck!
CodePudding user response:
People can try to crack a password hash even if it takes a long time: https://security.stackexchange.com/questions/199494/how-to-crack-a-password-given-its-hash-and-its-possibilities
This makes your password hash sensitive which means you should not put it in your JWT token. https://stackoverflow.com/questions/43496821/is-it-safe-to-store-sensitive-data-in-jwt-payload#:~:text=Ideally you should not store,by simply base64 decoding it.
The time complexity/security risk depends on a lot of things(be sure you are salting your password).
This is a common problem with JWT tokens: Here is a link to some solutions: Invalidating JSON Web Tokens
One that was missed would be adding a password version(some number that increments when the password is changed) to your password. Then passing this version back in your token, instead of the password hash. Since you are already querying your database(to make sure the password is the same) you can just query to make sure the password version is the most recent version without any extra time complexity. If it is the same change the password. If it is not the same do not change the password.