Skip to main content

Command Palette

Search for a command to run...

Understanding JWT Authentication in Node.js

Updated
•6 min read•View as Markdown
Understanding JWT Authentication in Node.js

Imagine you build a website where users can:

  • log in

  • upload files

  • create posts

  • view private data

Now think about this question:

How does the server know which user is making the request?

If someone opens:

/profile

how can the server decide:

  • whether the user is logged in

  • whether access should be allowed

This is where authentication comes in.

In this article, you'll learn:

  • what authentication means

  • what JWT is

  • JWT structure

  • how login works with tokens

  • sending tokens with requests

  • protecting routes using JWT

Everything will stay beginner-friendly and practical.


What Authentication Means

Authentication simply means:

Verifying who a user is

Example from real life:

When you enter a building, security may ask for:

  • ID card

  • fingerprint

  • password

After verification, you are allowed inside.

Web applications work similarly.


Why Authentication is Required

Without authentication:

  • anyone could access private data

  • users could modify other accounts

  • admin pages would be exposed

Example:

/dashboard

should only be accessible to logged-in users.

Authentication helps the server identify users safely.


Traditional Authentication vs Token Authentication

Earlier websites often used:

  • sessions

  • cookies stored on server

Modern applications commonly use:

  • JWT tokens

Why?

Because JWT authentication is:

  • simple

  • scalable

  • stateless


What Does “Stateless” Mean?

Stateless means:

Server does not store login information manually for every user

Instead:

  • the client stores the token

  • the token is sent with every request

The server only verifies the token.


Simple Real-World Analogy

Think of a movie ticket.

After buying a ticket:

  • you receive proof

  • staff checks the ticket later

  • they don't repeatedly ask for payment proof

JWT works similarly.

After login:

  • server gives a token

  • client stores it

  • token is shown with future requests


What is JWT?

JSON Web Token stands for:

JSON Web Token

It is a compact string used for:

  • authentication

  • user verification

  • protected routes

Example JWT:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

It may look scary initially…

But conceptually, it’s just a digital identity card.


JWT Authentication Flow

Image

Installing JWT Package

Most Node.js apps use:

jsonwebtoken

Install it:

npm install jsonwebtoken

Creating a Simple JWT

const jwt = require("jsonwebtoken");

const token = jwt.sign(
  { id: 1, name: "Aman" },
  "secretkey"
);

console.log(token);

This creates a JWT token.


Understanding jwt.sign()

jwt.sign(payload, secret)

Payload

Contains user data.

Example:

{
  id: 1,
  name: "Aman"
}

Secret

Used to verify token authenticity.

"secretkey"

In real apps:

  • store secrets in environment variables

  • never hardcode them


Structure of a JWT

A JWT has 3 parts:

HEADER.PAYLOAD.SIGNATURE

Example:

xxxxx.yyyyy.zzzzz

Each section has a purpose.


1. Header

Contains metadata about the token.

Example:

{
  alg: "HS256",
  typ: "JWT"
}

This tells:

  • token type

  • algorithm used


2. Payload

Contains actual user data.

Example:

{
  id: 1,
  role: "user"
}

Common payload data:

  • user ID

  • email

  • role

Important:

Do NOT store sensitive data like:

  • passwords

  • credit card info

inside JWT payloads.


3. Signature

Used to verify:

  • token integrity

  • token authenticity

The server checks:

  • whether token was modified

  • whether token is valid

You usually don't handle this manually.

Libraries handle it automatically.

Image

Login Flow Using JWT

Let’s create a very basic login example.


Login Route

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

  const user = {
    id: 1,
    email: "aman@gmail.com"
  };

  const token = jwt.sign(user, "secretkey");

  res.json({
    token
  });
});

When login succeeds:

  • token gets generated

  • token is sent to client


What Happens After Login?

The frontend stores the token.

Usually inside:

  • localStorage

  • cookies

Example:

localStorage.setItem("token", token);

Now the user is considered logged in.


Sending Token with Requests

When accessing protected routes, the client sends the token.

Usually inside request headers.

Example:

fetch("/profile", {
  headers: {
    Authorization: token
  }
});

The server reads this token and verifies it.


Protecting Routes Using Tokens

Suppose this route should only work for logged-in users:

/profile

We create middleware to verify JWT.


JWT Verification Middleware

function verifyToken(req, res, next) {

  const token = req.headers.authorization;

  if (!token) {
    return res.send("Access denied");
  }

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

    if (err) {
      return res.send("Invalid token");
    }

    req.user = decoded;

    next();
  });
}

Using Protected Routes

app.get("/profile", verifyToken, (req, res) => {

  res.json({
    message: "Protected data",
    user: req.user
  });

});

Now:

  • only valid tokens can access this route

Before vs After Authentication

Without Authentication

Anyone can access:

/profile

No restrictions.


With JWT Authentication

Only users with valid tokens can access protected routes.


Complete Minimal Example

const express = require("express");
const jwt = require("jsonwebtoken");

const app = express();

app.use(express.json());

function verifyToken(req, res, next) {

  const token = req.headers.authorization;

  if (!token) {
    return res.send("Access denied");
  }

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

    if (err) {
      return res.send("Invalid token");
    }

    req.user = decoded;

    next();
  });
}

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

  const user = {
    id: 1,
    name: "Aman"
  };

  const token = jwt.sign(user, "secretkey");

  res.json({ token });
});

app.get("/profile", verifyToken, (req, res) => {

  res.json({
    message: "Protected route",
    user: req.user
  });

});

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

Important Beginner Security Tips

Never Store Passwords Inside JWT

Wrong:

{
  password: "123456"
}

JWT payloads are readable after decoding.


Use Strong Secret Keys

Weak secrets are dangerous.

Bad:

"123"

Better:

process.env.JWT_SECRET

Add Token Expiry

Tokens should expire after some time.

Example:

jwt.sign(user, "secretkey", {
  expiresIn: "1h"
});

This improves security.


Simple Real-World Analogy

Imagine entering a concert.

After verification:

  • you receive a wristband

Security later checks:

  • wristband validity

instead of asking for your identity repeatedly.

JWT tokens work similarly.


Small Practice Assignment

Task 1

Create a login route that returns a JWT token.


Task 2

Send the token using request headers.


Task 3

Create middleware that:

  • checks token existence

  • verifies token


Task 4

Protect a route like:

/dashboard

using JWT middleware.


Task 5

Add token expiry using:

expiresIn