Scope does not match when creating Confluence content via REST API

Hi there,

I am trying to create a blog post via the Confluence Cloud REST API, but apperently do not find the correct permission scope for that.

My manifest contains the following scopes:

permissions:
  scopes:
    - storage:app
    - read:configuration:confluence
    - read:content-details:confluence
    - read:user:confluence
    - read:group:confluence
    - write:content:confluence
    - write:page:confluence

So according to the documentation the correct scopes “write:page:confluence” and “read:content-details:confluence” are present.

My request looks like:

const bodyData = {
      title: "My New News",
      type: "content",
      status: "current",
      space: {
        key: "WORKSPACE"
      }
    };

    const resp = await requestConfluence("/wiki/rest/api/content/", {
      method: 'POST',
      headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json'
      },
      body: JSON.stringify(bodyData)
    });

Unfortunately I am always getting the error message: “Unauthorized, scope does not match” code: 401

Thanks in advance
Sven

Hi @SvenHe ,

You are right, that the scopes are correct for the request.

Are you sure that the app was installed for Confluence and not for Jira?
If that’s the case, can you share the invocation id for that request for us to check?

Caterina

Hi @ccurti ,

thanks for your reply.

The app is installed for Confluence. What do you mean by invocation id? Where can I find it?

Kind regards
Sven

Hi @SvenHe,

I see now that the request is done using the requestConfluence bridge from a customUI.
In that case, the easiest way to check the scopes of the request is to do the following:

  • from the https://api.atlassian.com/ex/confluence//wiki/rest/api/content request in the browser developer tools, get the authorization token from the request headers
  • decode it (for example you could be using a tool like https://jwt.io, note the security warnings there though) and check for the scope attribute

Do you see the required read:content-details:confluence and write:content:confluence scope?

If not, we should try to re-deploy and re-install the app (a forge install --upgrade will be required if the scope has been added afterwards).

Another option, which will not tell us what happened but might resolve the problem, could be to create a brand new app with the same code by using the forge register command. This will generate a new app with a new id and the app will need to be reinstalled on the sites.

I also did some checks to see if there could have been something else happening (e.g. the user didn’t have the permission to create blogs) but the only time when the request returned a 401 was when the scopes were missing.

Regarding the invocation id, that is what is shown in the forge tunnel when a request is performed. With that information, we have a way to check the scopes attached to a request. However, this doesn’t apply to customUI.
For example, in my console I get the following based on the example below and the d3225a64c43416e1 is the invocation id:
invocation: d3225a64c43416e1 index.run

Hope this helps,
Caterina

1 Like

Hi Caterina,

to provide an invocation id, I moved the code to my Forge backend and replaced the request with the one from @forge/api.

The invocation id which appeared in my tunnel is now:

invocation: ba9609c0922e4d91 index.handler

I have also checked the encoded authorization token, as you have advised. Both scopes are included.

"scope": "read:me read:content-details:confluence write:content:confluence read:configuration:confluence write:page:confluence read:group:confluence read:user:confluence offline_access"

Looking forward to hear from you again.

Thanks so far,
Sven

:wave: @SvenHe,

I had a quick look at the logs and still couldn’t find an explanation for this (I’ll dig more next week).
In the meantime, I have 2 more questions for you:

  • In the payload in the original request, I see type: "content". This should be type: "blogpost", right?
  • Can you also confirm that the ba9609c0922e4d91 invocation returned the same 401 - Unauthorized, scope does not match? And was that using the asApp or the asUser request?

And one more:

  • Do you know if this happens on every site? Maybe you tried a few and could reproduce it consistently on all of them.

Caterina