I have an express app where some routes are public(accessible to everyone on the internet) and some are protected. I use JWT for route authentication. I have different type of users in the system, for example: author, subscriber etc. Some of the routes are meant to be access authors and some by subscribers. But there are a few routes which can be accessed by both author and subscribers.
To make sure when a user request to protected routes, I use middleware function for each category of users to verify their authentication token.
An example route accessible to authors only like this bellow,
router.get("/", verifyToken.author(), async (req, res) => {
try {
// doing stuff
} catch (err) {
// doing stuff
}
});
An example route accessible to subscribers only like this bellow,
router.get("/", verifyToken.subscriber(), async (req, res) => {
try {
// doing stuff
} catch (err) {
// doing stuff
}
});
PS: verifyToken.author() or any other middleware function I wrote for the purpose of verifying token are actually closure. Because sometimes I need to pass parameter in the functions. So, an example of these methods will be,
module.exposts.author = () => {
return (req, res, next) => {
const token = req.header("Authorization");
if (!token) return res.status(401).send({ message: "Access Denied!" });
try {
jwt.verify(token, process.env.AUTHOR_SECRET);
next();
} catch (err) {
res.status(401).send({ message: "Access Denied!" });
console.log(err);
}
};
};
And when I need to write a function for verifying token for both author and subscriber, I can just check do so and use the method as a middleware to the required route. But I am afraid it is not as simple as it sounds because in reality I don't have just these 2 type of users. And almost all the user types has complex route access where maybe 5 particular type of user can access the route.
As I was saying, let's say author and subscriber is among the 5 user types I said above. So writing a function for author+subscriber and writing another for 5 type of users where author, subscriber exists, it seems so much code duplication.
I hope I am able to explain why I just don't want to write something like this bellow,
module.exports.authorSubscriber = () => {
return (req, res, next) => {
const token = req.header("Authorization");
if (!token) return res.status(401).send({ message: "Access Denied!" });
try {
jwt.verify(token, process.env.AUTHOR_SECRET);
next();
} catch (err) {
try {
jwt.verify(token, process.env.SUBSCRIBER_SECRET);
next();
} catch (err) {
res.status(401).send({ message: "Access Denied!" });
console.log(err);
}
}
};
};
Instead, I want something like this, where I can re-use the function I wrote for author previously,
module.exports.authorSubscriber = () => {
return (req, res, next) => {
const token = req.header("Authorization");
if (!token) return res.status(401).send({ message: "Access Denied!" });
try {
jwt.verify(token, process.env.AUTHOR_SECRET);
next();
} catch (err) {
exports.author()
}
};
};
But, author() won't work here. It works when called from a route because then it gets the req, res, next. But in this case, it is being called from another function and no req, res, next is passed. If I do exports.author(req, res, next) in authorSubscriber and define author to accept these parameters. it still doesn't work. I think route middleware gets the 'req, res, next` automatically, these things can't be passed manually, can they? This was the reason I made these functions closure because on a similar verifier I need to pass a certain token and middleware doesn't take extra parameters.
I am confused. You may have clearly realized that I have knowledge gaps, that's why I am missing something here.
Please help.