RFCs are a way for Atlassian to share what we’re working on with our valued developer community.
It’s a document for building shared understanding of a topic. It expresses a technical solution, but can also communicate how it should be built or even document standards. The most important aspect of an RFC is that a written specification facilitates feedback and drives consensus. It is not a tool for approving or committing to ideas, but more so a collaborative practice to shape an idea and to find serious flaws early.
Please respect our community guidelines: keep it welcoming and safe by commenting on the idea not the people (especially the author); keep it tidy by keeping on topic; empower the community by keeping comments constructive. Thanks!
Summary of Project
Forge remote is a set capabilities that make it easier to securely integrate remote back ends with your Forge apps. So far, we’ve made it possible to call Atlassian APIs from your remote server when:
- a user interacts with the UI of your Forge app, or
- a product or lifecycle event you’ve subscribed to is triggered, or
- a scheduled trigger is invoked
This RFC goes into detail on Milestone 3 from RFC-8 and proposes a new mechanism for calling Atlassian APIs from remote back ends without any invocation coming from Forge.
- Publish: 5 Feb 2024
- Discuss: 23 Feb 2024
- Resolve: 1 Mar 2024
There are various use cases that require communication with Atlassian APIs from a remote back end without relying on a user interaction, product event or schedule. For example, you might need to trigger actions based on webhooks from other systems or utilise your own external UI.
Typically this might be solved for by providing long lived credentials that could be used to generate access tokens as needed (
refresh_token etc) or something like a per-installation shared secret like we have in Connect.
The downside of long lived credentials is the risk that comes with managing them (retrieving them, storing them, rotating them etc). These credentials are extremely sensitive and require robust security controls to manage and protect them.
With Forge, our goal is to abstract away as much security risk as possible. We want to take care of that as part of the platform.
Our proposal is to introduce a new module called
authTrigger that operates in a similar way to a web trigger. This module will offer a URL that can be invoked from your remote server, with the sole purpose of triggering the generation and delivery of a new Atlassian API token back to your remote server.
An example manifest would look like this:
- key: auth-trigger
- key: auth-trigger-endpoint
Each installation would have a unique auth trigger URL, which you can retrieve via GraphQL similarly to how getURL works for web triggers today. This request would be authenticated with a short-lived access token that you will receive through one of the existing Forge remote flows (e.g. an Install/Upgrade lifecycle event).
So the installation of an app might go something like:
- Customer installs your app
avi:forge:installed:applifecycle event is delivered to your remote server with an
- You use the
appSystemTokento call the auth trigger getURL GraphQL mutation and retrieve the auth trigger URL.
- You persist the installationId and authTriggerURL in your remote data store to use when you need it.
Then later, when you need to make an offline API request
- Make a request to the authTriggerURL for that installation (no auth required). A successful request will return a 200 response code and an empty response body.
- A new
appSystemTokenis delivered to the remote
endpointdefined in your manifest
Success! You now have the
appSystemToken which you can use as the bearer token to make API requests for the next 55 minutes.
In cases where installations go out of sync (despite our retry logic for events etc.) your app will be able to recover automatically. The next time it receives a short lived access token for that installation (e.g. the next time as user interacts with the app or a product event you’ve subscribed to is triggered) you will be able to make a getURL() request to recover the auth trigger URL and restore the offline access.
You will also be able add an additional layer of redundancy with remote support for scheduled triggers. Potentially you could set up a schedule to ensure all your installations are synced daily.
This is an important improvement over Connect where it can be difficult to recover if the shared secret for an installation is lost because you need to wait for a new install or upgrade event.
Forge doesn’t currently support asUser access for back-end processes and that will also be the case for the initial release of this functionality. It is something we’ll be exploring soon for Forge across the board, but we’ll save that for a future RFC .
Remember, you can make asUser() requests with the short lived tokens available when the user is invoking your UI modules.
We recognize that this differs from standard OAuth and is a trade-off against one of our other goals, which is to adhere to standards as much as possible. However, we believe that this strikes the best balance between security and ease of adoption.
We considered options such as providing a
client_secret in the developer console, or including
refresh_tokens with installation events. However, these options don’t meet our goals around trust and would also require some level of customization to work in the Forge/Atlassian context anyway.
While this proposal may require more effort to implement initially, it will ultimately reduce ongoing security risks for both you and our shared customers.
We are still early in the design/proof-of-concept phase and keen for your feedback.
We’re seeking input on:
- Whether this would work for your use case.
- Whether you see any major flaws in the proposal.
- Any specific implementation details you might like to see included in the final design.
- Any major difficulties you might see if you’re migrating from Connect and shared secrets.
- What you’d like to see from a developer tooling perspective.