Facebook Pixel

How JWT Works in Node.js: Step by Step

JWT is the common way to do stateless auth. Here is how it works, step by step.

How JWT Works in Node.js: Step by Step

JWT (JSON Web Token) is the common way to do stateless auth in Node.js. Here is how it works, step by step.

What Is a JWT

A JWT is a signed string with three parts: header, payload, signature. The header says which algorithm. The payload carries claims (user id, role, expiry). The signature proves the token was not tampered with.

The Three Parts

header.payload.signature

  • header: base64url-encoded JSON like { alg: 'HS256', typ: 'JWT' }.
  • payload: base64url-encoded JSON with claims like { userId: 'abc', role: 'user', exp: 1735689600 }.
  • signature: HMAC of header.payload using your secret. Proves the token was not tampered with.

Step 1: User Logs In

router.post('/login', asyncHandler(async (req, res) => {
  const { email, password } = req.body;
  const user = await User.findOne({ email }).select('+passwordHash');
  if (!user) return res.status(401).json({ error: 'Invalid credentials' });
  const match = await bcrypt.compare(password, user.passwordHash);
  if (!match) return res.status(401).json({ error: 'Invalid credentials' });
  const token = jwt.sign({ userId: user.id }, process.env.JWT_SECRET, { expiresIn: '7d' });
  res.cookie('token', token, { httpOnly: true, secure: true, sameSite: 'lax' });
  res.json({ user: toUserDTO(user) });
}));

Step 2: Client Sends the Token

For subsequent requests, the client sends the token. In a cookie (browser sends it automatically) or in the Authorization header (Bearer <token>).

Step 3: Server Verifies the Token

const auth = (req, res, next) => {
  const token = req.cookies.token || req.headers.authorization?.split(' ')[1];
  if (!token) return res.status(401).json({ error: 'Not authenticated' });
  try {
    const decoded = jwt.verify(token, process.env.JWT_SECRET);
    req.user = decoded;
    next();
  } catch {
    return res.status(401).json({ error: 'Invalid token' });
  }
};

jwt.verify checks the signature and the expiry. If valid, you get the payload. If not, you get an error.

Step 4: Handler Uses req.user

Now req.user has the userId and any other claims you signed. Handlers use it to scope queries:

router.get('/me', auth, asyncHandler(async (req, res) => {
  const user = await User.findById(req.user.userId);
  res.json(toUserDTO(user));
}));

Step 5: Logout Clears the Cookie

router.post('/logout', (req, res) => {
  res.clearCookie('token');
  res.json({ message: 'Logged out' });
});

The Takeaway

JWT has three parts: header, payload, signature. On login, sign a token with the user id and an expiry. Store it in an httpOnly cookie. On each request, verify the signature and expiry in an auth middleware; set req.user. Logout clears the cookie. JWT is stateless: the server does not store sessions.

On login, sign a token with jwt.sign({ userId }, secret, { expiresIn }). Store in an httpOnly cookie. On each request, verify with jwt.verify(token, secret) in an auth middleware. Set req.user from the payload. Logout clears the cookie. The server is stateless; no session store needed.

header.payload.signature. Header is base64url-encoded JSON with the algorithm. Payload is base64url-encoded JSON with claims (userId, role, exp). Signature is HMAC of header.payload using your secret, proving the token was not tampered with.

In an httpOnly, secure, sameSite cookie for web apps. The browser sends it automatically. In secure storage (Keychain, Keystore) for mobile. Do not use LocalStorage (open to XSS).

Read the token from req.cookies.token or the Authorization header. Call jwt.verify(token, process.env.JWT_SECRET). It checks the signature and expiry. If valid, set req.user from the payload and call next. If not, return 401.

The server does not store sessions. The token carries all the info (userId, role, expiry) and is signed so it cannot be tampered with. The server verifies the signature and expiry on each request, without looking up a session.

Ready to master Node.js completely?

Want to upskill yourself, crack your next interview, and get your dream job? Join our comprehensive course to dive deeper with high-quality video tutorials, solve interview questions, and a premium community.

Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.