Authentication (JWT & Bcrypt) in Node.js

When building a login system in Node.js, two questions matter: 


  • How do you store passwords safely?

  • How do you verify users after login?


This is where Bcrypt and JWT (JSON Web Token) come in. Bcrypt secures passwords using hashing. On the other hand, JWT in Node.js handles authentication without storing sessions on the server. 


In this blog, we will cover: 


  • How does Bcrypt work?

  • How to implement JWT authentication in Node.js? 

  • How to combine both to build secure apps?

What is Bcrypt and How Does it Work?

When users register on your Node.js application, you should never store their passwords directly in the database. Instead, you convert it into a secure format using bcrypt encoding. 


Bcrypt is a password hashing library designed to securely store passwords. Unlike simple hashing algorithms (like SHA256), bcrypt is: 


  • Slow by design to prevent brute-force attacks

  • Automatically salted (adds randomness to each password)

  • Adaptive (you can increase its strength over time)


In Node.js projects, it is installed using npm: 

npm install bcrypt


Here’s how bcrypt works when a user signs up: 


  • User enters a password

  • Bcrypt generates a salt (random string)

  • The password + salt is hashed together

  • The final hash is stored in the database


Example of Bcrypt Hashing Process: 


const bcrypt = require('bcrypt');


const plainPassword = "user123";

const saltRounds = 10;


async function hashPassword() {

  const hashedPassword = await bcrypt.hash(plainPassword, saltRounds);

  console.log(hashedPassword);

}


hashPassword();


When a user logs in:


const bcrypt = require('bcrypt');


async function comparePassword(inputPassword, storedHash) {

  const isMatch = await bcrypt.compare(inputPassword, storedHash);

  console.log(isMatch); // true or false

}

Benefits of Bcrypt 

Simple hashing is not enough in real-world applications. Here’s why bcrypt encoding is still one of the most trusted methods for password security in modern Node.js applications: 

Built-in Salting

Bcrypt automatically adds a unique salt to every password before hashing. You don’t need to manually generate salts. Brcypt handles it internally. This means: 


  • Two users with the same password will have different hashes

  • Attackers cannot use precomputed rainbow tables to crack passwords

Slow By Design to Prevent Brute Force Attacks

Unlike fast hash algorithms, bcrypt is intentionally slow. If an attacker tries millions of password combinations, bcrypt slows them down significantly. You control this using salt rounds: 

const saltRounds = 10;

Adaptive Security

Hardware gets faster every year. What’s secure today may not be secure tomorrow. Bcrypt allows you to increase the cost factor (salt rounds) over time without changing your entire system. This makes it future-ready. 

Industry Standard 

If you are preparing for interviews or building client projects, knowing bcrypt is expected. From startups to enterprise apps, bcrypt is widely used in: 


  • Authentication systems

  • REST APIs

  • MERN stack projects

  • Production Node.js backends

Simple Integration with Node.js

Using <npm install bcrypt>, you can quickly implement secure password storage without complex cryptography knowledge. That’s why bcrypt remains the first step in secure JWT authentication for Node.js systems. 

What is JWT and How is it Used?

A JSON Web Token (JWT) is a compact, secure way to transmit user information between the client and server. This makes authentication stateless and eliminates the need to store sessions on the server. After login: 


  • Server verifies credentials

  • Server generates a JWT token in Node.js

  • The token is sent to the client

  • The client sends this token in future requests

  • The server verifies the token instead of asking for login again


Here’s how you can install JSON Web Token in Node.js: 

npm install jsonwebtoken


A JWT has 3 parts (Header, Payload, and Signature). 

For example: 

xxxxx.yyyyy.zzzzz


Here is an example of creating a JWT Token: 

const jwt = require('jsonwebtoken');


const user = { id: 1, email: "[email protected]" };


const token = jwt.sign(user, "secretKey", { expiresIn: "1h" });


console.log(token);


  • <jwt.sign()> creates the token

  • <”secretkey”> is used to generate the signature

  • <expiresIn> adds security by limiting token validity


Token validation: 

jwt.verify(token, "secretKey", (err, decoded) => {

  if (err) {

    console.log("Invalid Token");

  } else {

    console.log(decoded);

  }

});

How to Combine Bcrypt and JWT for Enhanced Security?

Individually, bcrypt encoding and JWT authentication in Node.js are powerful. Together, they form a complete, production-ready authentication system. Most beginners understand them separately but struggle to connect the flow. Here’s the authentication flow in a typical node js json web token system: 

Step 1: User Registration

  • User enters password

  • Password is hashed using bcrypt

  • Only the hashed password is stored in the database

const bcrypt = require("bcrypt");


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


The database stores encrypted data like <$2b$10$kjsdfhksjdfhksjdfhksjdfh..>, instead of the actual password. 

Step 2: User Login

  • User enters email + password

  • Server fetches stored hash

  • <bcrypt.compare()> verifies the password


const isMatch = await bcrypt.compare(inputPassword, user.password);


  • If false > Login fails

  • If true > Move to the next step

Step 3: Generate JWT Token

After successful password verification: 

const jwt = require("jsonwebtoken");


const token = jwt.sign(

  { userId: user._id },

  process.env.JWT_SECRET,

  { expiresIn: "1h" }

);


This creates the JWT token that the client will use for future requests. 

Step 4: Access Protected Routes

When the user accesses a protected API: 


  • Token is sent in headers

  • Server verifies using <jwt.verify()>


jwt.verify(token, process.env.JWT_SECRET);


  • If valid > Access granted

  • If invalid > 401 unauthorized

Best Practices for Using Bcrypt and JWT

Many beginners learn JWT authentication Node JS from tutorials but miss critical security practices. In real-world projects, these small mistakes can create major vulnerabilities. Here are some best practices for using Bcrypt and JWT: 

Never Store JWT Secret in Code

Avoid codes like: 

jwt.sign(payload, "mySecretKey");


Instead, use environment variables: 


jwt.sign(payload, process.env.JWT_SECRET);


Store secrets in a <.env> file and never push them to GitHub. This is basic but often ignored in beginner projects. 

Set Expiry for Every JWT

Always define <expiresIn>

{ expiresIn: "1h" }


If a token gets stolen, expiry limits damage. Never create permanent tokens in production systems. 

Use Proper Salt Rounds for Bcrypt

Balance security and performance with: 

const saltRounds = 10;


  • 8-12 rounds are common for most Node.js apps

  • Don’t use very low values just for speed

  • Don’t go too high without testing performance

Always Use HTTPS in Production

JWT tokens are sent in headers. If your API runs on HTTP, tokens can be intercepted. For production: 


  • Use HTTPS

  • Enable secure cookies (if storing tokens in cookies)

Validate JWT in Middleware

Instead of verifying tokens in every route, create middleware: 

function authenticateToken(req, res, next) {

  const token = req.headers.authorization?.split(" ")[1];


  if (!token) return res.sendStatus(401);


  jwt.verify(token, process.env.JWT_SECRET, (err, user) => {

    if (err) return res.sendStatus(403);

    req.user = user;

    next();

  });

}

Never Store Sensitive Data Inside JWT Payload

JWT payload is base64 encoded, not encrypted. Do not store passwords, bank details, or personal secrets. Kee the payload minimal. 


{ userId: user._id }

Keep Dependencies Updated

If you are using <jsonwebtoken node js>, <bcrypt>, or <npm jwt> packages, keep them updated regularly to avoid vulnerabilities. 

Final Words

If you truly want to build secure applications in Node.js, learning routing and CRUD operations alone is not enough. Authentication is what transforms a basic backend project into a production-ready system. 


Bcrypt encoding ensures that the user passwords are never stored in plain text, reducing the risk even if your database is compromised. JWT in Node.js enables stateless authentication, allowing your server to verify users without storing session data. Together, they form the backbone of modern JWT authentication used in real-world APIs. 


Implement this complete flow in a small project. Test edge cases. Break it intentionally and fix that. That hands-on clarity is what production systems demand. 

Frequently Asked Questions (FAQs)

Q1. What is JWT in Node.js?


Ans. JWT (JSON Web Token) in Node.js is a secure method for handling authenticationusing digitally signed tokens instead of server-side sessions. After login, the server generates a JWT token using the <jsonwebtoken> library, which the client sends with future requests. The server verifies the token signature before granting access. 


Q2. How does bcrypt work in Node.js?


Ans. Bcrypt works by converting a plain-text password into a secure hash using a salt and multiple hashing rounds. When a user logs in, bcrypt compares the entered password with the stored hash using <bcrypt.compare()>. It does not decrypt passwords. This one-way hashing process makes bcrypt encoding highly secure forstoring credentials. 


Q3. Is JWT better than session-based authentication?


Ans. JWT is better for APIs and scalable applications because it is stateless. The server does not need to store session data, which improves performance and scalability. However, JWT must be implemented correctly with token expiry, secure storage, and proper verification middleware to avoid vulnerabilities. 


Q4. What is the difference between hashing and encryption?


Ans. Hashing is a one-way process used for storing passwords securely, which is what bcrypt encoding does. Encryption is reversible using a key. In authentication systems, passwords should always be hashed, not encrypted.

Discover More Courses on Skillwaala