Unauthorized; scope does not match - Forge App

Hi guys

I seem to be having an issue I can’t figure out.

I created a forge app, using custom ui. The app is primarily for importing changes and then modifying Confluence pages.

I initially created it using the jira admin page module, forgetting that the app is for Confluence, but thought this wouldn’t really be an issue, because the app is just for once off use.

Anyway, I’m calling the below from the index.js using resolver as follows:

const fetchConfluencePage = async (spaceKey, pageTitle) => {
  console.log(`fetching for ${spaceKey} and page: ${pageTitle}`);
  const res = await api
    .asUser()
    .requestConfluence(route`/rest/api/content?type=page&spaceKey=${spaceKey}&title=${pageTitle}`);

  console.log(`Res: ${JSON.stringify(res)}`);
  const data = await res.json();
  console.log(`data found: ${JSON.stringify(data)}`);
  return data.results;
};

resolver.define('fetchConfluencePage', async (req) => {
  console.log(`Doing it: ${JSON.stringify(req)}`);
  return await fetchConfluencePage(req.payload.spaceKey, req.payload.pageTitle);
})

You can see I’m logging everything so that I can help myself debug this issue.
This is what I see in the logs.

I keep getting this:
“code”:401,“message”:“Unauthorized; scope does not match”

I keep adding scopes, I started off with this one:
read:confluence-content.summary
Then I just kept adding until it became this:

permissions:
  scopes:
    - 'read:confluence-content.summary'
    - 'write:confluence-content'
    - 'read:confluence-space.summary'
    - 'read:confluence-content.all'
    - 'search:confluence'

But still no luck.

Can anyone see what I’m doing wrong? Is it because I’m using the resolver/jira admin page?

  • Jarrod
1 Like

Hi guys, I figured it out on my own :grinning:

But let me share what I found, in case someone else has this issue.

Turns out, what may actually be obvious, is that you need to create the app, according to the product you want to use it in. Since I created it as a Jira app, turns it out, it would never work.

I needed to recreate the app, as a confluence app. Simply changing the module in the manifest, doesn’t seem to work either. I’m guessing it has something to do with the app id. So it actually needs to be completely recreated.

Hope this helps anyone else in the world having this issue. :slightly_smiling_face:

3 Likes

Hey @Jarrod,

Thanks for providing so much detail and your resolution for others to benefit from!

Sorry for the delayed response. To clarify a little, I believe the solution lies more in where the app was installed. For example, in order to have Confluence scopes apply, you will need to run forge install for Confluence on sites you wish to use the app in, even if your app is only displayed in Jira.

2 Likes

Hey @kchan

Anytime!

I actually tried that. I saw the app appear on the “Manage Apps” screen, but it didn’t appear on the left navigation section, with another one of my test apps? Strange right?
I also noticed that when the app was asking for my approval (when it was installed on Jira), it wasn’t mentioning all the scopes I had added, it only had the “user read me” one, even after running the “forge install --upgrade” command.

However, when I recreated the app from the cli, choosing Confluence initially, then manually copied over all my code, including the scopes - after deploying and the app asked for my permission, I now saw all the scopes that I had added.

I’m not sure if you’re able to check logs or anything on your side perhaps to confirm? But that was my experience.

Ah, if the scopes didn’t appear when you ran forge install, it sounds like you may not have run forge deploy before running forge install.

forge deploy uploads the manifest.yml to our backend which stores the required scopes information for installation.

Hey Kchan,

Yup, I definitely did that :slight_smile:

Anyway, it doesn’t seem to be bothering me anymore when I made the change in my solution. Thanks for taking the time to help me figure this out.

1 Like

I’ve run into this problem again and beginning to think it is a bug? Perhaps someone can confirm.

I’m trying to create a Macro, which has a MacroConfig, with a list of Jira Projects.

I’ve added the correct scope accordingly:

modules:
  macro:
    - key: daily-deployment
      function: main
      title: example
      description: example
      config:
        function: deployment-config
  function:
    - key: main
      handler: index.run
    - key: deployment-config
      handler: index.config
app:
  id: ari:cloud:ecosystem::app/xyz
  name: XYZ
permissions:
  scopes: 
  - 'read:jira-work'

I receive confirmation that the app was installed:


When the app asks me to Authorise, there is no indication that the app will allow reading Jira:

I created this app originally this morning and ran into this issue. Then assumed I had done something wrong, so uninstalled and deleted the app from the Developer Console, then proceeded to recreate it and still seem to be experiencing this issue.

I then see this in the logs:

INFO    2021-08-05T12:03:18.761Z 92444af9-25bb-4e47-a310-414cd2a18682 Calling: /rest/api/3/project/search?startAt=0&maxResults=50
ERROR   2021-08-05T12:03:18.800Z 92444af9-25bb-4e47-a310-414cd2a18682 {
  message: 'Authentication required',
  name: 'NEEDS_AUTHENTICATION_ERR',
  stack: ''
}

From my experience, it would seem like you can’t interact with one product within another, does anyone else have this issue and was able to overcome it?

Hi @Jarrod

I recently faced this type of issue in Confluence and got it resolved.

In my case, I noticed that if there is a typo in the URL or the URL generated is not done properly the API returns a 401 response even if the correct scopes are in the manifest.

For example, instead of this;

const res = await api
    .asUser()
    .requestConfluence(route`/rest/api/content?type=page&spaceKey=${spaceKey}&title=${pageTitle}`);

Try this;

const res = await api
    .asUser()
    .requestConfluence(route`/rest/api/content?type=page&spaceKey=replaceWithSpaceKey`);

And then is if it works. This will help you generate/pass in the accepted URL.

Hope this help.