User context is lost in connect remote - /jql/parse validation fails

I’m in the process of migrating an existing ACE app to Forge. As a first step, I’ve configured the original ACE app to run as a Connect remote within a Forge app.

Everything works as expected when accessing the app through Connect modules - except for a backend validation routine that parses JQL queries via the Jira REST API. Specifically, the following call to /rest/api/3/jql/parse fails because the user context seems to be lost (i.e. project names are not recognized etc.).

Here’s the relevant code snippet:

> const httpClient = addon.httpClient(req);
> httpClient.post({
>       url: '/rest/api/3/jql/parse',
>       headers: {
>         Accept: "application/json",
>         "Content-Type": "application/json",
>       },
>       body: JSON.stringify({
>         queries: [query]
>       })
>     },
>       function (err, response, contents) {
>         if (err || (response.statusCode < 200 || response.statusCode > 299)) {
>           reject(Error("Validation service failed: " + err));
>           return;
>         } else {
>           contents = JSON.parse(contents);
>           if (contents.queries[0].errors) {
>             reject(Error("Invalid query: " + contents.queries[0].errors[0]));
>             return;
>           }
>           resolve(contents.queries[0]);
>           return;
>         }
> 
>       }
>     );

To fix this, I tried to impersonate the user by calling the API through asUserByAccountId, like so:

> httpClient.asUserByAccountId(req.context.userAccountId).get(
>   { url: '/rest/api/3/myself' },
>   function (err, res, body) {
>     console.log('Calling as user:', body);
>   }
> );

However, this fails with the following error:

> {
>   "error": "invalid_grant",
>   "error_description": "The oauth client ID in the issuer string was the literal 'undefined'. This is probably because your add-on does not have the `ACT_AS_USER` scope (or didn't have it at the time it was installed). Please add `ACT_AS_USER` to the `scopes` section of your descriptor, and re-install the add-on."
> }

The app already uses the ACT_AS_USER scope and also the req.context.userAccountId is correctly populated.

Question
What’s the correct way to preserve the user context when using a Connect app as a remote for a Forge app - in particular when validating user queries with the JQL /parse endpoint?

Any insights would be much appreciated.

Thank you!

Are you attempting the impersonation in the context handling a Forge Remote call addon.authenticateForge()?

Do you have this in your manifest.yml?

permissions:
  scopes:
    - act-as-user:connect-jira

Are you attempting the impersonation in the context handling a Forge Remote call addon.authenticateForge()?

No, the ACE route performing the query validation is invoked from within an iframe of a Connect module. The token is obtained using:

AP.context.getToken(function (token) { ...

Having added the additional scope to the manifest.yml, the impersonation now fails with:

Calling as user: {"error": "Add-on '<my app key>' disallowed to impersonate the user because 'no valid active user exists'"}

It turned out that req.context.userAccountId was being corrupted by a middleware. Impersonation is working correctly now. Thank you for your support @jhazelwood!

1 Like