Creating a Middleware to Decode User from JWT ๐
In the previous tutorial, we successfully created a Login Endpoint that sends a
JWT (JSON Web Token) to the user after login. But right now, anyone can access our
notes API routes without logging in โ that is a big security problem!
To fix this, we need a middleware that checks every incoming request,
verifies the JWT token, and only allows access if the token is valid.
This is how real-world apps protect their private routes.
In this tutorial, we will learn:
fetchuser middlewareWhat is Middleware in Express JS?
A middleware is simply a function that runs between the incoming request and the final
route handler. It has access to the req (request), res (response),
and next function. When a middleware calls next(), Express moves on to the
next function in the chain โ either the next middleware or the route handler.
// Basic middleware structure
function myMiddleware(req, res, next) {
// do something
next(); // pass control to the next handler
}
Why Do We Need a JWT Middleware?
After a user logs in, our server sends them a JWT token. On every future request (like fetching, adding, or deleting notes), the user sends that token back inside the request header. Our middleware will:
id from the token.req.user so route handlers can use it.401 Unauthorized error if the token is invalid or missing.Step 1: Create the middleware File
Inside your project root, create a new folder called middleware and inside it
create a file called fetchuser.js.
cloudnotebook-backend/
middleware/
fetchuser.js
models/
routes/
index.js
Step 2: Install and Import jsonwebtoken
Make sure jsonwebtoken is already installed. If not, install it now:
npm install jsonwebtoken
Step 3: Write the fetchuser Middleware
Open middleware/fetchuser.js and write the following code.
This middleware reads the token from the header, verifies it, and attaches the decoded user to req.user.
const jwt = require("jsonwebtoken");
const JWT_SECRET = "your$ecretKey123"; // Use same secret as in auth routes
const fetchuser = (req, res, next) => {
// Get the token from the request header
const token = req.header("auth-token");
// If no token found, deny access
if (!token) {
return res.status(401).json({ error: "Access Denied. No token provided." });
}
try {
// Verify the token and decode the user data
const decoded = jwt.verify(token, JWT_SECRET);
// Attach the decoded user to the request object
req.user = decoded.user;
// Move to the next middleware or route handler
next();
} catch (error) {
return res.status(401).json({ error: "Invalid Token. Please authenticate." });
}
};
module.exports = fetchuser;
Step 4: How the Token Is Sent by the Frontend
When the user logs in, they receive a JWT token. For every protected request after that, the frontend must send the token inside the HTTP header like this:
// Frontend sending token with every protected request
fetch("http://localhost:5000/api/notes/fetchallnotes", {
method: "GET",
headers: {
"auth-token": "your_jwt_token_here",
"Content-Type": "application/json",
},
});
Step 5: Use the Middleware in a Protected Route
Now let's use our fetchuser middleware to protect the notes route.
Import it in your routes/notes.js file and add it before the route handler.
const express = require("express");
const router = express.Router();
const fetchuser = require("../middleware/fetchuser");
// Protected Route โ only accessible with a valid JWT token
// GET /api/notes/fetchallnotes
router.get("/fetchallnotes", fetchuser, async (req, res) => {
try {
// req.user is now available thanks to our middleware
console.log("Logged in user ID:", req.user.id);
res.json({ message: "Notes fetched successfully!", userId: req.user.id });
} catch (error) {
console.error(error.message);
res.status(500).send("Internal Server Error");
}
});
module.exports = router;
How the Middleware Flow Works
| Step | What Happens |
|---|---|
| 1. Request arrives | Frontend sends a GET/POST request with auth-token in the header |
| 2. Middleware runs | fetchuser middleware intercepts the request before the route handler |
| 3. Token missing? | Returns 401 Unauthorized โ request is blocked |
| 4. Token invalid? | Returns 401 Invalid Token โ request is blocked |
| 5. Token valid | User is decoded, attached to req.user, and next() is called |
| 6. Route handler runs | The actual route logic runs with access to req.user.id |
โ ๏ธ Important Note
Always store your JWT_SECRET key in a .env file โ never hardcode it directly in your source code.
Add .env to .gitignore so it is never pushed to GitHub.
Example .env file:
JWT_SECRET=your$ecretKey123
Usage in code:
const JWT_SECRET = process.env.JWT_SECRET;
Features and Learnings:-
fetchuser middleware to verify and decode JWT tokens.req.user for use inside route handlers.401 error responses..env files.