I have public and private routes in an app.
// public
router.use(publicRoute);
// After this all Routes are private
router.use(runAsyncWrapper(isAuthenticated));
// private
router.use(privateRoute);
There is also a route that matches all possible routes, and returns a 404 error.
app.all('*', (req, res, next) => {
next(new MyError(`Route ${req.originalUrl} doesn not exist.`));
});
In the middleware I try to authenticate the user.
const isAuthenticated = async (req, res, next) => {
const {
headers: { authorization },
} = req;
const user = await tryToAuthenticateAndReturnUser(authorization);
if (!user) throw new MyError('Token is not valid', 401);
req.user = user;
next();
};
This middleware is run for any route that doesn't match any public route, even if the route itself doesn't exist. So if I request a route that doesn't exist, instead of 404 error it will return me the "Token is not valid", 401
error.
How do I make it return the right error, 404 if route doesn't exist, and 401 if route exists but user can't be authenticated?
CodePudding user response:
Try to apply the runAsyncWrapper
middleware only to the protected routes:
// public
router.use(publicRoute);
// private
router.use(runAsyncWrapper(isAuthenticated), privateRoute);
CodePudding user response:
I had to add the middleware for every route separately, as @kmp answered in the comments to my question. I could improve it a little bit, by adding middleware to routes using first word in routes' path.
For example, if we have such routes
GET `/users` //to get all users
POST `/users` //to create a user
GET `/posts/:userId` //to get posts of a user
POST `/posts/:userId` //to create a user's post
We can create an array like this
const protectedRoutes = ['/users', '/posts'];
and then add authentication middleware like this
protectedRoutes.forEach(route => router.use(route, runAsyncWrapper(isAuthenticated)))
After this every route that starts with /users
or /posts
will be protected.