As you think about building apps for Atlassian cloud products, you'll need to handle data in a multitenant environment.
Atlassian apps in the cloud are different from the server environment, where each instance of an app is installed on just one tenant. As an app developer, you only need to worry about the data you’re given on that instance.
In the cloud, your app is hosted and accessed through multiple Atlassian cloud instances that have installed your app. You need to securely handle and save the data for each tenant.
Multitenancy is handled differently in Forge and Connect. This page outlines what you’ll need to consider for both.
If you're a Marketplace Partner, visit our cloud-readiness hub for guides on moving your apps and business to cloud. Check how to get access.
The Forge platform enables secure data management through its architecture and the way it handles data. This includes data isolation to prevent leaks as well as data handling policies for the Forge environments.
The Forge platform sandboxes apps, as described in the App runtime section. Since apps are sandboxed, app calls occur in separate instances of the app. This means that data is isolated at the runtime level, preventing data from leaking.
Forge builds security directly into the platform to prevent data leaking to other tenants so that you don’t have to worry about it while developing your app.
Before you write one line of code, it’s good to consider how to manage data in your app with multiple tenants. Here are some things to consider when architecting your app:
When a customer installs your app in the Atlassian product, the product reads the app descriptor and sends the tenant client information to the installed lifecycle webhook you’ve specified.
1 2// app-descriptor.json { ... "lifecycle": { "installed": "/installed" } ... }
Your app should have an endpoint at /installed
and expect data to be POSTed to
it. Here’s is an example of the data object that will be sent:
1 2{ "key": "installed-addon-key", "clientKey": "unique-client-identifier", "sharedSecret": "a-secret-key-not-to-be-lost", "serverVersion": "server-version", "pluginsVersion": "version-of-connect", "baseUrl": "https://example.atlassian.net", "displayUrl": "https://docs.example.com", "productType": "jira", "description": "Atlassian Jira at https://example.atlassian.net", "serviceEntitlementNumber": "SEN-number", "eventType": "installed" }
When you receive this data, save it to your persistent data store and index against
the clientKey
as the unique identifier.
Because every communication from the Atlassian product contains the clientKey
in the JSON Web Token (JWT), you can use the clientkey
to verify that the request
is coming from the expected tenant. You use the clientKey
and sharedSecret
to
create a JWT
to validate data to and from the Atlassian product.
If your app needs to store any other data, you now have the tools to securely bind that data to the appropriate tenant:
clientKey
in each JWT.clientKey
.clientKey
to verify that the data in your datastore belongs to
the tenant requesting access.clientKey
as a foreign key.Rate this page: