Home > Software design >  Authentication middleware is called for routes that don't exist
Authentication middleware is called for routes that don't exist

Time:02-12

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.

  • Related