Our website is having problems loading CSS and JS resources on a Amazon S3 bucket with the very latest version of Chromium (Version 33.0.1722.0 - 237596) and Chrome Canary. It works well with any of the other browsers including the current Chrome (31.0.1650.57).
The error is:
Script from origin 'https://mybucket.s3.amazonaws.com' has been blocked from loading by Cross-Origin Resource Sharing policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://app.example.com' is therefore not allowed access.
Our S3 CORS configuration on the resource bucket is:
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<MaxAgeSeconds>300000</MaxAgeSeconds>
<AllowedHeader>Authorization</AllowedHeader>
</CORSRule>
</CORSConfiguration>
Is it a bug with Chromium? Did something change on the latest CORS spec?
Wanted to chime in with an alternate theory to this old question: Chrome has a bug/"feature" that's been present since at least Aug 2014 that causes a cross-origin request to fail if the resource was first loaded via a normal fetch, apparently because Chrome caches the CORS-less resource headers and then refuses to give the cached resource to the cross-origin request.
To make matters worse in our testing in a complex scenario, it isn't even necessarily fully consistent between refreshes (because order of resource loading?) and other browsers don't appear to share the behavior.
It was fun bug hunt! It seems that simply adding
crossorigin='anonymous'
to any tags loading the resource forces Chrome to pull the CORS headers in, fixing the subsequent cross-origin requests.Add any query parameter such as
?cacheblock=true
to the url, like so:Instead of: https://somebucket.s3.amazonaws.com/someresource.pdf
do: https://somebucket.s3.amazonaws.com/someresource.pdf?cacheblock=true
The technical explanation I don't have entirely down. But it is something like the following:
Including a query parameter will prevent the 'misbehaving' caching behavior in Chrome, causing Chrome to send out a fresh request for both the preflight request and the actual request, allowing the proper headers to be present on both requests, allowing S3 to respond properly. Approximately.
In all likelihood, you're running into a very well-known problem with S3/CloudFront/CORS. The best solution I've been able to find is to have an app that proxies between S3 and CloudFront, always adding the appropriate CORS headers to the objects as they come back.
S3 + CloudFront are broken when it comes to serving CORS assets to different web browsers. The issue is two-fold.
Vary: Origin
header, so it has issues with using*
for theAllowedOrigin
value, and will only cache the first of multipleAllowedOrigin
values.In the end, these two issues make S3 + CloudFront an untenable solution for using CORS with a (fast) CDN solution — at least, out of the box. The bulletproof solution is to create a simple app that proxies the requests between S3 and CloudFront, always adding the requisite CORS headers so that CloudFront always caches them.
Request against a “Cold” cache
Request against a “Warm” cache
Yes, this is a well-known, widespread issue:
I can say that our S3 and CloudFront teams are well-aware of the issues discussed here. By writing up a simple app that can act as a proxy between S3 and CloudFront, you can manually inject all of the correct CORS response headers before CloudFront caches them.
If you always work in Firefox, then you likely won't notice the issue — CloudFront will always be caching your CORS-enabled responses. If you work primarily in Safari or Chrome, you'll see it much more often when you switch back to a browser which requires these headers (Firefox and IE). Also, if you have separate development/staging/production environments, you're likely to run into the multi-origin issues more often.
Amazon released a fix for this a few months back. We were seeing the errors in current versions of Chrome & Safari (did not check Firefox). For anyone still running into this problem, try the following configuration:
S3 bucket CORS policy:
CloudFront distribution settings (Behavior tab):
We are hosting css and static javascript files via CloudFront with an S3 origin. We reference our javascript files via
<script crossorigin="anonymous" src="http://assets.domain.com/app.js">
.EDIT
We began seeing this issue again with Safari 10.1.2. It turns out that we were accessing the Javascript file in two ways...
On page A via
<script crossorigin="anonymous" src="http://assets.domain.com/app.js">
. On page B via$.ajax()
(so that it was lazy loaded).If you went to page A -> page B -> page A, we would get a cross origin denied error. We took out the lazy loading approach and it solved our issue (again).