Sequelize.js: How to Auto-Hash Passwords

Updated: December 29, 2023 By: Guest Contributor Post a comment

Introduction

In modern web development, handling user passwords with utmost security is crucial. Passwords should never be stored as plain text in databases. Instead, they should be hashed using a robust algorithm. Sequelize, a Node.js ORM for relational databases like PostgreSQL, MySQL, SQLite, and MSSQL, offers a simple yet powerful way to hash passwords before they are stored. This guide will cover how to automatically hash passwords in Sequelize using lifecycle hooks and the bcrypt library.

Setting Up Sequelize Model

First, you need to set up your Sequelize model. Here’s a simple User model with a password field:

const { Sequelize, Model, DataTypes } = require('sequelize');
const sequelize = new Sequelize('database', 'username', 'password', {
  dialect: 'mysql',
  // other options
});
class User extends Model {}
User.init({
  username: DataTypes.STRING,
  password: DataTypes.STRING
}, { sequelize, modelName: 'user' });

Installing Bcrypt

Before proceeding, ensure that you have bcrypt installed:

npm install bcrypt

Now, you can require it in your file:

const bcrypt = require('bcrypt');

Auto-Hashing Passwords Using Hooks

To hash passwords automatically, you can use Sequelize’s ‘beforeCreate’ and ‘beforeUpdate’ hooks. These hooks are called before a model instance is created or updated, respectively.

User.beforeCreate((user, options) => {
  const salt = bcrypt.genSaltSync();
  user.password = bcrypt.hashSync(user.password, salt);
});
User.beforeUpdate((user, options) => {
  if (user.changed('password')) {
    const salt = bcrypt.genSaltSync();
    user.password = bcrypt.hashSync(user.password, salt);
  }
});

Handling Password Verification

To verify passwords during login:

User.prototype.validPassword = function(password) {
  return bcrypt.compareSync(password, this.password);
};

To use this method:

const isMatch = userInstance.validPassword('inputPassword');
if (isMatch) {
  // Passwords match
} else {
  // Password does not match
}

Advanced Usage

If you want to hash passwords asynchronously or incorporate more complex logic, you can use asynchronous hooks and bcrypt’s asynchronous functions.

User.beforeCreate(async (user, options) => {
  const salt = await bcrypt.genSalt();
  user.password = await bcrypt.hash(user.password, salt);
});

In the context of password verification for login, you could modify the validPassword method to be async as well:

User.prototype.validPassword = async function(password) {
  return await bcrypt.compare(password, this.password);
};

Conclusion

Auto-hashing passwords in Sequelize is a best practice that should be implemented in any application handling user credentials. This not only secures the passwords but also abstracts the complexity from developers. Following the steps outlined in this guide will ensure that your user’s passwords are handled securely. Always keep your dependencies updated and review your security strategies constantly to keep up with evolving threats.