DEV Community

Cover image for How to Use Bcrypt for Password Hashing in Node.js
john mbugua
john mbugua

Posted on

How to Use Bcrypt for Password Hashing in Node.js

Page Content

Introduction to Bcrypt

Securing user data has become paramount, and one of the most critical aspects of this security is password protection. This is where password hashing comes into play.

Password hashing: is a process of transforming a plain text password into a fixed length string of characters, which is typically a cryptographic hash.

Bcrypt: A library to help you hash passwords.

Getting started with Bcrypt

Let's get started

To start using bcrypt in your Node.js application, you first need to install it. Below are the instructions for installing bcrypt:

npm install bcrypt

Using Bcrypt with Mongoose Pre-Save Middleware

In this section, we will explore how to use bcrypt with Mongoose pre save middleware to securely hash passwords before saving them to the database. This approach ensures that plain text passwords are never stored in the database, enhancing the security of your Node.js application.

Before we begin, make sure you have installed both mongoose and bcrypt in your project:

npm install mongoose bcrypt

Importing required modules

const mongoose = require('mongoose');
const bcrypt = require('bcrypt');
Enter fullscreen mode Exit fullscreen mode

The pre save middleware is a function that runs before a document is saved to the database. This method it is an important way to hash the user's password:

// pre save middleware
UserSchema.pre("save", async function () {
  //    hashing the password
  const salt = await bcrypt.genSalt(15);
  this.password = await hash(this.password, salt);
});
Enter fullscreen mode Exit fullscreen mode

Implementing Password Comparison with Instance Methods in a Node.js and Mongoose Application

In this section, we will discuss how to use instance methods in Mongoose to compare passwords using bcrypt. This approach is particularly useful for verifying user credentials during the login process. Here is the code for the instance method, followed by an explanation of how it works:

UserSchema.methods.comparePassword = async function (mainpassword) {
  return await bcrypt.compare(mainpassword, this.password);
};
Enter fullscreen mode Exit fullscreen mode

Explanation

Instance Method Definition

  • UserSchema.methods.comparePassword: This line defines a new instance method called comparePassword on the Mongoose schema UserSchema. Instance methods are functions that operate on individual documents instances of the model.

Async Function

  • async function (mainpassword) { ... } : The method is defined as an asynchronous function that takes mainpassword as an argument. mainpassword represents the plain text password that needs to be compared with the stored hashed password.

Password Comparison

  • return await bcrypt.compare(mainpassword, this.password); : This line uses bcrypt compare function to compare the provided plain text password mainpassword with the hashed password stored in the current document this.password . The compare function returns a promise that resolves to true if the passwords match and false otherwise.

Password Verification in Node.js Using Bcrypt with Mongoose Instance Methods

In this section, we will focus on how to use the comparePassword instance method within the login logic of a Node.js application to securely verify user passwords using bcrypt. Please note that the validation and error handling in this example are not the primary focus and are included for completeness.

const login = async (req, res) => {
  const { email, password } = req.body;

  //   validation
  if ((!email, !password)) {
    throw new BadRequestError("Please provide email and password");
  }

  const userLogin = await UserModel.findOne({ email });

  if (!userLogin) {
    throw new UnauthenticatedError("Invalid credentials");
  }

  const isPasswordCorrect = await userLogin.comparePassword(password);

  if (!isPasswordCorrect) {
    throw new UnauthenticatedError("Invalid credentials");
  }

  const token = userLogin.createToken();
  res
    .status(StatusCodes.OK)
    .json({ user: { name: userLogin.getName() }, token });
};
Enter fullscreen mode Exit fullscreen mode

Explanation of comparePassword Usage

Finding the User

  • The code first retrieves the user document from the database using UserModel.findOne({ email })

  • If the user is not found, it throws an error indicating invalid credentials.

Comparing Passwords

const isPasswordCorrect = await userLogin.comparePassword(password);

  • This line uses the comparePassword instance method defined on the user schema.

  • The method compares the provided plain text password password with the hashed password stored in the database userLogin.password .

  • comparePassword uses bcrypt compare function/method and returns true if the passwords match, or false otherwise.

Handling Incorrect Passwords

  • If the password comparison fails !isPasswordCorrect , an error is thrown indicating invalid credentials.

Generating and Returning a Token

  • If the password comparison succeeds, a token is generated using userLogin.createToken()

  • The response includes the user name and the generated token

Conclusion

In this article, we explored how to use bcrypt in a Node.js application with Mongoose to securely hash and verify passwords. We covered the installation of bcrypt, the implementation of password hashing using Mongoose pre save middleware, and the use of Mongoose instance methods for password comparison during login. By following these steps, you can enhance the security of your application authentication system, ensuring that user passwords are properly protected.

Happy Coding

Top comments (0)