Trying to secure an admin page in Atlassian Connect Express with addon.authorizeJira({ global: ["ADMINISTER"] })

I’m using the following logic to secure a configuration screen for Jira admins only:

  app.get(
    "/configure",
    [
      addon.authenticate(true /* accept context JWTs */),
      // only allow product admins
      addon.authorizeJira({ global: ["ADMINISTER"] }),
    ],
    (req, res) => {
      res.status(200).send("OK");
    }
  );

When attempting to access this page as a user with membership of the site-admins group on a site where this group is mapped to Jira Product Administration, I get a 401, not authorized when calling the /configure route.

The message in logs shows:

Authorization failed
GET /configure?key=configure--configure-page&...&jwt=eyJ0eXAiOiJKV1QiLC...5llWqDHdg0 401 28.573 ms - 49

This code very closely follows the ACE 7.1.5+ example at Connect app authorization

The Jira user in question has full access to all the standard Jira admin screens.

What’s wrong here?

1 Like

Which atlassian-connect-expression version you’re using?

Based on the error (see authorization.js) it seems that project permissions are being checked and fail due to missing project/issue context (you are accessing non-issue endpoint, right?)

1 Like

@david see Unauthorized: permissions could not be determined on "atlassian-connect-express": "^7.4.6" - #4 by dmorrow

1 Like

@ViliusZigmantas & @marc I was using v7.4.1, so updating to 7.4.7 fixed the problem.

This code now totally works with ACE 7.4.7:

  app.get(
    "/configure",
    [
      addon.authenticate(true /* accept context JWTs */),
      // only allow product admins
      addon.authorizeJira({ global: ["ADMINISTER"] }),
    ],
    (req, res) => {
      res.status(200).send("OK");
    }
  );

For ACE < 7.4.7, instead this works just fine:

 const userIsJiraAdmin = (httpClient, userAccountId) => {
    return new Promise((resolve, reject) =>
      httpClient.post(
        {
          url: "/rest/api/3/permissions/check",
          headers: {
            "X-Atlassian-Token": "nocheck",
          },
          anonymous: !userAccountId,
          json: {
            globalPermissions: ["ADMINISTER"],
            accountId: userAccountId,
          },
        },
        function (err, _, body) {
          if (err) {
            reject(err);
            return;
          }

          if (body.hasOwnProperty("errors")) {
            reject(body.errors);
            return;
          }

          const isAdmin = body.globalPermissions.indexOf("ADMINISTER") !== -1;
          resolve(isAdmin);
        }
      )
    );
  };
  app.get(
    "/configure", 
    [ addon.authenticate(true /* accept context JWTs */)] , 
    async (req, res) => {
      const { userAccountId } = req.context;
      if (!(await userIsJiraAdmin(addon.httpClient(req), userAccountId))) {
        res.status(401).send("Unauthorized: you must be a Jira admin");
        return;
      }
      res.status(200).send("OK");
    }
  );
3 Likes