DEV Community

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

Posted on

2

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

Playwright CLI Flags Tutorial

5 Playwright CLI Flags That Will Transform Your Testing Workflow

  • --last-failed: Zero in on just the tests that failed in your previous run
  • --only-changed: Test only the spec files you've modified in git
  • --repeat-each: Run tests multiple times to catch flaky behavior before it reaches production
  • --forbid-only: Prevent accidental test.only commits from breaking your CI pipeline
  • --ui --headed --workers 1: Debug visually with browser windows and sequential test execution

Learn how these powerful command-line options can save you time, strengthen your test suite, and streamline your Playwright testing experience. Practical examples included!

Watch Video ๐Ÿ“น๏ธ

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

๐Ÿ‘‹ Kindness is contagious

Explore a trove of insights in this engaging article, celebrated within our welcoming DEV Community. Developers from every background are invited to join and enhance our shared wisdom.

A genuine "thank you" can truly uplift someoneโ€™s day. Feel free to express your gratitude in the comments below!

On DEV, our collective exchange of knowledge lightens the road ahead and strengthens our community bonds. Found something valuable here? A small thank you to the author can make a big difference.

Okay