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:
The Forge Remote project aims to make it easier for developers to securely integrate their Forge apps with remote backends. This post explains our approach to tackling the problem including some high-level technical details. We’re looking for feedback to make sure we build the best possible solution.
- Publish: 28 April 2023
- Discuss: 17 May 2023
- Resolve: 29 May 2023
Problem
Forge allows you to build fully within the Atlassian platform, but there are plenty of valid reasons why you might need to connect your Forge app to a remote system:
- You have hit the limits of Forge’s native capability (e.g. you process a lot of data)
- You’ve already built a back-end stack that works for you, and you’d like to leverage it with new apps that you build on Forge
- You need to connect with best-of-breed technology (e.g AI services)
- You need to integrate with another SaaS product or platform
With Forge today it’s possible to interact with remote systems but it can be difficult and inefficient. For example, you can set egress permissions to make remote Fetch API calls but there’s no easy way to authenticate those requests. Likewise, you can use Web Trigger functionality to invoke your Forge app remotely but you need to craft your own auth solution.
FRGE-1167 We are in the process of implementing authentication between our Forge App and our backend, and it is a pain in the …
This means wasted development time that could be better spent building valuable features.
Who are we solving for?
Forge Remote is the solution for Forge apps that need to integrate with remote services. It’s an option for developers willing to take on the additional complexity and security responsibilities of managing a remote service. For most use cases, we’d still encourage apps built on native Forge capabilities where possible.
Connect-on-Forge will remain the pathway for existing Connect apps to migrate to Forge. There are still a number of blockers we need to address before this becomes a viable option for many apps and these will be addressed as part of a separate initiative.
Proposed Solution
There are several different ways that a Forge app might need to communicate with a remote service, and we plan to address these in a series of milestones. Broadly speaking, we’ll be expanding the concept of remotes
which already exists in the Forge Manifest and applying that to support more use cases.
Milestone 1: Remote back ends for Forge front ends
In this milestone, we’ll make it easy to connect your Forge-hosted front ends (Custom UI or Client-side UI Kit) with your remote back ends. You will be able to specify remote endpoints in your app’s manifest and Forge will automatically route back-end requests.
These requests will include a signed token that enables the remote to securely verify the request came from Atlassian. You will be able to use any standard JWT library to do this (e.g. java-jwt or node-jsonwebtoken) with a public key which we will expose through a JWKS endpoint.
They will also include short-lived (60min) OAuth 2 bearer tokens so that the app can communicate back to product APIs.
A manifest for a macro with a remote backend might look something like this:
modules:
macro:
- key: confluence-remote-greeting
resource: main
resolver:
endpoint: remote-hello-world-ui ---> Instead of function
endpoint: ---> Instead of function
- key: remote-hello-world-ui
remote: remote-app
route:
path: echo/
auth:
tokens:
user: true ---> asUser() access token
app: true ---> asApp() access token
remotes:
- key: remote-app
baseUrl: https://remotehost.com/`
Requests routed to that remote endpoint might look something like this:
"access_tokens": {
"user", // Short lived oauth token (60mins)
"app"// Short lived oauth token (60mins)
},
"context_token": "...", // Signed token for verifying the requests
"api_base_url": "api.atlassian.com/ex/<cloudid>"
...
}
Milestone 2: Remote delivery of Atlassian webhooks/events
In this milestone, we will use the same mechanism to route Atlassian product events directly to a remote backend. These requests will also include a signed token to verify the request came from Atlassian and short-lived tokens to call back into the product APIs.
A manifest with a trigger that sends an issue-created event to a remote backend might look like this:
modules:
trigger:
key: test
events:
- avi:jira:created:issue
resolver:
endpoint: remote-hello-world-ui ---> Instead of function
endpoint: ---> Instead of function
- key: remote-hello-world-ui
remote: remote-app
route:
path: echo/
auth:
tokens
app: true ---> asApp() access token
remotes:
- key: remote-app
baseUrl: https://remotehost.com/
And the payload would look like the previous example.
Milestone 3: Remote access to product APIs at any time
In this milestone, apps will be able to call Atlassian product APIs from their remote back ends at any time. Apps will be given a mechanism to access APIs without a user interaction or product event needing to occur. This could be via credentials sent out with an installation hook (like Connect) or some other mechanism.
Where possible we would encourage the use of the short-lived credentials (from previous milestones) but we know certain use cases will require long-lived API access. For example, a timed batch job executing on the remote or some other external, non-Atlassian event-driven application interaction.
Milestone 4: Remote access to Forge Storage (and more?)
In this milestone, you will be able to access Forge storage remotely using the auth mechanisms introduced in the previous milestones. This means you’ll be able to integrate with remote compute but store data at rest in Forge.
If there is demand, we could also include other Forge capabilities like Forge Async Events.
Milestone 5: Improved remote access to Forge functions (Web triggers)
Web triggers enable remote invocations of hosted Forge functions but the current offering is very basic. You need to solve fundamental capabilities for yourselves (like auth). As part of this milestone, we will enhance the functionality of web triggers to add flexibility and provide an out-of-the-box auth solution.
Actions
While we would appreciate any reactions you have to this RFC (even if it’s simply giving it a supportive “Agree, no serious flaws”), we’re especially interested in learning more about:
- What do you think about the order of priorities? Are we building the most useful functionality first?
- Are there any use cases you don’t think we’ve covered?
- Would you have a preferred way to receive long-lived API credentials?
- Are there any Forge capabilities you’d like remote access to other than Storage?
- Any initial thoughts you might have on the finer details of running a remote backend e.g.
- Releasing new versions
- Traceability and observability
- Throttling and retry policies
It’s our goal to have an EAP for milestone 1 available by June 2023. I’ll update this post when we’re ready to start taking sign-ups.
Thanks for your feedback!