Use Attachment Images in Custom UI

Hey there :wave:,

I’m currently experimenting with UI Kit as well as Custom UI. And while it was possible for me to include Images that are attached to a Confluence Page using UI Kit, I was unsuccessful when trying the same while using Custom UI.

I even tried to do a request on the /download/-url of the image using requestConfluence within an resolver, but sadly, this won’t work either and results in a 401.

Bundling the image into the forge app itself is not possible, as I want to show an image dependent on the content of a confluence page.

Are there any plans to allow attachment images/attachments in general in Custom UI?

Cheers,
Fabian :tea:

5 Likes

Hey @FabianSiegel :slight_smile:

I don’t believe we have any concrete plans for this, although it is good feedback that I will take to the team.

If you’ve done this kind of thing in connect in the past, how would you normally approach this?

Hey @danielwinterw,

thanks for answering that quickly :slight_smile:

When doing similar things with Connect in the past, it was usually just possible to insert an image by using an <img>-tag and use the link provided by the REST Api.

4 Likes

I am also using CustomUI and making use of the ‘@atlaskit/avatar’ component:

<Avatar appearance="circle" src="https://secure.gravatar.com/avatar/bd311dd52b9c5d3667b0b34f72959007?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FBJ-0.png" size="large" />

The image url is retrieved from the users.avatarUrls from the Atlassian rest API. The problem is the following:

Refused to load the image 'https://secure.gravatar.com/avatar/bd311dd52b9c5d3667b0b34f72959007?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FBJ-0.png' because it violates the following Content Security Policy directive: "img-src 'self' data: blob: https://avatar-management--avatars.us-west-2.prod.public.atl-paas.net".

I am using the standard Content security policy from the Atlassian CustomUI - Todo app - example:
<meta http-equiv="Content-Security-Policy" content="style-src 'self' 'unsafe-inline'" />

@danielwinterw any solutions in place at the moment?

1 Like

Hey @bjornbrynjar :slight_smile: I’ll pass this feedback on to the team as I don’t believe this is currently possible.

2 Likes

Hi @danielwinterw,
since the attachment download is blocking our Forge App development right now, I have to follow up here. We can create/edit attachments, read the attachment-metadata and upload new content, but we can’t download the content?
Cheers,
Andreas

Hi @spall, I’ll defer this one to @SamSmyth as he is leading the custom UI improvements.

Thanks for reaching out :slight_smile:

1 Like

Hi @spall,
Better support for attachments is something we are looking at but are unable to give an exact timeframe for yet. As a workaround if you are using Jira you should be able to use requestJira() (from @forge/bridge) in the custom UI frontend or asUser().requestJira() (from @forge/api) in the resolver backend to download attachments. For example requestJira(/secure/attachment/{id}/{filename}). Doesn’t look like there is an equivalent workaround for Confluence at this time though.
Hope that helps :slightly_smiling_face:

Hi @SamSmyth ,
your answer helps us already, we want to offer the app for jira as well and would use attachments there as well.

We found an undocumented rest call in the Confluence cloud UI and tried the following

api.asUser().requestConfluence("/rest/files/1.0/files/content/XXXXXXX/byAttachmentIds", {
method: ‘POST’,
body: JSON.stringify({“attachmentIds”:[“eeeeee”,“yyyyyy”,“vvvvvvv”]})
});
But the call did not work :upside_down_face:

We have found a workaround. Technically it’s a bit questionable, but it results in the fact that we can still read the content of the attachment after the upload. We create a comment with the content of the file after the upload and then read the first comment. We would prefer another solution, but have not found it yet.

Hi @SamSmyth,

Nice to meet you and cool to hear that you’re responsible for Custom UI improvements! That must be an exciting role! :smiley:

I feel with the recent answers, the focus of this thread has slightly shifted away from the original problem @FabianSiegel and I are experiencing. So let me reiterate on what our problem is exactly and ask a more general question.

We are doing a REST call to either one the following endpoints in Confluence:

https://your-domain.atlassian.net/wiki/rest/api/content/{id}/child/attachment
https://your-domain.atlassian.net/wiki/rest/api/content/{attachmentId}

The data we get back contains a _links object like this:

"_links": {
    "webui": "/spaces/X/pages/123/Page+Name?preview=image.png",
    "self": "https://your-domain.atlassian.net/wiki/rest/api/content/{attachmentId}",
    "download": "/download/attachments/{contentId}/image.png"
}

We want now want to display the _links.download URL in a <img> like this:

<img src="https://your-domain.atlassian.net/wiki/{_links.download}" />

As far as I can tell the only actual problem here seems to be that the CSP on the forge iframe prevents images to be loaded from <instance>.atlassian.net and api.media.atlassian.com. And as far as I understand this should be quite easy to fix by adding these domains to the img-src of the CSP.

Now, it might be really easy for you to fix this one specific issue regarding only attachments, and as they are hosted on your own domains this probably won’t really raise any major security concerns either. But as you see in the reply from @bjornbrynjar, this will not suffice. If you do not find a way to give app developers more control over the CSP this might very well become one of the biggest pain points with forge / Custom UI.

For now we had to stop working on some of our forge apps because of this. So my more general question: Is it likely that we will get more control over the CSP any time soon (say within 3 months), or should we ditch forge and stick with Connect?

Cheers,
Sven

6 Likes

Just to let you know @sven.schatter, the following code is now working perfectly:

<Avatar appearance="circle" src="https://secure.gravatar.com/avatar/bd311dd52b9c5d3667b0b34f72959007?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FBJ-0.png" size="large" />

Meaning *gravatar.com must have been added to the img-src part of the CSP on the atlassian side - for this to work…

2 Likes

Interesting! Thanks, @bjornbrynjar. We’ll have another look at this shortly ourselves. :slight_smile:

EDIT: Wait, you are using Avatar which leads me to believe you are talking about Forge UI Kit? In our case we need to do this in a img in a Custom UI iframe so behaviour might be different. Thanks for letting us know either way!

Cheers,
Sven

1 Like

I believe that’s a React component, Björn is using “CustomUI and making use of the ‘@atlaskit/avatar’ component”.

That has indeed happened in @forge/csp 0.1.1 (see package diff @forge/csp/0.1.0/0.1.1).

3 Likes

You are right @sopel, I am using CustomUI and making use of the ‘@atlaskit/avatar’ react component.

Thanks for the package diff link :wink:

2 Likes

Hey @sven.schatter,

Nice to meet you too :slightly_smiling_face:. We do have plans to give developers more control over the CSP in the next 3 months. Feel free to reach out if you have any more questions about custom UI.

6 Likes

Very curious to know what is coming in terms of opening up the CSP.

I’m working on a document review app using custom UI and I’d like to be able to display image
fragments from a remote document server. Is that something that’s ever going to be possible?

Are there alternate strategies to load dynamic resources like this to a custom UI - like indirectly through the forge app itself via a invoke or web trigger?

I see invoke is limited in the amount of data it can return so that doesn’t seem viable but perhaps we could prop a web trigger endpoint to do the load. Do we need to roll our own security in that case?

Thanks,
Jeff

Hi @jeffryan,

It will be possible to fetch images from a remote server as part of our upcoming CSP work.

Currently you are correct, the two ways to get dynamic resources into your Custom UI app are via invoke and web triggers. Web triggers currently have a lower payload limit than invoke due to a limitation:

4 Likes

Hey Sam,

It will be possible to fetch images from a remote server as part of our upcoming CSP work.

this is awesome news. Thank you :slight_smile:

Cheers,
Fabian :tea:

While creating a Custom UI app I have also encountered this problem.

I requested the user details from the REST API and sent the URL of the icon to the frontend. I have an avatar atlaskit component which takes the URL. So, here is where my problem started I couldn’t get the image to show at all. (Except when I converted it to base64)

So upon further investigation I found that if your avatar icon is not custom (Meaning you have the “letters” avatar icon) the URL gets blocked. As soon as I changed my avatar to be some random png it started loading it no problem.
The only difference in the URL that I have noticed is that when you don’t have a custom picture, the URL starts with “secure.gravatar.com” and redirects to the correct URL. But, when using any image it directly goes to the correct URL.

Hello @SamSmyth , I noticed a new Forge drop this week that includes content security and egress controls for custom UI. Great stuff!!! I’ve been trying out the new controls and had luck with most of them. However, I am still not able to get images loading from an external site. For example, I add this entry to my manifest.yml:

  external:
    images:
      - '*.w3schools.com'

but at runtime when I try to render an image from that site I get a CSP violation error. My browser console shows:

Refused to load the image 'https://www.w3schools.com/images/w3schools_green.jpg' because it violates the following Content Security Policy directive: "img-src 'self' data: blob: https://secure.gravatar.com https://avatar-management--avatars.us-west-2.prod.public.atl-paas.net https://api.atlassian.com".

I notice the CSP blob in the message does not include the site I configured in the manifest. I’ve also tried specifying the manifest images entry with a full URL to the image to no avail.

Any idea what I’m doing wrong?

Best Regards,
Jeff Ryan

1 Like