Authenticated Access to S3

tl;dr

Trello will begin requiring API key and token authorization to access card attachment download URLs.

Timeline

As of right now, you can construct the future-proof /download/ URLs and pass in authorization. We HIGHLY recommend updating to use this access pattern now as no changes will be required when authorization is required. More on this in Opt In To Try New Routes below.

We are working to determine the date at which we will limit all authorization validity to 1 hour permanently.

Details

Currently, when you make a request to GET a file attachment on a card, you will receive back a payload that includes the URL at which the file is hosted.

For instance, with the following request:

curl https://api.trello.com/1/cards/{idCard}/attachments/?fields=url&key={{apiKey}}&token={{apiToken}}

You’d get back a HTTP 200 response with the following body:

[{
  "id": "5ef22a288dcee602857a9990",
  "url": "https://trello-attachments.s3.amazonaws.com/5b6893f01cb3228998cf629e/5b6b3ed249cf2381d501427c/c017c7020704c12468c868be104e4ed4/me.png"
}]

The URL provided in url is publicly available and requires no authorization of any sort to access.


Moving forward, public access to these files will be turned off. And the value returned for the url will no longer be the location where the file is hosted. Instead it will be a URL that includes /download/ in the path, similar to below:

[{
  "id": "5ef22a288dcee602857a9990",
  "url": "https://api.trello.com/1/cards/5edfa37673e537161016361c/attachments/5ef22a288dcee602857a9990/download/Screen_Shot_2020-06-23_at_11.13.18_AM.png?signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYmYiOjE1OTM0NTcyMDAsImV4cCI6MTU5MzQ2MjYwMCwicmVzIjoiNWVkZmEzNzY3M2U1MzcxNjEwMTYzNjFjOjVlZjIyYTI4OGRjZWU2MDI4NTdhOTk5MCIsImlhdCI6MTU5MzQ1OTkwNSwiYXVkIjoiVHJlbGxvIiwiaXNzIjoiVHJlbGxvIn0.8YcOCOFZ4rURYWoiYYEhAEeyQJyMcnSBRo83UviTA_k"
}]

The /download/ URL format is the following:

https://api.trello.com/1/cards/{idCard}/attachments/{idAttachment}/download/{attachmentFileName}

The url value returned from the API includes a signature parameter which is valid for 1 hour with the /download/ URL. If you were to make a GET request to the URL without the signature (or after it has expired) you would receive a 401.

Moving forward, there are two options for accessing the file for extended amounts of time.

If you are using the files directly in your application as a single user, you can add in an API key and token to the request to the /download/ URL.

Making a GET request with the key and token will return a 302 that redirects to the URL of the hosted file. You will always be 302’ed so long as the tokened user has access to the attachment. The route you are redirected to is only valid for 1 hour.

If your application exposes the URL to users other than the one who has granted your application access, you should not use this method.


If your application needs to give broader access to the file (like showing the file to multiple users), you do not want to leak the key and token, and so you should use the following method of making a preflight HEAD request.

Making a HEAD request to the /download/ URL with a valid key and token results in a 302 HTTP response with a Location: header that is the URL of the file.

For instance, here is the HEAD request:

curl --head https://api.trello.com/1/cards/{idCard}/attachments/{idAttachment}/download/Screen_Shot_2020-06-23_at_11.13.18_AM.png\?signature\={signatureFromAbove}\&token={token}\&key={key}

And our response with the Location: header:

HTTP/1.1 302 Found
[...]
Location: https://trello-attachments.s3.amazonaws.com/5edfa37573e53716101635c9/5edfa37673e537161016361c/1fe80390ba5fe13ef04f612c51647f7c/Screen_Shot_2020-06-23_at_11.13.18_AM.png
[...]

The URL in the Location header is accessible for 1 hour. Your application can safely share that URL for the duration of its validity.

Opt In To Try New Routes

You can currently construct the /download/ routes and pass in authorization. We HIGHLY recommend updating to use this access pattern now as no changes will be required when authorization is required.

When constructing the new routes, remember that the name property is user modifiable and may change. For use as a file path either use the new fileName property, or parse the file name out of the url.

3 Likes

Hi, we plan to use these new links in our app.
But, I think that something is missing in that new method.
Is it possible to get a “permament_url”, something that we can give to someone, (or export in json or csv…) that will not be the temporary s3 url, or will not contains a private key-token?

I mean, can I give a url to someone, like
https://api.trello.com/1/cards/{idCard}/attachments/{idAttachment}/download/
without any secret key, or temporary url

And let the trello app authentify the user if it is not, and start the download.
Exactly like what happen when I send a link to a todo to someone?
The trello ui does the job to authentify the user, and let him access the todo if the user is authorized to.

Yes - we would expect you to do this.

Hi everyone,

It looks like the first method

“you can add in an API key and token to the request to the /download/ URL”

will finally not be supported? (that is a good thing!)
I just tried, it, and got that response:

auth in query params for attachments is not allowed

Do you have plans to remove or change the “url” attributes in the previews array of attachments?

Attachments and their previews will work the same way. They have a /card/:id/attachments/:id/previews/:id/download url too.

When an enterprise is opted into the authed attachments feature, the url field will change to the new format.

Hi,

When I do an API call to get the attachment. I’m getting the result like one below. As mentioned in the above threads, I’m not getting any signature. What could be the reason?

{“id”:“60f68843759ce010381e77c9”,“url”:“https://trello.com/1/cards/60f686b7f20a5d686f0e05c7/attachments/60f68843759ce010381e77c9/download/logo2.png”}

Hi there,

It’s actually expected that you do not get a signature in a auth’d attachment URL. Please refer to our second announcement regarding this new change here.

1 Like

O código realmente não funciona. O retorno: “unauthorized permission requested”