Sling Academy
Home/Node.js/How to use BCrypt with Sequelize models

How to use BCrypt with Sequelize models

Last updated: December 29, 2023

Introduction

Securing user data is a fundamental aspect of web development, particularly when it comes to storing passwords. A common approach is to hash passwords before they are saved to a database, and BCrypt is one of the most reliable algorithms for hashing passwords. In this tutorial, we’ll integrate the BCrypt hashing algorithm with Sequelize, an ORM for Node.js, to provide enhanced security for user passwords in a Node.js application. We will start with the basics of setting up Sequelize models and then move on to how to integrate BCrypt for password hashing.

Setting Up Sequelize Models

Sequelize is a promise-based ORM for Node.js. To start, you need to install Sequelize and its dependencies:

npm install sequelize
npm install --save pg pg-hstore # If using PostgreSQL

Next, configure Sequelize to connect to your database:

const Sequelize = require('sequelize');

const sequelize = new Sequelize('database', 'username', 'password', {
  host: 'localhost',
  dialect: 'postgres',
});

With the connection set up, define a User model that will include a password field:

const User = sequelize.define('user', {
  username: {
    type: Sequelize.STRING,
    unique: true,
  },
  password: {
    type: Sequelize.STRING,
    allowNull: false,
  },
});

Integrating BCrypt for Password Hashing

For hashing passwords, we’ll be using the ‘bcrypt’ library. Install it using the following command:

npm install bcrypt

Now, you can hook into Sequelize’s model lifecycle events to hash the password before a User is created or updated:

const bcrypt = require('bcrypt');
const saltRounds = 10;

User.beforeCreate((user, options) => {
  return bcrypt.hash(user.password, saltRounds)
    .then(hash => {
      user.password = hash;
    })
    .catch(err => {
      throw new Error(err);
    });
});

User.beforeUpdate((user, options) => {
  if (user.changed('password')) {
    return bcrypt.hash(user.password, saltRounds)
      .then(hash => {
        user.password = hash;
      })
      .catch(err => {
        throw new Error(err);
      });
  }
});

Advanced: Handling Authentication

With the hashing integrated, the next step is to handle authentication by comparing a login attempt’s password with the hashed password stored in the database. Below is a method that can be added to the User model to perform this verification:

User.prototype.isValidPassword = function(password) {
  return bcrypt.compare(password, this.password)
    .then(result => result)
    .catch(err => throw new Error(err));
};

To authenticate a user, you’d call this method with the submitted password:

User.findOne({ where: { username: 'someuser' } })
  .then(user => {
    if (!user) {
      // Handle user not found
    }
    return user.isValidPassword('submitted_password');
  })
  .then(isValid => {
    if (!isValid) {
      // Handle password not matching
    }
    // User is authenticated
  })
  .catch(err => {
    // Handle error
  });

Conclusion

In this tutorial, we walked through the process of integrating BCrypt with Sequelize models for secure password hashing. We started with setting up Sequelize and moved through hashing passwords on user creation and updates. We also covered authentication by validating passwords against the hashed ones in the database. By following these steps, you’ll ensure that your application is using industry-standard practices for password security, keeping your users’ information safe. Remember, security is an ongoing process, and it’s important to keep abreast of best practices and potential vulnerabilities.

Next Article: Fixing Sequelize Error TS1086 in Node.js Projects

Previous Article: Fixing error: sequelize.import is not a function in Node.js

Series: Sequelize.js Tutorials

Node.js

You May Also Like

  • NestJS: How to create cursor-based pagination (2 examples)
  • Cursor-Based Pagination in SequelizeJS: Practical Examples
  • MongooseJS: Cursor-Based Pagination Examples
  • Node.js: How to get location from IP address (3 approaches)
  • SequelizeJS: How to reset auto-increment ID after deleting records
  • SequelizeJS: Grouping Results by Multiple Columns
  • NestJS: Using Faker.js to populate database (for testing)
  • NodeJS: Search and download images by keyword from Unsplash API
  • NestJS: Generate N random users using Faker.js
  • Sequelize Upsert: How to insert or update a record in one query
  • NodeJS: Declaring types when using dotenv with TypeScript
  • Using ExpressJS and Multer with TypeScript
  • NodeJS: Link to static assets (JS, CSS) in Pug templates
  • NodeJS: How to use mixins in Pug templates
  • NodeJS: Displaying images and links in Pug templates
  • ExpressJS + Pug: How to use loops to render array data
  • ExpressJS: Using MORGAN to Log HTTP Requests
  • NodeJS: Using express-fileupload to simply upload files
  • ExpressJS: How to render JSON in Pug templates