Securing your backend routes is crucial when building modern web applications. One of the most common and secure ways to handle authentication is by using JWT (JSON Web Tokens).
In this guide, you’ll learn:
- What JWT is
- How to implement login/signup
- How to protect routes using tokens in an Express.js app
- Adding encryption using bcryptjs to store hashed passwords
What is JWT?
JWT (JSON Web Token) is a compact, URL-safe token used to securely transmit information between parties. It has three parts:
- Header – Type and algorithm
- Payload – User info (e.g. ID, email)
- Signature – Verifies the token's authenticity
A sample token looks like:
eyJhbGciOi... (header). (payload). (signature)
Step 1: Setup
Install required packages:
npm install express jsonwebtoken bcryptjs dotenv
Also set up your project:
npm init -y
Create a basic server.js
:
import express from 'express';
import dotenv from 'dotenv';
dotenv.config();
const app = express();
app.use(express.json());
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => console.log(`Server running on port ${PORT}`));
Step 2: Mock User Database (In-Memory for Demo)
const users = []; // This would be replaced with a real database
Step 3: Signup Route (Register User)
import bcrypt from 'bcryptjs';
app.post('/signup', async (req, res) => {
const { username, password } = req.body;
const existing = users.find(u => u.username === username);
if (existing) return res.status(400).json({ message: 'User already exists' });
const hashedPassword = await bcrypt.hash(password, 10);
users.push({ username, password: hashedPassword });
res.status(201).json({ message: 'User registered successfully' });
});
Step 4: Login Route (Generate JWT Token)
import jwt from 'jsonwebtoken';
app.post('/login', async (req, res) => {
const { username, password } = req.body;
const user = users.find(u => u.username === username);
if (!user) return res.status(400).json({ message: 'Invalid credentials' });
const isMatch = await bcrypt.compare(password, user.password);
if (!isMatch) return res.status(400).json({ message: 'Invalid credentials' });
const token = jwt.sign({ username }, process.env.JWT_SECRET, {
expiresIn: '1h'
});
res.json({ token });
});
.env
file:
JWT_SECRET=your_jwt_secret_key
Step 5: Middleware to Protect Routes
const authenticateToken = (req, res, next) => {
const authHeader = req.headers.authorization;
const token = authHeader && authHeader.split(' ')[1]; // Bearer <token>
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();
});
};
Step 6: Protected Route
app.get('/profile', authenticateToken, (req, res) => {
res.json({ message: `Hello, ${req.user.username}!` });
});
Testing the Flow
- POST /signup – Register a user
- POST /login – Get JWT token
-
GET /profile – Add
Authorization: Bearer <token>
header
Summary
Endpoint | Purpose | Protected? |
---|---|---|
POST /signup |
Register new users | ❌ |
POST /login |
Log in and get token | ❌ |
GET /profile |
Access user data | ✅ (JWT) |
Final Thoughts
JWT is a powerful tool for stateless authentication in Express. It’s ideal for APIs where you need to:
- Validate users
- Protect routes
- Handle sessions without storing them server-side
Top comments (0)
Some comments may only be visible to logged-in visitors. Sign in to view all comments.