Hashing and Comparing Passwords With bcrypt in Node.js

If you have wanted to integrate user authorisation into your web app you have most certainly been wanting to know how to hash passwords stored in your database for increased security.

I have been integrating user auth into my personal web apps for a while and wanted to share how you can do the same with bcrypt and Node.js!

If you are unfamiliar with Node.js, I have an article called 'What is Node.js and Should I Learn it in 2021?' which you can read to familiarise yourself with it.

What is bcrypt?

bcrypt is a password hashing function that uses a certain number of salt rounds which adds random data into the password to make every password unique regardless of whether they are same plain password. This means that even if we both have the password 'apple123', they will be stored as a different hash in the database so If one is cracked the other one won't be.

The standard numbers of salt rounds in bcrypt is 10 and every time a new round is added it will double the time taken to hash but also to crack it.

The Two Main Functions of bcrypt

bcrypt.hash

bcrypt.hash(plainPassword, numberOfSaltRounds, function(err, hash) {
// Store hash in your database.
});

This is the hash function which is used to take in a plain password by the user and then run a number of salt rounds on it while hashing the password. You can take this hashed password and store that in the database instead of the plain password.

bcrypt.compare

bcrypt.compare(plainPassword, hashedPassword, function(err, result) {
// If result is true then you can log in the user and store the session.
});

The compare function will take in 2 arguments. The plain password which has been taken from the users input and the hashed password which you have taken from the database.

If this result is true then you can successfully login the user and store the session such as a cookie in the browser.

However, if this plain password doesn't compare successfully you can send back a message such as "Invalid username/password".

On that note, it reminds me of something I heard a while back to increase security against brute force attacks.

You should always send back a message saying both the username/email and password is invalid instead of just saying the password is incorrect when the username is correct. This is because the attacker could then identify a user exists and then start to brute force their password.

Example of bcrypt In Node.js with Express

Example of Node.js and bcrypt code to hash and compare passwords

Let's start to break down this example line by line!

Firstly we are importing the dependencies at the top such as Express and bcrypt. We are using Express due to making it easier to set up API's in Node.js. We will use this Express function and set it as a variable called 'app' so we can refer to it in the code.

We are using 'urlencoded' because we can grab the data inputted by the user in the requests.

The two routes are '/register' and '/login' which will both be using bcrypt in some way.

'/register' Route

Starting with the '/register' route you will need to set it as an asynchronous function because we will be awaiting on the bcrypt hash to do it's magic. If not we will just get back an undefined variable as the hashed password.

If you are hashing the password correctly you should see something like this once you send a plain password to it.

Hashed password displayed in the console

This is the hashed password in my console log which I have sent a request to this route using Postman to test the API endpoint. If you haven't used Postman before to test your API's you're missing out!

Postman sending request to localhost to test API

I sent a username and password in the request body to the '/register' route which led to this hashed password being generated.

You will want to connect your database up at this point because you will be storing the hashed password along with the username in the database to refer back to at a later date when the user wants to login.

'/login' Route

The login route will take a little bit more code to set up since you will need to refer to the user in the database and grab the hashed password to compare against the plain password the user inputs.

So firstly you want to store the username and plain password in variables.

Then search the database for a user with that username. If this comes back true you will want to use the bcrypt.compare function.

Enter in the plain password from the variable you just made along with hashed password from the user you found in the database.

If this compare function comes back true you can store the session and login the user successfully!

Which Database To Use To Store User Data?

This depends very much on the use case of the app but I have a recommendation.

MongoDB works very nicely due to the Mongoose dependency you can install which makes it easy to connect to. Dev Ed has made a great video covering MongoDB and creating a Node.js API with it.

Conclusion

I hope this overview of how bcrypt works with the database of your choice has helped. It was something that took me a while to get used to but bcrypt is a great package to give you peace of mind and know your passwords are hashed correctly.

Here are some good recommendations on where to go next if you are wanting to learn more.

  • Web Dev Simplified ironically is great at simplifying this process. Here's a YouTube video of his explaining it all in detail.
  • Dev Ed creates an authentication system with MongoDB and JWT using bcrypt in this YouTube video.

I hope these videos help!

Take care.

Join the mailing list!