A cautionary tale of working with AtlasKit editor, Media Client, the Atlassian Media API and how the only option to get it to work is not very GDPR-friendly

Over the past weeks, we’ve been trying to see if it was possible to use the Media Picker (https://atlaskit.atlassian.com/packages/media/media-picker) in combination with Editor core (https://atlaskit.atlassian.com/packages/editor/editor-core).

Although it must be stated that these components are marked “designed for internal Atlassian development”, the banner also mentions that “External contributors will be able to use this component”. That is not entirely accurate in terms of this combination of components.

The specific issue is with the Media Picker. Although this component is designed to be implementation agnostic, the only proper use case would be for Marketplace Partners to be able to use it in combination with the Atlassian Media API. That way, we can upload images / attachments to Atlassian instead of our own systems.

Unfortunately, the Media API has it’s own authentication flow and does not recognise / support Connect apps. Here is a brief explanation on how it works.

Keep in mind that this is all not documented properly, and is reverse engineered from source code and browser inspection

The Media Picker expects a Media Client (https://atlaskit.atlassian.com/packages/media/media-client) configuration, which includes the requirement of an AuthProvider that has the following properties

export interface ClientBasedAuth {
    readonly clientId: string;
    readonly token: string;
    readonly baseUrl: string;
}
export interface AsapBasedAuth {
    readonly asapIssuer: string;
    readonly token: string;
    readonly baseUrl: string;
}
export declare type Auth = ClientBasedAuth | AsapBasedAuth;

Coming from connect, one might think that ID refers to the clientId of the app, baseUrl the instance URL and token a JWT token that is created using the shared secret. Unfortunately, for the Atlassian Media API that is not the case.

In Confluence Cloud, this information is actually retrieved via a handshake from the host application to the Media API. The host application does a request to <BASE_URL>/cgraphql?q=MediaUploadTokenQuery with the session token in the cookies, and get’s a configuration and MediaPickerUserToken in response which hold the values that are required to create the AuthProvider (id, baseUrl and token).

Normally, one would expect that this is something we can recreate in a Confluence Connect app, for instance by using AP.request. However, please notice how the context /wiki is missing from the <BASE_URL>/cgraphql?q=MediaUploadTokenQuery call. Given that AP.request does not allow calls to the base URL without the /wiki context path in Confluence Cloud, we cannot recreate this step of the process. In addition, it is also not possible to call /cgraphql from the backend as our authentication methods are not accepted. As Confluence Cloud developers, we do not have access to /cgraphql.

Basically, this means that we cannot reverse engineer our way through using the Media Picker and Media Client in combination with the Atlassian Media API.

This is frustrating, because it means that A) we will need to create our own implementation of the Media API on the backend (without any proper documentation on that interface as it is outside the scope of AtlasKit) and B) it means that we need to handle customer data on our own systems, something that every Marketplace Partner and Atlassian really tries to avoid (GDPR, anyone?).

The most infuriating part of this, is that we are allowed to upload attachments using the Confluence Cloud REST API. This means that once we’ve received the uploaded file on our backend, we can then reroute it to the Confluence Cloud API and attach it to the page as if the Media API was used.

The lack of documentation, transparency and access to the Media API is unwarranted given that all operations are available to Marketplace Partners via the Confluence Cloud REST API. It adds an unnecessary burden to Marketplace Partners to create our own file upload implementation or even Media API backend if we want to use Media Picker / Media Client and provide customers with a seamless UX/UI experience.

It also adds an unnecessary GDPR hurdle given that Marketplace Partners will now become Data Processors for uploaded files even though we will immediately reroute that data to the Atlassian servers using the Confluence Cloud REST API. Given that Atlassian spent most of 2019 to go above and beyond to implement the most stringent GDPR measures, this loophole seems silly at best, and stupid at least.

I hope someone from Atlassian is monitoring this category and that it will trigger some sort of action that will allow Marketplace Partners to leverage the Media API in a way that provides additional value and security to our shared customers.

18 Likes

Hey Remie, thank you for doing all this research

Let me chime in here to say that this is really an important requirement for many of our not-yet Cloud apps given that native nesting is no longer possible in the new Confluence editor. So we would appreciate some sort of officially supported solution

2 Likes

awesome writeup Remie. I think this post pretty much described the frustrations of those affected including my team and me.

There’s a bunch of community posts seeking for more details on Media API in the past like these and I don’t think we got any support:


I also emailed the Media API team after stumbling upon a documentation page on using Media API - https://api-gev2.media.atlassian.com/api.html
(which has been taken down now) and was told that they no longer provide external consumers with the ability to use the API directly.

As for working around it, similar to yours - my team and I went with uploading files to page via AP.request to /rest/api/content/${contentId}/child/attachment directly.

5 Likes