Step 4
We want to protect all the routes related to users so only an admin can access them. A naive approach would be to copy and paste the following snippet for each and every route handler:
const { authorization } = req.headers;
const [_, token] = authorization.trim().split(" ");
const valid = await verifyToken(token);
const user = decodeToken(token);
if (!valid || user.role !== "ADMIN") {
return res.status(403).json({
message:
"You are not authorized to access this resource.",
});
}
A more elegant solution is to use an Express middleware function! According to its documentation:
Middleware functions are functions that have access to the request object (
req
), the response object (res
), and the next middleware function in the application's request-response cycle. The next middleware function is commonly denoted by a variable namednext
.Middleware functions can perform the following tasks:
- Execute any code.
- Make changes to the request and the response objects.
- End the request-response cycle.
- Call the next middleware function in the stack.
Add the following to the top of the server/routes/users.js
before handling any route requests:
const checkAdmin = async (req, res, next) => {
const { authorization } = req.headers;
const [_, token] = authorization.trim().split(" ");
const valid = await verifyToken(token);
const user = decodeToken(token);
if (!valid || user.role !== "ADMIN") {
return res.status(403).json({
message:
"You are not authorized to access this resource.",
});
}
next();
};
Then update the route handlers as follows:
- router.get("/api/users", async (req, res) => {
+ router.get("/api/users", checkAdmin, async (req, res) => {
// Remove the logic for authorization!
// No change is made to the rest of this route handler!
});
- router.get("/api/users/:id", async (req, res) => {
+ router.get("/api/users/:id", checkAdmin, async (req, res) => {
// No change is made to the body!
});
- router.post("/api/users", async (req, res) => {
+ router.post("/api/users", checkAdmin, async (req, res) => {
// No change is made to the body!
});
- router.delete("/api/users/:id", async (req, res) => {
+ router.delete("/api/users/:id", checkAdmin, async (req, res) => {
// No change is made to the body!
});
- router.put("/api/users/:id", async (req, res) => {
+ router.put("/api/users/:id", checkAdmin, async (req, res) => {
// No change is made to the body!
});
Save the changes. Then, using Postman, send a request to post to /api/users
and enclose the authorization token of a regular client (rather than an admin).
Notice the server responded with 403: Access forbidden!
Repeat the same process and this time enclose an admin token!