Use Attachment Images in Custom UI

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

Well, I’m not sure if someone waved a magic wand or what but I closed and reopened the issue editor and now the remote image is loading just great! I guess I had just been refreshing the page previously as that is typically all I need to do. Anyway, scratch that last question.

Thanks again for all the great work on the CSP extensions.

Best Regards,
Jeff Ryan

3 Likes

Hey @SamSmyth. I am using the confluence APIs to save attachments in confluence page using forge custom UI app.
I want to display those attachments in my IMG or audio HTML tag.
After fetching the URL using the confluence APIs and putting all the permission in manifest, the audio is still blocked by CSP.

Content Security Policy: The page’s settings blocked the loading of a resource at “https://your-domain.atlassian.net/wiki/download/attachments/557079/Insane.mp3?version=2&modificationDate=1632897649047&cacheVersion=1&api=v2 (“media-src”).”

Manifest.yml permission -

I have also included the permission for it, still I’m not able to figure out why it’s blocking the resource. If you know about this error, please help.

Hey @YashShivhare,

Can you confirm that the domain listed in the error message matches the entry in the media: manifest property? If this is the case can you share with me a bit more detail about the error message (e.g. the exact message you are seeing), feel free to share this with me over a private message :slightly_smiling_face:.

Hey @SamSmyth, thanks for the reply…

I was able to solve the previous problem, but now when I’m trying to record voice using mic and creating a URL using window.URL.createObjectURL of blob for playing the recorded audio, but I’m not able to play that It display error like this -

Content Security Policy: The page’s settings blocked the loading of a resource at blob:https://8700c44c-6c5a-4527-9234-c7c035f9ddfa.cdn.prod.atlassian-dev.net/4ad70f49-cbf0-4c4b-be60-ac5581eed19d.

This is the iframe URL of my app -

React App

What do you suggest I include in my manifest to allow it to play?
Since it’s not a straight forward URL, it’s a blob URL. I’m a little confused and since it’s playing the audio, should I include it in my media permission inside manifest.yml.

Hey @YashShivhare,

Sadly we don’t currently support blob in our Content Security Policy. Would love if you could raise a ticket on our public feedback board to help us track and prioritise shipping this feature.