Developing for Atlassian Government Cloud?
This content is written with standard cloud development in mind. To learn about developing for Atlassian Government Cloud, go to our Atlassian Government Cloud developer portal.
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.
Forge facilitates many of the trust features that customers look for through a shared responsibility model, where security responsibilities are shared between you and Atlassian.
Forge routes requests to Atlassian products and Forge infrastructure such as Forge storage from your app to the correct tenant.
When processing tenant data inside the Forge app, it is your responsibility to isolate data between tenants. Consider not storing customer data beyond the scope of a single invocation, avoiding global variables or temporary files. See Security for Forge apps for more details.
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: