amazon-s3corsamazon-cloudfront

CloudFront is not correctly passing back the Access-Control-Allow-Origin header from S3


I am accessing CloudFront from two different domains. I configured S3 to allow cross-origin from both domains. A page from mydomain1 would get the data properly, then a page from mydomain2 would send out the request correctly:

> origin: https://mydomain2

and CloudFront responded with:

< content-type: application/json
< content-length: 65
< date: Fri, 04 Dec 2020 22:45:50 GMT
< access-control-allow-origin: https://mydomain1
< access-control-allow-methods: GET, PUT
< access-control-allow-credentials: true
< accept-ranges: bytes
< server: AmazonS3
< x-cache: Hit from cloudfront

Of course, the browser blocked this request, as the allowed-origin didn’t match

I initially thought that I had the Origin Request Policy wrong, but no, I was using the Managed-CORS-S3Origin, which had the right name and I checked it and it said it was passing along the Origin header to S3 origin — the problem was not made any easier by the fact that “origin” in the Content Distribution business means something very different than what it means in HTTP business.

But clearly, the value of the Access-Control-Allow-Origin response header is being cached for some reason.


Solution

  • Because the people at AWS are trying to kill me, there are two different policies attached to CloudFront cache.

    One is the Origin Request Policy, and it governs what headers are passed on from CloudFront to S3. That was set automatically and correctly to pass on the Origin header.

    The other is the Cache Policy, which chooses which headers are used to form the cache-key, and in this case did not include the Origin.

    Which is just bonkers. The cache-key is how a CDN like CloudFront decides that two requests are alike enough that it can replay the response to the first request as the response to the second request too.

    OK, maybe there is some system somewhere that needs a header but doesn’t care about the value, so CloudFront should pass on the header with the first request and then cache the response to fulfill every subsequent request, regardless of the header.

    But most of the time, 99.9% of the time, the server requires the header because it is going to use the header’s value to create the response, and a different header-value would elicit a different response. Certainly, that is the case with S3 and the Origin header, since S3 copies the value of the Origin request header into the Access-Control-Allow-Origin header of the response.

    So, if you select the Managed-CORS-S3Origin Origin Request Policy, to manage CORS with an S3 origin, then CORS simply will not work until you write up a matching Cache Policy. And nobody tells you this. Auuuggghhh!

    Auuuggghhh