AWS S3 + CloudFront gives CORS errors when serving images from browser cache

15,239

Solution 1

I was stuck in the same problem and found that exposing headers as shown below solve the problem:

<CORSConfiguration>
  <CORSRule>
    <AllowedOrigin>MYIP</AllowedOrigin>
    <AllowedMethod>PUT</AllowedMethod>
    <AllowedMethod>POST</AllowedMethod>
    <AllowedMethod>DELETE</AllowedMethod>
    <AllowedMethod>PUT</AllowedMethod>
    <ExposeHeader>ETag</ExposeHeader>
    <AllowedHeader>*</AllowedHeader>
  </CORSRule>
</CORSConfiguration>

Solution 2

I found myself with the same sort of problem: no Access-Control-Allow-Origin coming up. It was very random, sometimes it worked, other times it did not. I finally narrowed it down in this way:

  1. Turned on S3 website hosting
  2. Tested for CORS header in both S3 and CloudFront

Here is how to easily test for a CORS header:

curl -i -H "Origin: http://YOUR-SITE-URL" http://S3-or-CLOUDFRONT-URL | grep Access

In my case it would work fine in S3, but in CloudFront it will only sometimes return back the access-control headers:

Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET
Access-Control-Max-Age: 3000

After more research, I discovered that our CloudFront distribution was configured to block the headers from going to S3. To fix this:

  1. Go to CloudFront distribution in the AWS dashboard
  2. Click on Distribution Settings
  3. Click on the Behaviors Tab
  4. Edit the default pattern Behavior
  5. Click on Forward Headers and select Whitelist
  6. Add the 3 suggested headers: Access-Control-Request-Headers, Access-Control-Request-Method, Origin
  7. Save changes

Once the headers made it to S3, we could always see the correct access control information with curl command above.

Share:
15,239
Chris Scott
Author by

Chris Scott

Updated on June 06, 2022

Comments

  • Chris Scott
    Chris Scott almost 2 years

    If I clear my browser cache, everything loads just find from my cloudfront-enabled S3 bucket. When I turn off cache, however, I get errors in the console:

    Image from origin [ORIGIN URL] has been blocked from loading by Cross-Origin Resource Sharing policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin [MY LOCALHOST ADDRESS] is therefore not allowed access.

    MY CORS configuration:

    <?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>*</AllowedHeader>
        </CORSRule>
    </CORSConfiguration>
    

    I also followed this advice a while back and changed the cloundfront distro settings. It seemed to have worked back then but is definitely not working with browser cache now: CORS problems with Amazon S3 on the latest Chomium and Google Canary

    I also tried putting "Header add Access-Control-Allow-Origin "*"" in my websites .htaccess. No luck. Note: my website is hosted and accessed from localhost (it's a dev environment).

  • Anurag Pratap
    Anurag Pratap over 8 years
    MYIP format: for my local development machine I used : localhost:3000 as it specifies origin from where request is triggering.
  • Chris Scott
    Chris Scott over 8 years
    Oddly the problem spontaneously stopped happening (before I implemented this solution). But I will try this if it starts acting up again.
  • Chris Scott
    Chris Scott over 8 years
    I had the problem again, implementing your solution and it seems to have worked. I marked your answer as correct. Thank you!
  • Chris Scott
    Chris Scott over 8 years
    Spoke to soon. I am getting the errors again. Are there other tags I should include, other than, ExposeHeader?
  • Anurag Pratap
    Anurag Pratap over 8 years
    I don't think any other tag is required.Please ensure following things: * Format of origin is not correct. * You specify CORS for each bucket you are using.
  • Chris Scott
    Chris Scott over 8 years
    Can you elaborate on what you mean by "Format of origin is not correct"?
  • Eduardo Almeida
    Eduardo Almeida over 6 years
    Probably this is the most complete answer regarding this topic on Stackoverflow, but it's still not working for me. It seems that Cloudfront only Forward Headers from my Subdomains (eg.: www.myapp.com), but it doesn't to my domain (myapp.com) - if anyone knows why have a look here: stackoverflow.com/questions/45528115/…
  • Matt Dodge
    Matt Dodge about 6 years
    I had to add Access-Control-Allow-Origin and Access-Control-Allow-Methods to the headers but this approach worked. Basically, you need to include the headers that you are sending in your pre-flight requests to be passed through the cloudfront distribution. Great answer, thank you!
  • Matt Dodge
    Matt Dodge about 6 years
    Also FYI, the section isn't called "Forward Headers" anymore, it's now "Cache Based on Selected Request Headers" then select "Whitelist"
  • BrunoLM
    BrunoLM almost 5 years
    This doesn't always work for me, I have been having this issue for weeks now, sometimes the images don't load and I see a CORS error on the console. It's not easy to reproduce this bug.
  • Todd
    Todd about 4 years
    Thanks for the ETag header exposure that did the trick for me. I saw it in the documentation somewhere but was unable to locate it again. I would like to point out in your example code you have the "<AllowedMethod>PUT</AllowedMethod>" twice. Maybe one should be "<AllowedMethod>GET</AllowedMethod>"?