How Does JWT Authentication Work in Node.js?
Learn how JWT authentication works in Node.js: signing tokens, verifying them in Express middleware, and building stateless, scalable API security.
Expected Interview Answer
JWT authentication in Node.js works by issuing a signed JSON Web Token when a user logs in, then verifying that token's signature on each subsequent request instead of looking the user up in a session store.
A JWT has three Base64Url parts — header, payload (claims), and signature — joined by dots. The server signs the token with a secret (HS256) or private key (RS256) using a library like jsonwebtoken. The client stores the token and sends it in the Authorization: Bearer header; middleware calls jwt.verify() to check the signature and expiry, and if valid attaches the decoded claims to req.user. Because the signature proves integrity, the server stays stateless and needs no session lookup.
- Stateless — no server-side session storage required
- Scales easily across multiple servers and microservices
- Self-contained: claims travel with the request
- Works well for APIs and mobile clients
- Built-in expiry via the exp claim
AI Mentor Explanation
A JWT is like a signed player pass at a tournament. The gatekeeper signs it with the board's stamp when you enter, listing your name and role. At every gate you just flash it, and staff verify the stamp is genuine rather than phoning the registration desk each time.
Step-by-Step Explanation
Step 1
User logs in
Client posts credentials; server validates them against the database with a hashed password check (e.g. bcrypt).
Step 2
Sign the token
Server calls jwt.sign(payload, secret, { expiresIn }) to create a signed token embedding the user id and claims.
Step 3
Return token to client
The token is sent in the JSON response; the client stores it (memory, httpOnly cookie, or secure storage).
Step 4
Send on each request
Client attaches the token in the Authorization: Bearer <token> header on protected API calls.
Step 5
Verify in middleware
Server middleware runs jwt.verify(token, secret); on success it sets req.user, on failure it returns 401.
What Interviewer Expects
- The three parts of a JWT: header, payload, signature
- Difference between signing and encryption (JWTs are signed, not secret)
- Where and how tokens are stored and transmitted
- Handling expiry and refresh tokens
- Why JWT enables stateless authentication
Common Mistakes
- Thinking the payload is encrypted — it is only Base64Url encoded and readable
- Storing sensitive data like passwords inside the token
- Using a weak or hardcoded signing secret
- Not setting an expiry, making tokens valid forever
- Storing tokens in localStorage without considering XSS risk
Best Answer (HR Friendly)
“JWT authentication gives a user a digitally signed pass after they log in. On every later request the server just checks that the pass is genuine and not expired, so it doesn't need to remember each user in a database session, which makes the system simpler to scale.”
Code Example
const express = require('express');
const jwt = require('jsonwebtoken');
const app = express();
app.use(express.json());
const SECRET = process.env.JWT_SECRET;
// Login: issue a signed token
app.post('/login', (req, res) => {
const { username } = req.body; // validate credentials first
const token = jwt.sign({ sub: username, role: 'user' }, SECRET, {
expiresIn: '1h',
});
res.json({ token });
});
// Middleware: verify the token
function auth(req, res, next) {
const header = req.headers.authorization || '';
const token = header.startsWith('Bearer ') ? header.slice(7) : null;
if (!token) return res.status(401).json({ error: 'No token' });
try {
req.user = jwt.verify(token, SECRET);
next();
} catch (err) {
return res.status(401).json({ error: 'Invalid or expired token' });
}
}
app.get('/profile', auth, (req, res) => {
res.json({ user: req.user });
});
app.listen(3000);Follow-up Questions
- How do refresh tokens work alongside access tokens?
- What is the difference between HS256 and RS256 signing?
- How would you revoke a JWT before it expires?
- Why is storing a JWT in localStorage risky?
- What claims are considered standard (registered) in a JWT?
MCQ Practice
1. Which three parts make up a JWT, separated by dots?
A JWT is header.payload.signature — the first two are Base64Url-encoded JSON and the third is the signature that proves integrity.
2. What does jwt.verify() primarily check?
verify() recomputes the signature with the secret and rejects the token if it is tampered with or past its exp claim.
3. Why can a JWT payload never hold a secret like a password?
Signing proves integrity, not confidentiality; the payload is readable by anyone who has the token, so secrets must not go in it.
Flash Cards
What are the three parts of a JWT? — Header, payload (claims), and signature — Base64Url encoded and joined by dots.
Is a JWT payload encrypted? — No. It is only Base64Url encoded and fully readable; the signature only guarantees integrity.
Which header carries a JWT to the server? — The Authorization header as 'Bearer <token>'.
What makes JWT auth stateless? — The server verifies the signature and claims from the token itself, needing no session store.