简体   繁体   中英

How to implement “forgot/reset password” feature properly in Node.js? (Using one time token)

I am implementing a forgot/reset password functionality in a Node.js app using NestJs.

That is the general flow:

  1. A user types in his email in a "forgot password" form and submits the request
  2. The server generates a jwt token with the user's ID as the payload, then sends an email with the token as the link to reset the password (example: GET: example.com/reset/generated_jwt_token )
  3. User clicks the link from his email, the reset password page is rendered, he fills the form with the new password and submits the form with the password as the body (example: POST: example.com/reset/generated_jwt_token )
  4. Server verifies the token (that is not expired + user ID from payload exists in the DB) and updates the password.

The main problem with this approach is that the jwt token can be used unlimited amount of times to reset the password (until it expires after X minutes).

Is there a way to solve this? some say to put the current password's hash as the payload since it will be changed anyway and will guarantee 1 time use, but I'm not a fan of this method.

EDIT: Another approach i encountered is creating a blacklist collection in the DB of jwt token that cannot be used more than once. Or using a cache in redis the same way, but it seems not very scalable.

When a token is generated, you could save it (or something unique embedded inside it) into the database under that user. Then, the server verifies the token:

(1) when the link from the reset email is clicked

(2) when the user submits the reset password page

by checking that the token is the same as the one for that user in the database.

Also, when the user successfully changes their password, clear the token from the database so it can't be used again.

I agree with the (accepted) answer of @CertainPerformance.

I would like to add - Consider using authentication-flows-js . You will not have to worry about the implementation at all!

It is a module that answers most flows - authentication, registration, forgot-password, change password etc., and it is secured enough so applications can use it without the fear that it will be easily hacked.

From an article I wrote:

Forgot Password

The user enters their email in the forgot password form, and clicks submit. The server (AFM) verifies the account exists and is not locked. If it is locked, AFM throws an error. Otherwise, an email is sent to the user with a token. That token is stored in the DB in the same row/document/record of the user.

Read the full article with more explanations here .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM