JWT Authentication in Node.js
What is JWT?
JWT (JSON Web Token) is a compact, URL-safe token format for securely transmitting information between parties. Commonly used for authentication and authorization.
JWT Structure
header.payload.signature
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJ1c2VySWQiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIn0.
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5cParts:
- Header: Algorithm and token type
- Payload: Claims (user data)
- Signature: Verification signature
Installation
npm install jsonwebtoken bcryptjsCreating JWT
const jwt = require('jsonwebtoken');
// Generate token
const token = jwt.sign(
{ userId: user.id, email: user.email },
process.env.JWT_SECRET,
{ expiresIn: '1h' }
);
console.log(token);Verifying JWT
try {
const decoded = jwt.verify(token, process.env.JWT_SECRET);
console.log(decoded); // { userId, email, iat, exp }
} catch (err) {
console.error('Invalid token');
}Complete Authentication Example
const express = require('express');
const jwt = require('jsonwebtoken');
const bcrypt = require('bcryptjs');
const app = express();
app.use(express.json());
// Mock user database
const users = [];
// Register
app.post('/register', async (req, res) => {
try {
const { email, password } = req.body;
// Hash password
const hashedPassword = await bcrypt.hash(password, 10);
// Save user
const user = {
id: users.length + 1,
email,
password: hashedPassword
};
users.push(user);
res.status(201).json({ message: 'User created' });
} catch (err) {
res.status(500).json({ error: err.message });
}
});
// Login
app.post('/login', async (req, res) => {
try {
const { email, password } = req.body;
// Find user
const user = users.find(u => u.email === email);
if (!user) {
return res.status(401).json({ error: 'Invalid credentials' });
}
// Verify password
const validPassword = await bcrypt.compare(password, user.password);
if (!validPassword) {
return res.status(401).json({ error: 'Invalid credentials' });
}
// Generate token
const token = jwt.sign(
{ userId: user.id, email: user.email },
process.env.JWT_SECRET,
{ expiresIn: '1h' }
);
res.json({ token });
} catch (err) {
res.status(500).json({ error: err.message });
}
});
// Protected route
app.get('/profile', authenticateToken, (req, res) => {
res.json({ user: req.user });
});
// Middleware
function authenticateToken(req, res, next) {
const authHeader = req.headers['authorization'];
const token = authHeader && authHeader.split(' ')[1];
if (!token) {
return res.status(401).json({ error: 'No token provided' });
}
jwt.verify(token, process.env.JWT_SECRET, (err, user) => {
if (err) {
return res.status(403).json({ error: 'Invalid token' });
}
req.user = user;
next();
});
}Refresh Tokens
const refreshTokens = [];
// Login with refresh token
app.post('/login', async (req, res) => {
// ... authentication logic
const accessToken = jwt.sign(
{ userId: user.id },
process.env.JWT_SECRET,
{ expiresIn: '15m' }
);
const refreshToken = jwt.sign(
{ userId: user.id },
process.env.REFRESH_TOKEN_SECRET,
{ expiresIn: '7d' }
);
refreshTokens.push(refreshToken);
res.json({ accessToken, refreshToken });
});
// Refresh access token
app.post('/token', (req, res) => {
const { refreshToken } = req.body;
if (!refreshToken || !refreshTokens.includes(refreshToken)) {
return res.status(403).json({ error: 'Invalid refresh token' });
}
jwt.verify(refreshToken, process.env.REFRESH_TOKEN_SECRET, (err, user) => {
if (err) {
return res.status(403).json({ error: 'Invalid token' });
}
const accessToken = jwt.sign(
{ userId: user.userId },
process.env.JWT_SECRET,
{ expiresIn: '15m' }
);
res.json({ accessToken });
});
});
// Logout
app.post('/logout', (req, res) => {
const { refreshToken } = req.body;
const index = refreshTokens.indexOf(refreshToken);
if (index > -1) {
refreshTokens.splice(index, 1);
}
res.json({ message: 'Logged out' });
});Best Practices
- Use HTTPS in production
- Store tokens securely (httpOnly cookies)
- Set appropriate expiration times
- Implement refresh tokens for long sessions
- Never store sensitive data in payload
- Use strong secrets for signing
- Validate tokens on every request
Interview Tips
- Explain JWT structure: Header, payload, signature
- Show token generation: jwt.sign()
- Demonstrate verification: jwt.verify()
- Discuss security: HTTPS, secrets, expiration
- Mention refresh tokens: Long-lived sessions
- Show middleware: Authentication middleware
Summary
JWT is a token-based authentication method. Generate tokens with jwt.sign(), verify with jwt.verify(). Include userId in payload, set expiration time. Use middleware to protect routes. Implement refresh tokens for better security.
Test Your Knowledge
Take a quick quiz to test your understanding of this topic.