Understanding equivalent Connect to Forge OAuth2 Scope Mappings

For context, we have a JIRA app that was originally Connect-only.

Recently we successfully adopted Forge manifest for this app (Connect-on-Forge), and has been deployed to production in this state for a few months.

Our original Connect descriptor (atlassian-connect.json) had the following scopes:

"scopes": ["READ", "WRITE", "DELETE"]

(Note: the only thing the app writes or deletes is an issue entity property)

As part of the adoption of Forge manifest, our manifest.yml has the following equivalent scopes (and this avoided the need for a major version upgrade and admin approval):

permissions:
  scopes:
    - read:connect-jira
    - write:connect-jira
    - delete:connect-jira

We are now in the process of converting the connectModules to native Forge modules.

We have a jira:issueAction module that opens a UI Kit 2 modal to confirm deletion of an issue entity property. When the user confirms, the modal calls requestJira() to do the deletion:

const context = useProductContext();
const issueId = context?.extension.issue.id;
const url = `/rest/api/3/issue/${issueId}/properties/${entity-property-key}`;

const deleteHandler = async () => {
  const response = await requestJira(url, { method: "DELETE" });
  ...
}

Everything seemed to be going well until the requestJira() call, at which point our app threw up an “Access required” modal with the message:

Access required

For action-title to display, you need to grant it access to Atlassian apps on your behalf.

Cancel | Allow access

Apart from the slightly odd messaging (“For X to display…” even though the action is already displayed), we assumed this meant that the delete:connect-jira scope would need to be changed to an equivalent Forge scope.

Looking through the list, we found delete:issue.property:jira which sounded like exactly what we need, and would seem to be more granular that the sweeping delete:connect-jira scope we already had.

So we were surprised then when redeploying the app to our development environment that it was treated as a major version upgrade.

Apologies if this is a basic Forge question, but this is the first of our apps to go through the migration from Connect to Forge and we’re unclear what to expect here.

So two questions:

  1. Is it expected that requestJira() would ask me to “grant it access to Atlassian apps on your behalf”? (and does this mean in production every user has to explicitly grant access?)
  2. What would be the equivalent Forge scope that doesn’t require a major upgrade / admin approval? (Do we even need a scope if we’re using requestJira() to perform the delete directly from the UI via the REST API as the user?)

Thanks for any tips you can provide.

EDIT: After upgrading to the new major version (forge install –-upgrade), the Access Required prompt no longer appears. The questions regarding whether delete:issue.property:jira scope is necessary, and why it triggers a major version still stand.

I have yet to face this issue myself, but did you check to see if forge version bulk-upgrade is also able to perform the upgrade to the major version without requiring admin approval?

Thanks for the tip.

The new version is only deployed to our development environment currently, and will likely require more scope changes (read:issue.property:jira to replace read:connect-jira and write:issue.property:jira to replace write:connect-jira) as we replace the remaining connect modules, so if we get another major version when we redeploy we’ll check out forge version bulk-upgrade.

I’m not familiar yet with how bulk upgrade is intended to work, but I’m assuming we can test it in our development environment before promoting to a higher environment.

I think these scopes are only relevant to access app properties and not related to jira issues

    - read:connect-jira
    - write:connect-jira
    - delete:connect-jira

What you need to access jira is more like this:

    - read:jira-work
    - write:jira-work

There are 2 ways to implement permissions

  • granular scopes (you need to define exactly what you need to access)
  • classic scopes (simmilar to connect)

There are however some permissions in forge that are not included in classic scopes (e.g. JSM, software APIs and some more). In total you can’t have more than 50 scopes

This documentation is quite helpfull, if you have not seen it yet:

Just confirming that:

  1. Attempting to call requestJira(`/rest/api/3/issue/${issueId}/properties/${key}`) from a Custom UI component to read/write/delete entity properties does require new scopes to be defined (otherwise I get an error).
  2. Adding read:issue.property:jira and write:issue.property:jira scopes triggers a major version bump.

Presumably, as @m.herrmann mentions, the existing *:connect-jira scopes are considered to confer a different set of permissions. So adding these granular scopes is treated as “requesting more permissions”, even though in the corresponding connectModules I could use AP.request(`/rest/3/issue/${issueId}/properties/${key}`) to read/write/delete entity properties without any problems.

I haven’t yet checked what forge version bulk-upgrade does in this case…but either way it looks like I won’t be able to avoid a major version bump.

Would love for an Atlassian who knows anything about this to confirm.

In principle, my Forge modules aren’t doing anything that the Connect modules couldn’t already do, so its hard to see how this is considered “more permissions” that in turn forces a major version.

Hi @FeiyangYe,

I’m sorry to @-mention you directly like this, but as you previously were involved in some discussions on the seamless updates of Connect to Forge migrations I’m hoping you might either know the answer, or know who to ask.

The scenario is this:

  • A Connect app that used AP.request() to read/write/delete a Jira entity property

  • The Connect app had

    "scopes": ["READ", "WRITE", "DELETE"]
    
  • After adopting Forge manifest, these scopes became

    permissions:
      scopes:
        - read:connect-jira
        - write:connect-jira
        - delete:connect-jira
    
  • After publishing the Connect-on-Forge version, installs were seamlessly upgraded as expected, as there were no “net new” scopes requested

  • The Connect modules are now being replaced with native Forge equivalents

  • The Forge modules use requestJira() from @forge/bridge to read/write/delete the same entity property

  • This requires replacing the scopes with

    permissions:
      scopes:
        - read:issue.property:jira
        - write:issue.property:jira
        - delete:issue.property:jira
    
  • The granular scopes (to our knowledge) are more restrictive than the *:connect-jira scopes they replace

  • The scope changes result in a major version bump of our app when deployed

The question is:

  • How can we tell whether the new Forge-only major version will be seamlessly updated?
  • Will admin approval be needed even though there are actually fewer permissions in the new version?

Any help you can provide would be greatly appreciated, as we’re concerned that if admin approval is needed, we won’t be able to decommission our Connect infrastructure for some time yet.

Thanks in advance.

Hey @scottohara,

Apologies for the delayed response here - I’ve been travelling and have only just had an opportunity to respond.

When a Connect scope is defined in a Forge manifest, it can be utilised for any requests made from within a connectModule or when utilising a Connect JWT from the backend. When you move to utilising Forge modules (making requests via requestConfluence/Jira()) or utilising a Forge offline token, these require classic or granular scopes to be defined and will not inherit the permissions provided by Connect.

Understanding this, we have delivered the ability to move your app entirely from Connect to Forge without the admin having to press the Upgrade button, as long as you do not elevate your app’s permissions on this journey.

For scopes, the addition, removal or modification of a scope cannot be achieved atomically (ad a minor version) and will therefore be a major version. As long as it does not elevate permissions as per this mapping table, you will be able to utilise the forge version bulk-upgrade command to bring installations on prior versions to a later version.

Hope this helps.

Thanks @SeanBourke , that makes sense.

So it’s less about major vs minor versions, and more about whether permissions actually elevate or not (which is exactly how it should be, in my opinion).

We’ll proceed with our release on this basis, with forge version bulk-upgrade, and hopefully we see a corresponding drop in traffic to our Connect infrastructure to the point where we feel comfortable to start the decommissioning.

Appreciate the help.

Just wanted to update that this all worked as described.

We pushed our Forge-native version to production today (who said no releases on Fridays?), ran forge version bulk-upgrade, and we are now the proud owner of our first RoA app. :tada:

We now need to repeat the process for the rest of our apps (some of which we expect will be much harder to migrate).

Congratulations! And I’m happy to hear that the installation move worked exactly as we designed it to! The team put significant effort into making this work very reliably and as permissibly as possible.

My main question is: what documentation could we have improved that would have given you the trust you needed without needing to make this thread? I’m aware that there are many developers that are going to go on this journey in the next nine months and I’m keen to make everybody’s journey smoother than the last persons. Thanks in advance for any feedback!

In general, I think Forge versioning (and the lack of manual control over version numbers) is what we found most confusing.

Some of our developers have over 30 years of software development experience, and even coming from Connect and P2 development, are used to a development workflow of:

  • Make some changes (features, bug fixes, whatever) & test
  • Identify the semantic version number of the new release based on our assessment of what the changes/impact will be
  • Create a release (tag, version etc.)
  • Push that same version to a test/QA/staging environment
  • Push that same version to production

With Forge, I understand there is documentation that describes major vs minor versions and what constitutes each, but we ended up with a scenario where as we iterated in development (changing the forge manifest & redeploying many times), our version number kept radically increasing.

For the app we just released, our version number in dev now sits at 6.2.0 (the previous Connect-on-Forge version was 2.1.0).

When we deploy the same version to staging, after a few iterations it now sits at 5.1.0.

And the production release yesterday ended up being 3.0.0.

It is quite strange to have effectively the same build in three environments all having different version numbers. I’m sure this has been discussed to death in the past and there are likely valid reasons for it; all I’m saying is that this is wildly different to our experience building & deploying software over the course of our careers.

Compounding this is was the assumption that “major version bump” == “requires admin approval”. As Sean clarified above, the key trigger for admin approvals is less about major vs minor versions and more to do with “are there any elevated permissions that an admin would need to consent to”. We found this to be somewhat confusing.

There seems to be a disconnect between when major version is incremented (which is generally when something significant changes in the manifest, e.g. new modules, new scopes, new remotes etc.), and when admin approval is actually going to be required.

Finally, we had not previously used forge version bulk-upgrade before this, so we weren’t quite sure what to expect. The first thing that caught us out was that the man page / help for this command doesn’t mention that --environment is needed (it is, however, listed in forge version bulk-upgrade start –-help).

So we started by simply running forge version bulk-upgrade start and we saw all of our dev versions listed. Realising this, we added the --environment production flag.

From the list of versions, we picked our latest version (thinking “upgrade to this version”), but this gave “no upgrade paths available”, and we realised it was actually asking “what version to upgrade from”. So maybe some better guidance in this tool would be useful.

As has been mentioned in another thread, some better guidance on when it is safe to tear down our Connect infrastructure would also go a long way. As of now, we still see Marketplacebot pinging our /atlassian-connect.json descriptor file, even though we adopted Forge Manifest some months ago. It is unclear what impact there will be when we shutdown our old infra and these Ecoscanner and Marketplacebot requests start 404-ing.

I hope that is useful.


❯ forge version bulk-upgrade --help                    
Usage: forge version bulk-upgrade [options] [command]

upgrades installations from one major version to another version.

Options:
  --verbose         enable verbose mode
  -h, --help        display help for command

Commands:
  cancel [options]  cancels a version upgrade that is in progress.
  help [command]    display help for command
  list [options]    returns a summary of version update requests. Details include:
   - upgrade ID
   - upgrade request status
   - start date
   - completed date
   - from version
   - to version
   - number of updates completed
   - number of updates pending
   - number of updates failed
  start [options]   upgrades installations using one major version to another version. The version selection list displays:
   - major version number
   - deployment date
   - number of installations

While this does not help with the user-visible version numbers, check out the forge build command and the ability to use forge deploy to specify a previously-built tag. If nothing else, this can allow you to deploy exactly the same code to different environments. (The part about it not working with manifests containing environment variables is a bit of a problem though, since I am guessing that many Forge devs do declare such variables.)

Reasons why I personally think it’s madness to migrate to Forge at this point in time:

  1. Rolling releases (RFC-106) hasn’t gone GA yet. Sounds like a new optional addon feature but it’s the basic foundation for versioning and permission handling which was severely overlooked. Without it you end up with the majority of installs stuck on outdated versions.
  2. As you said, they’re still lacking basic e2e migration guides and post-migration cleanup. To be this far into the “migrate now or face consequences!” rhetoric you’d expect the process to be so seamless as to not require the many CDAC threads like this one.
  3. The AI models are advancing exponentially. Anyone still writing code by hand is living under a rock. Within 6 months I expect every Connect app can be migrated perfectly in one-shot. Bizarre deadline timing choice to waste ungodly sums of developer time and resources whilst we’re so close to LLMs perfecting the grunt work of software development.

/2c