S3 not returning Access-Control-Allow-Origin headers?
Asked Answered
D

6

40

I am having trouble forcing S3 to set CORS headers on all of the objects it returns from a bucket, though CORS is enabled, as client-side S3 uploads is working, the returned objects do not have CORS headers!

The policy I have enabled is :

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
    <CORSRule>
        <AllowedOrigin>*</AllowedOrigin>
        <AllowedMethod>GET</AllowedMethod>
        <AllowedMethod>POST</AllowedMethod>
        <AllowedMethod>PUT</AllowedMethod>
        <AllowedHeader>*</AllowedHeader>
    </CORSRule>
</CORSConfiguration>

An example object URL https://s3.amazonaws.com/captionable/meme/test

Does anyone know what is wrong?

Dorso answered 10/7, 2013 at 11:59 Comment(0)
V
55

First of all, make sure an Origin header with every request. If no Origin header is sent, S3 won't send access-control headers, as S3 deems them irrelevant (and typically, they are). A browser (for which the CORS mechanism is meant) will automatically send an Origin header when doing cross-origin HTTP requests through XMLHTTPRequest.

In case of loading images with img, you need to add crossorigin="anonymous" attribute. See MDN Documentation on crossorigin attribute. This will cause the browser to send an Origin request header like it does with XMLHTTPRequest.

Going by the answer of Sam Selikoff, you may need to change

 <AllowedOrigin>http://*</AllowedOrigin>

to

 <AllowedOrigin>http://*</AllowedOrigin>
 <AllowedOrigin>https://*</AllowedOrigin>

I haven't tested this.

Going by Paul Draper's comment on this answer: Watch out for caching issues. A browser may use a cached response that did not include the appropriate Access-Control response headers. During development, you can clear your cache. In production, you must switch to a new URL for the resource, if it was used in a static manner before.

Valgus answered 10/7, 2013 at 12:12 Comment(9)
And therein lies the rub. I was creating an image tag, which does not send Origin headers. That said, I expected S3 to always return CORS headers, though it only does so when 'Origin' is specified. Thanks for the confirmation that CORS is properly configured.Dorso
In that case, it seems that I should be setting the crossOrigin attribute of an image tag. Do you by any chance know the supDorso
I don't have any experience with that attribute. Setting it to "anonymous" might just trigger the browser to send the Origin header. Maybe post separate question?Valgus
Also, the request needs to be a GET and not a HEAD. To test this with curl : curl -iH "Origin: test" http://…Hayne
This answer is mostly correct, but it is most certainly not irrelevant. If the response without CORS is cached, the next request will retrieve a CORS-less response and fail.Garlen
Adding <?xml version="1.0" encoding="UTF-8"?> <CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/"> <CORSRule> <AllowedOrigin>*</AllowedOrigin> <AllowedMethod>GET</AllowedMethod> <MaxAgeSeconds>3000</MaxAgeSeconds> <AllowedHeader>Authorization</AllowedHeader> </CORSRule> </CORSConfiguration> workes for me. But this only works if I open developer console and goto networks tab and check the 'disable cache'. Doesn't work without opening the developer console.Remit
You may need to add HEAD to the AllowedMethodsMcgean
is it possible to force S3 to send headers back in response even though ORIGIN is not present in request ?Inhalant
The CORS headers were not being returned by S3 until we followed this advice: "In case of loading images with img, you need to add crossorigin="anonymous" attribute." Once we did that, CORS was working in Chrome. Thanks @MyrneStolDoyledoyley
G
32

I also ran into this with an <image> tag, and after following Myrne Stol's answer I added the crossorigin=anonymous tag to my image tag. I verified that the Origin header was indeed being sent to S3, but still, the Access-Control-Allow-Origin header was not being sent in response.

I came across this SO answer and it solved it. I changed the AllowedOrigin in my S3 config to this:

<AllowedOrigin>http://*</AllowedOrigin>
<AllowedOrigin>https://*</AllowedOrigin>

and now S3 responds with the access headers. Yay!

Gowan answered 7/6, 2015 at 19:28 Comment(3)
@cory-dolphin I think this should be the accepted answer here. I too had the same problem with the image tag and adding these two lines fixed it.Sectarian
This isn't working for me (~2 years later). I've changed the configuration and I'm testing both in Postman & with a <video> tag. S3 doesn't respond with CORS headers in either case. Am I doing something wrong or has S3 changed?Hines
You also have to include an Origin header in any request - this threw me using curl (e.g. curl -X GET -v --header "Origin: https://www.example.com" https://s3-eu-west-1.amazonaws.com/my-bucket/asset.ext )Expunge
J
31

Chrome has this amazing bug which they won't fix:

enter image description here

If you're lucky enough to have control over the code that is generating the tag you can add crossorigin="anonymous" to the tag.
Like <img src="foo.bar/baz.jpg" crossorigin="anonymous" />
If you can modify either the URL for the tag or the URL for the XHR request, you could add a query parameter to one of them to bypass the cache.
Like foo.bar/baz.jpg?x-request=xhr.

Safari has this issue too btw.

Janel answered 20/3, 2019 at 15:59 Comment(2)
NGL I've been struggling to find an explanation for hours this should be upvoted more, as it was the real reason I had issues - I would have never thought that having an <img> (or in my case even background-image in css) would change the behavior of the JS code used afterward. You're a savior.Inquisitor
I think the real issue is that the server varies the response based on whether or not the origin header is included, but doesn't include "Vary: Origin" in the response. So caches are perfectly entitled to return the response without the CORS headers as the server has allowed it to be cached. I assume the server we're talking about here is S3 - I'm posting a bug report to ask them to fix their broken behaviour. The fetch spec has a clear description that S3 is violating: fetch.spec.whatwg.org/#cors-protocol-and-http-cachesTraherne
C
3

TLDR; Make sure that every image or video element that requests a resource which (somewhere) needs CORS uses crossorigin="anonymous"

I ran into this issue for a video element that was exporting to a canvas. The CORS was setup in S3 correctly, but it still gave me an error and refused to play the video.

It turned out there was a second video element pointing to the same resource, and that video element didn't have crossorigin="anonymous". Hence, the second video played fine since it wasn't expecting an access-control header, but the server response was cached and blocked the first video from playing because the cached server response didn't have an access-control header

Cellule answered 13/9, 2018 at 22:42 Comment(0)
R
0

I have faced an issue where I was not getting the CORS header from s3 issue is the origin sent from the chrome is with www like https://www.example.com while on s3 we have allowed only https://example.com So s3 wont send the CORS in case of Origin name mismatch

Just shared in case someone will face similar situation

Rozellarozelle answered 3/9, 2023 at 5:40 Comment(0)
D
0

I fixed this issue by adding Metadata: On the properties of the image go to the Metadata section and add the next feature:

Type - System defined Key - Cache-Control Value - no-cache In this case, the origin automatically appears in the header.

Doner answered 4/3 at 9:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.