Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Middleware is executed when using Postman, ignored when running API test with axios #5481

Closed
ShookTea opened this issue Feb 15, 2024 · 0 comments
Labels

Comments

@ShookTea
Copy link

ShookTea commented Feb 15, 2024

Context

I'm using express in version 4.18.2.

I've created a following two functions that create Express middleware:

  • authenticate - checks for presence of a valid access token, returns HTTP Unauthorized response if it doesn't, otherwise calls next()
  • authorize(permissions) - checks if logged in user (as verified in authenticate) has required permissions, returns HTTP Forbidden response if it doesn't, otherwise calls next().

Here's the code: (note the logger.verbose usages)

import { header } from 'express-validator';
//...

export function authenticate() {
  return [
    header('authorization')
      .isLength({ min: 1 })
      .withMessage('Authorization header required'),
    (req, res, next) => {
      const token = req.headers.authorization?.split(' ') ?? [];
      if (token.length !== 2 || token[0].toLowerCase() !== 'bearer') {
        logger.verbose('Invalid access token type (only "bearer" accepted)');
        res.status(StatusCode.UNAUTHORIZED).send({'error': 'Invalid access token'});
        return;
      }

      const accessToken: Promise<AccessToken|null> = AccessToken.findOne({
        // database access
      });

      accessToken
        .then((at: AccessToken|null) => {
          if (!at) {
            logger.verbose('Access token not found');
            res.status(StatusCode.UNAUTHORIZED).send({'error': 'Invalid access token'});
          } else {
            req.user = at.user;
            logger.verbose(`User ${at.user.uuid} detected`);
            next();
          }
        })
        .catch((e) => {
          logger.error('ERROR!', e);
          res.status(StatusCode.INTERNAL_SERVER_ERROR).send();
        });
    }];
}

export function authorize(...permissions: Permission[]): ExpressMiddleware {
  return (req, res, next) => {
    logger.verbose(`Authorizing for permissions ${permissions}`);
    const user: User|null = req.user;
    if (!user) {
      logger.verbose('User is not authorized');
      res.status(StatusCode.UNAUTHORIZED).send({'error': 'Invalid access token'});
      return;
    }

    userHasPermission(user, ...permissions)
      .then((allow: boolean) => {
        if (allow) {
          logger.verbose('Permission granted!');
          next();
        } else {
          logger.verbose('Permission denied');
          res.status(StatusCode.FORBIDDEN).send({'error': 'Forbidden'});
        }
      })
      .catch((e) => {
        logger.error('ERROR!', e);
        res.status(StatusCode.INTERNAL_SERVER_ERROR).send();
      });
  };
}

Here's an example usage:

  router.get(
    '/users',
    authenticate(),
    authorize(Permission.USER_READ, Permission.USER_ALL),
    (req, res) => {
      // logic for the route
    }
  );

I'm writing a test for API using Jest and sending requests with Axios, like this:

const axios = axios.create({
  baseURL: 'http://localhost:8000',
  validateStatus: () => true,
});

axios.request({
  method: 'GET',
  url: '/users',
  headers: {
    'Authorization': 'Bearer {token}'
  }
})

Problem

When I manually test the endpoint with Postman, it works as expected: I get HTTP Unauthorized when the token is invalid, HTTP Forbidden when I don't have required permissions, otherwise the endpoint continues with its logic. All calls of logger.verbose are visible in the server console.

But when running Jest tests, while the first middleware, authenticate, works properly the second one, authorize, is not executed - the permissions of a user are ignored and all requests result with HTTP OK status. Even the log messages (like "Authorizing for permissions...") are not displayed in the server logs, while log messages from the first middleware are still printed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant