Flymingo Tech - Blogs
  • Tech News
  • How-To Guides
  • Product Reviews
  • Industry Analysis
  • Cybersecurity
  • Programming
  • Development
  • Tech Lifestyle
  • About Us
  • Contact Us
  • Privacy Policy
  • Terms & Conditions
Monday, Aug 3, 2026
Flymingo Tech - BlogsFlymingo Tech - Blogs
Font ResizerAa
  • About us
  • Privacy Policy
  • Terms & Conditions
  • Contact
Search
  • Tech News
  • How To Guide
  • Product Reviews
  • Industry Analysis
  • Cybersecurity
  • Programming
  • Development
  • Tech Lifestyle
Follow US
CybersecurityHow-To GuidesProgramming

How to Secure Passwords Using bcrypt in Node.js

Hasan Hashmi
Last updated: August 3, 2026 11:27 am
Hasan Hashmi
Share
SHARE

Introduction

Passwords are the first line of defence for almost every online application. When you’re building a social media platform, an e-commerce store, or an internal business portal user password protection should be your top priority.

Contents
  • Introduction
  • What Is Password Hashing?
    • Current password
    • Hashed Password
  • What Is bcrypt?
  • How Does bcrypt Work?
    • Step 1: User types password
    • Step 2: bcrypt Generates a Salt
    • Step 3: Combinding Password & Salt
    • Step 4. Hashing It
    • Step 5: User Sign In
  • Installing bcrypt in Node.js
  • Your First Password Hash
  • Building a Secure Registration and Login System Using bcrypt in Node.js
  • Create a New User Account
  • Understanding bcrypt.compare()
  • Environment Variables
  • Real-World Illustration
  • Best Tips
  • Common Errors to Avoid

But many beginner developers make one big mistake: they store passwords in plain text. If a database is hacked , all the passwords are instantly compromised . This can lead to account takeovers, identity theft and serious security issues.

But happily there is a much safer way. Instead of storing the passwords in the database directly, you should hash the passwords before storing them. One of the most trusted libraries for this is bcrypt.

In this guide, you’ll learn how bcrypt works, why it’s more secure than older hashing algorithms, and how to use it in a Node.js application. You will also get a basis for a secure authentication system that follows modern security best practices.

Why You Should Never Store Plain Text Passwords

Imagine you are building a user registration system. A user signs up with the following credentials:

Email

john@example.com

Password

MyPassword123

A beginner might store these values like this:

EmailPassword
john@example.comMyPassword123

At first sight this looks harmless. But it is a major security hazard.

If an attacker gets into your database, they immediately know every user’s password. Many people also use the same password on multiple sites. That means a single breach could leave email accounts, banking apps and social media profiles exposed.

So, storing plain text passwords is one of the biggest security mistakes a developer can make.

What Is Password Hashing?

Password hashing is the method of converting a password into a fixed length string of characters by using a mathematical algorithm.

Hashing is a one-way process, and it is not an encryption. The password is hashed and cannot be ” dehashed “.

For instance:

Current password

MyPassword123

Hashed Password

$2b$10$Mdbj6x7vI5S8rP2r4vY4eOlv8bY9nFv0L3xS6K9zM1JqA7BcD8EfG

The hashed value looks random but it always represents the original password.

When the user logs in again, the password is bcrypt hashed and compared with the stored hash. If they match, then authentication passes.

What Is bcrypt?

bcrypt is a password hashing library designed to store passwords securely.

Unlike older hashing algorithms that use a static salt , bcrypt automatically generates a unique salt for each password . It also allows developers to specify how computationally intensive the hashing operation should be.

When computer hardware gets faster you can increase the cost factor used by bcrypt to make it harder to crack passwords.

Currently, bcrypt is used extensively in:

  • Node.js apps
  • Express.js API’s
  • Laravel-Projekte
  • Ruby on Rails apps
  • Django apps
  • Enterprise authentication technologies

Bcrypt is still one of the recommended password hashing algorithms due to its proven reliability.

How Does bcrypt Work?

So when a user creates a password , bcrypt does a few things .

Step 1: User types password

For instance: MyPassword123

Step 2: bcrypt Generates a Salt

A salt is a random unique value per password.

Now, since each password is mixed with a different salt, even if two users have the same password, their hashes will still be completely different.

Step 3: Combinding Password & Salt

The password is then combined with the generated salt and hashed using bcrypt.

Step 4. Hashing It

The password is not stored in the database , but the hash .

Step 5: User Sign In

Later, when the user logs in, bcrypt hashes the password entered using the stored salt. It then compares the new hash with the current hash.

If both hashes are equal then login is successful .

Thus, the original password is never needed to be stored anywhere.

Understanding Salt

A salt is one of bcrypt’s most important security features.

Without a salt, two users who choose the same password would produce identical hashes.

For example:

UserPasswordHash
Alicepassword123Same Hash
Bobpassword123Same Hash

This makes password databases easier to attack.

With bcrypt, every password receives a different random salt.

UserPasswordHash
Alicepassword123Different Hash
Bobpassword123Different Hash

Therefore, attackers cannot easily determine which users share the same password.

bcrypt vs MD5 vs SHA-256

Many beginners wonder why they should use bcrypt instead of MD5 or SHA-256.

Here’s a comparison:

FeaturebcryptSHA-256MD5
Built for Passwords✅ Yes❌ No❌ No
Automatic Salt✅ Yes❌ No❌ No
Adjustable Cost Factor✅ Yes❌ No❌ No
Resistant to Brute Force✅ High⚠️ Moderate❌ Poor
Recommended Today✅ Yes⚠️ Only with additional safeguards❌ No

Though the SHA-256 algorithm is safe for many cryptographic operations, it is meant to be fast. However, password hashing has to be done deliberately slowly in order to make brute force attacks costly.

This makes bcrypt more suitable for password storage.

Installing bcrypt in Node.js

Before you write any code, create a new Node.js project.

Begin the project:

npm init -y

Then install bcrypt:

npm install bcrypt

After the installation, import the package into your project:

const bcrypt = require(“bcrypt”);

You are now ready to begin hashing passwords properly.

Your First Password Hash

Let’s hash a password using bcrypt.

const bcrypt = require("bcrypt");

async function hashPassword() {
    const password = "MyPassword123";

    const hashedPassword = await bcrypt.hash(password, 10);

    console.log(hashedPassword);
}

hashPassword();

In this case, the number 10 is the salt rounds number, which is often referred to as the cost factor. The larger the number, the greater the security; however, more time will be spent on the computation process.

For the majority of web applications, the number of 10-12 salt rounds is considered sufficient from both the security and performance perspectives.

As soon as you execute the script, you will notice that a different hash will be generated because bcrypt generates a different salt each time.

It is absolutely natural because of the following reason.

Building a Secure Registration and Login System Using bcrypt in Node.js

Now that you understand how bcrypt works, let’s implement it in a real-world application. In this section, you’ll create a very simple authentication system with Express.js, MongoDB and bcrypt.

After this tutorial you will be able to:

  • Securely register new users.
  • Hash passwords before saving them.
  • Check passwords at login.
  • Create authentication tokens.
  • Adhere to best practices in the industry.

Project Setup

First, create a new project folder.

mkdir bcrypt-auth-demo
cd bcrypt-auth-demo

Next, initialize a Node.js project.

npm init -y

Now install the required packages.

npm install express mongoose bcrypt jsonwebtoken dotenv

Install Nodemon for development.

npm install --save-dev nodemon

Your project structure should look like this:

bcrypt-auth-demo/
│
├── models/
│      User.js
│
├── routes/
│      auth.js
│
├── .env
├── server.js
└── package.json

Keeping your project organized makes it easier to maintain as it grows.

Creating the Express Server

Create a file named server.js.

const express = require("express");
const mongoose = require("mongoose");
require("dotenv").config();

const app = express();

app.use(express.json());

mongoose.connect(process.env.MONGO_URI)
.then(() => console.log("MongoDB Connected"))
.catch(err => console.log(err));

app.listen(3000, () => {
    console.log("Server running on port 3000");
});

This code creates an Express server and connects it to MongoDB.

Creating the User Model

Inside the models folder, create User.js.

const mongoose = require("mongoose");

const userSchema = new mongoose.Schema({

    name:String,

    email:{
        type:String,
        unique:true
    },

    password:String

});

module.exports = mongoose.model("User",userSchema);

This schema stores:

  • Name
  • Email
  • Hashed password

Notice that we never plan to store the original password.

Creating the Registration API

Now create routes/auth.js.

Import the required modules.

const express = require("express");
const bcrypt = require("bcrypt");
const User = require("../models/User");

const router = express.Router();

Create the registration endpoint.

router.post("/register", async(req,res)=>{

const {name,email,password}=req.body;

const existingUser=await User.findOne({email});

if(existingUser){

return res.status(400).json({
message:"User already exists"
});

}

const hashedPassword=await bcrypt.hash(password,10);

const user=new User({

name,
email,
password:hashedPassword

});

await user.save();

res.status(201).json({

message:"Registration Successful"

});

});

Let’s get a grip on what’s going on.

The API will then verify whether the email already exists.

If it does, registration ceases immediately.

Otherwise, bcrypt hashes the password

Finally only the hashed password is stored in the database.

This method ensures sensitive user credentials are kept safe.

Create a New User Account

Now suppose a user enters the following data.

{ “name”: “John”, “email”: “john@gmail.com”, “password”: “Password123” }

Instead of saving:

Password123

MongoDB has something like this:
$2b$10$0WJ7XWkDiL…..

Even if someone gets into your database they can’t read the original password.

Creating the Login API

Registration is only half of the authentication process.

Users also need to log in securely.

Create the login route.

router.post("/login",async(req,res)=>{

const {email,password}=req.body;

const user=await User.findOne({email});

if(!user){

return res.status(404).json({

message:"User not found"

});

}

const isMatch=await bcrypt.compare(

password,

user.password

);

if(!isMatch){

return res.status(401).json({

message:"Invalid Password"

});

}

res.json({

message:"Login Successful"

});

});

Unlike registration, login does not hash the password manually.

It then compares the entered password with the stored hash, by the bcrypt algorithm.

If both values match, the authentication succeeds.

Understanding bcrypt.compare()

This causes many beginners to ask why we cannot compare strings.

Like for example:

password===user.password

This will never work because:

Password123

is totally different from:
$2b$10$4jKf9…

More bcrypt under the hood:

  • Salt is extracted.
  • Rehashes the password entered again.
  • Compares both hash values securely.

This means developers never have to decrypt passwords.

Generating JWT Tokens

Most modern APIs use JSON Web Tokens (JWT).

Install the package.

npm install jsonwebtoken

Import it.

const jwt=require("jsonwebtoken");

Generate a token after successful login.

const token=jwt.sign(

{

id:user._id

},

process.env.JWT_SECRET,

{

expiresIn:"1d"

}

);

res.json({

message:"Login Successful",

token

});

Now the client receives a secure token instead of maintaining a server-side session.

This makes authentication scalable and suitable for REST APIs.

Environment Variables

Don’t ever put secrets directly into your code.

Instead, create a .env file.

PORT=3000

MONGO_URI=mongodb://localhost/auth

JWT_SECRET=myverystrongsecretkey

Then load it with:

require(“dotenv”).config();

Using environment variables is more secure and keeps sensitive information out of source control.

Complete Authentication Flow

Here’s how the entire process works:

User Registers

↓

Password Entered

↓

bcrypt Generates Salt

↓

Password Hashed

↓

Hash Stored in MongoDB

↓

User Logs In

↓

bcrypt Compares Password

↓

JWT Token Generated

↓

Access Granted

This workflow is used in many real-world applications.

Real-World Illustration

Suppose you’re building a shopping website.

Customer creates an account.

Rather than saving:

SummerSale2026

The database includes:

$2b$10$khH93j8ksl…

Then the customer logs in.

bcrypt never exposes or decrypts the password, it just verifies it.

So even if the database is leaked, attackers cannot immediately access customer accounts.

Best Tips

Follow these recommendations for using bcrypt.

  • Use 10-12 salt rounds for most applications.
  • Always validate user input.
  • Store secrets in environment variables.
  • “Use HTTPS in production.”
  • Limit the number of login attempts.
  • Lock out account after too many wrong logins.
  • Utilize JWT expiration times.
  • Update dependencies.

If you do these things you will make your authentication system much more secure.

Common Errors to Avoid

Avoid these common errors:

❌ Save plain text passwords

❌ MD5 stored passwords

❌ Hard coded secret keys

❌ Bypass email validation

❌ Not paying attention to failed login attempts

❌ Sending detailed authentication errors

Instead, send generic messages like:

Wrong email or password.

This prevents attackers from learning whether an email address exists in your system.

TAGGED:Backend DevelopmentWeb DevelopmentWeb Frameworks
Share This Article
Facebook LinkedIn Copy Link Print
Leave a Comment

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Let's Connect

304.9KLike
8.4KFollow
LinkedInFollow

Popular Posts

How to Configure Nginx as a Reverse Proxy (Step-by-Step)

Hasan Hashmi
13 Min Read

Learn Docker with Practical Examples: A Complete Beginner’s Guide

Hasan Hashmi
13 Min Read

Low-Code vs. Traditional Coding in 2026: Which Is Better for Developers?

Hasan Hashmi
11 Min Read

Monorepo vs Multirepo: Which Is Better for Modern Development?

Hasan Hashmi
6 Min Read

You Might Also Like

CybersecurityDevelopmentProgrammingTech News

Top 3 VPNs to Keep Your Online Privacy Safe

10 Min Read
How-To GuidesProgrammingTech News

How to Contribute to Open Source as a Beginner

7 Min Read
How-To Guides

Most Popular Backend Frameworks in 2025

3 Min Read
DevelopmentHow-To Guides

Web3 Development: How to Get Started as a Beginner

7 Min Read
Flymingo Tech - Blogs
Flymingo Tech specializes in delivering innovative IT solutions, empowering businesses to enhance their operational efficiency, streamline workflows, and drive growth through the use of cutting-edge technology, customized software development, and forward-thinking digital strategies.
  • +91 7378658675
  • contact@flymingotech.com

Social Networks

Facebook-f Twitter Instagram Linkedin

© 2024 Flymingo Tech. All rights reserved.

Welcome Back!

Sign in to your account

Username or Email Address
Password

Lost your password?