Securing API Routes with Authentication Middleware

Securing API Routes with Authentication Middleware

Last updated: 3/7/2025

1 hour
Medium

Securing API Routes with Authentication Middleware

🌍 Introduction

Now that we’ve implemented user authentication and JWT-based login, we need to protect API routes so only authenticated users can access them.

In this lesson, you’ll learn: βœ… How to create authentication middleware in Express.js.
βœ… How to secure API routes using JWT tokens.
βœ… How to return proper error responses for unauthorized access.


πŸ“Œ 1. Why Do We Need Authentication Middleware?

Right now, anyone can access our API routes.
We need middleware to: πŸ”Ή Verify the JWT token before allowing access.
πŸ”Ή Reject unauthorized requests with a 401 Unauthorized error.
πŸ”Ή Pass valid users to the next middleware function.


πŸ“Œ 2. Creating Authentication Middleware

Create a new file middleware/auth.js and add the following code:

const jwt = require("jsonwebtoken"); module.exports = function (req, res, next) { const token = req.header("Authorization"); // Check if token is provided if (!token) { return res.status(401).json({ error: "Access denied. No token provided." }); } try { // Verify token const decoded = jwt.verify(token.replace("Bearer ", ""), process.env.JWT_SECRET); req.user = decoded; // Attach user data to request next(); // Continue to the protected route } catch (error) { res.status(400).json({ error: "Invalid token" }); } };

βœ” Checks for token in the Authorization header.
βœ” Verifies the token using jwt.verify().
βœ” Attaches user info (req.user) to the request for later use.
βœ” Returns 401 Unauthorized if the token is missing or invalid.


πŸ“Œ 3. Protecting API Routes with Middleware

Now, we’ll protect a profile route so only authenticated users can access it.

Modify routes/auth.js:

const authMiddleware = require("../middleware/auth"); router.get("/profile", authMiddleware, async (req, res) => { res.json({ message: "Welcome to your profile!", userId: req.user.userId }); });

βœ” The authMiddleware runs before handling the request.
βœ” If valid, the user can access the /profile route.
βœ” If invalid, the API returns an error response.


πŸ“Œ 4. Testing the Protected Route

βœ… 1️⃣ Accessing /profile Without a Token

❌ Request:

GET /auth/profile

❌ Response:

{ "error": "Access denied. No token provided." }

βœ… 2️⃣ Accessing /profile With a Valid Token

βœ” Request:

GET /auth/profile Authorization: Bearer eyJhbGciOiJIUzI1NiIs...

βœ” Response:

{ "message": "Welcome to your profile!", "userId": "656a7f3bc4d91b0012a8d849" }

πŸ“Œ 5. Protecting Other Routes

We can now secure any route by adding authMiddleware.

Example: Protecting a GET /users route:

router.get("/users", authMiddleware, async (req, res) => { const users = await User.find(); res.json(users); });

🎯 Summary

  • Authentication middleware ensures that only logged-in users can access protected routes.
  • JWT tokens are verified before allowing access.
  • Unauthorized requests return a 401 Unauthorized error.
  • The middleware can be reused to protect multiple routes.

βœ… Next Lesson: Project – TodoList with Authentication

Now that we have authentication and protected routes, we’ll apply these concepts in a TodoList API with authentication. πŸš€