Hello team,
we are encountering an issue while working with the Jira Assets API to save a schema and mapping. The process worked fine until we attempted to save a larger schema, which led us to hit the Forge limitation of 55 seconds per asynchronous event. To mitigate this, we decided to use the async
param as described in the Assets API documentation.
However, when using the async=true
parameter, we receive a 401 Unauthorized
response. Notably, the API call works as expected without the async
parameter.
const res = await api
.asApp()
.requestJira(
route`/jsm/assets/workspace/${data.workspaceId}/v1/importsource/${data.importId}/mapping?async=true`,
{
method: data.status == "NOT_CONFIGURED" ? "PUT" : "PATCH",
body: JSON.stringify({
"schema": subscriptionSchema(data.rootObjectType),
"mapping": subscriptionMapping(data.rootObjectType)
}),
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
}
);
We do believe that the scopes and permissions in our manifest.yml
file are correctly configured:
permissions:
scopes:
- import:import-configuration:cmdb
- read:jira-work
- storage:app
external:
fetch:
backend:
- https://api.atlassian.com
Do you have any idea what might be causing the 401
error when the async
parameter is included? This would make our day. Thank you
Hi @MartinFischer , are you able to provide me with your appId so I can dig a bit further?
Hello @BoZhang, sure thing. AppId: ari:cloud:ecosystem::app/5c433676-525e-4481-9601-5a4227da8cea - hope it will help as it is quite crucial for us
Hey @MartinFischer, I had a look at the logs. I found the following for the appId that you’ve mentioned.
- For the particular endpoint that you’ve attached (i.e
/importsource/{uuid}/mapping
docs), I can’t find any instances of 401 errors in the last 3 days.
- I did however find some 401 errors for calls to
GET /importsource/{importSourceId}/mapping/progress/{resourceId}
. I think the reason here is that the resourceId
path param is not set, which triggers the permissions checks in our edge services to complain. Are you able to confirm that you are populating this path param in your app?
Let me know if you need me to look at anything else
Hi @BoZhang
Thanks for your response. I realized that we initially tested this through a tunnel, which is likely why no logs were captured—apologies for any confusion. I’ve now tested it again in my dev environment, so you should be able to see it in the logs now.
A few notes:
- It seems one of my colleagues may have experimented with the
"/importsource/{importSourceId}/mapping/progress/{resourceId}"
endpoint before we realized that the resourceId
likely needs to be obtained using the async import schema approach, which unfortunately doesn’t work for us.
- Notably, when we initially tried using the async parameter, we encountered a 403 egress error because, most likely, “api.atlassian.net” was missing from our manifest file. After adding it, the error changed to a 401. Interestingly, without using the async parameter, the endpoint (
/importsource/{uuid}/mapping
) works fine, but with it, we consistently get the 401 error. In the developer console logs, we can see that access to “api.atlassian.net” returns a 401 when the async parameter is used.
Hi @MartinFischer, thanks for the extra info, I had another look and can now see the 401 errors for this endpoint. What’s happening is that this endpoint tries to redirect to a URL that is outside the original request’s base URL. A security feature that we have in place for Forge will prevent these redirects from happening and unfortunately, it’s blocking this request at the moment.
Please allow me some time to talk to the relevant people to try sort this out. Sorry about the inconvenience.
2 Likes
Hi @MartinFischer, I asked around and it seems like others have experienced this issue, the temporary work around is to manually follow redirects, like:
const res = await api
.asApp()
.requestJira(
route`/jsm/assets/workspace/${data.workspaceId}/v1/importsource/${data.importId}/mapping?async=true`,
{
// ... your existing request options
redirect: 'manual'
}
);
// manually get the progress url that you would be redirected to
const progressUrl = res.headers.get('Location');
// if no location header, then something has gone wrong
if (!progressUrl) {
throw new Error(`Did not receive a progressUrl. Status was: ${res.status}`);
}
// make another request for the progressUrl using asApp
We will try to find a proper fix for the issue, but in the meantime, are you able to try this workaround?
4 Likes
Hello @BoZhang. Thank you for providing this workaround solution. It seems to be functional (we will proceed with testing). For now, we can consider it as a solution. We appreciate your time and prompt responses.
2 Likes