Implement a Password Reset Feature in a Node.js App

Simon Ugorji
Bits and Pieces
Published in
6 min readOct 25, 2022

--

In my article today, I will show you how you can implement a fully functional password reset feature in your NodeJS application.

Getting Started

The Crypto module

We will be using the built-in node module crypto to generate a hash for the password reset link. If this module does not come with your node version, use the command below to install it.

$ npm i crypto

If you have installed the module / verified that the module exists already, we may proceed with the next step

The model file

Head over to the user model and add the methods below to the schema object.

The first method

This method generatePasswordResetHash() will generate and return a sha512 hash using the user's current password.

If in your database, the user’s password is hashed already, you must modify the method to use the hashed password instead.

So you will do something like this

So if you want to use this method, create a new instance of the model and then pass in the user’s document as an argument so that it will extract the user’s hashed password or the user’s password (if you stored it in plain text)

The second method

This method verifyPasswordResetHash() will regenerate the hash again and then compare it against the submitted hash from the URL.

Now you need to set up the HTML pages needed for this feature. If you have one set up already, you may skip the step below.

The HTML templates

reset.html

This HTML page will have a form that will send the password reset link to the user.

new_pass.html

This HTML page will have a form that will enable the user to enter new password.

So this is an example of a password reset request form

password reset html page

Now here is the logic 😃

When a user enters his email address and requests for a password reset link, the system will check if the email address exists.

If the email address exists, the application should generate a hash using the user’s current password or the user’s hashed password if the password is hashed before they are saved, then I will attach this hash with the user’s email address to the password reset link

But if the email address does not exist, the application should respond with the message “Email address does not exist”.

Now, when the user opens the password reset link in a browser, we will extract the user’s email address and the hash from the URL. Then we will check again if the email address exists and if the hash is valid.

If the hash is valid, we will then issue a password reset form.

The server file

Now let us create a POST route that will generate a password reset link and send it to the user's email address.

In our password reset link, we will attach an Identifier that will help us to identify the particular user that is requesting for a password reset. Our Identifier in this case is the user’s email address, and when we generate a password reset link for the user, it will look like the format below;

Getting interesting right?

Let’s code it

In your server file, add the code below

This is the result of the code above, when I submit my email address for a password reset link

At this stage, you only need to send a mail to the user’s email address with the password reset link.

A little explanation

Let’s talk about the code above.

Remember that we added 2 schema methods in our model file.

The first method generatePasswordResetHash() used above, generates a hash with the user's current password using the sha512 algorithm and this hash will be included in our password reset link.

So what I basically did, was to create a new instance of the model and I passed in the user’s document as an argument so that the method generatePasswordResetHash() can take in the password directly when it is invoked.

What happens next?

Now, what happens when the user clicks on the reset link?

That’s a good question.

We need to set up / modify the already existing GET route for /reset.

Recall that this route serves a form that requests an email address from the user for the password reset link to be sent to.

We will check if the URL has a query that contains the email address & the hash, then we will extract them. This means that the URL must be in the format localhost:5000/reset?email=me@you.org&hash=aws5e5c44

A little explanation

Let’s talk about the code above.

Recall again that we added 2 schema methods in our model file.

The second method verifyPasswordResetHash() used above, regenerates the hash with the user's current password, then compares this hash with the one from the URL. It returns true if they are equal or false if they are not.

So what I basically did was to create a new instance of the model and pass in the current user’s document as an argument, then I invoked the method verifyPasswordResetHash() and passed in the hash from the URL as an argument, for the method to regenerate a hash and compare it to see if they are equal.

What happens if they are equal?

It means that the user truly requested for a password reset and what we need to do now is to save the user’s email address in the session and issue a password reset form.

So this is a sample page that will be rendered when the hash is valid

password update  html form

All you have to do now is;

  • Create a new route that will read the form data
  • Compare the two passwords
  • Then update the user’s password using his email address stored in the session

After the user must have updated his password, the password reset link will become invalid because the hash will no longer be the same.

Bonus

I published an e-book that will help you understand how to perform CRUD operations in MongoDB Using NodeJS And Express. If you are a fan of my articles and you love how I write, I am sure that you will love this e-book too.

Use the link below to get $5 off your purchase.

Here is a GitHub repository implementing a basic password reset feature in NodeJS. Check it out and modify it to suit your project.

Thank you for reading

Build apps with reusable components like Lego

Bit’s open-source tool help 250,000+ devs to build apps with components.

Turn any UI, feature, or page into a reusable component — and share it across your applications. It’s easier to collaborate and build faster.

Learn more

Split apps into components to make app development easier, and enjoy the best experience for the workflows you want:

Micro-Frontends

Design System

Code-Sharing and reuse

Monorepo

--

--