AWS S3 CORS 403 Error with OPTIONS request AWS S3 CORS 403 Error with OPTIONS request ajax ajax

AWS S3 CORS 403 Error with OPTIONS request


For those who came here for 403 on OPTIONS request of cross origin s3 access and didn't find what they were looking for, perhaps my experience with this can help.

tldr; browsers are designed to set the origin to null on 302 redirects from a different origin

I also experienced a CORS issue on the preflight request to a resource on a bucket, a resource which was otherwise available if browsed to directly.

I had CORS configured on the bucket with the proper accepted headers and origin. Something like the following.

<?xml version="1.0" encoding="UTF-8"?><CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/"><CORSRule>    <AllowedOrigin>http://localhost:8080</AllowedOrigin>    <AllowedMethod>GET</AllowedMethod>    <AllowedMethod>HEAD</AllowedMethod>    <MaxAgeSeconds>3000</MaxAgeSeconds>    <AllowedHeader>authorization</AllowedHeader></CORSRule></CORSConfiguration>

I then received an error along the lines of

Access to XMLHttpRequest at 'https://[REDACTED].s3.amazonaws.com/[REDACTED]?AWSAccessKeyId=[REDACTED]' (redirected from '[REDACTED]') from origin 'null' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

After inspecting the request headers, it was clear that the one suspect thing was the Origin having a value of "null".

Access-Control-Request-Headers: authorizationAccess-Control-Request-Method: GETOrigin: nullReferer: [REDACTED]User-Agent: [REDACTED]

As it turns out, browsers are designed to set the origin to null on 302 redirects from a different origin due to security issues. More info here.

There is no fix to this issue other than to not do a redirect. I had to redesign the backend resource that was doing a redirect to instead provide a link for direct access to the s3 bbject.


HTTP 403 (Frobidden) does not necessarily means that you need CORSs. One option is having all requests to cloudfront (same origin) and, in you distribution, several origins and behaviors. Ex:

Beavior   ->  Origin/api/*    ->  my.api.com/static/* ->  my.s3.bucket

But if you actually need cross-origin requests, The CORS headers should be forwarded by cloudfront and have the same behavior, in your example you probably want to be more permissive with the headers you allow (<AllowedHeader>*</AllowedHeader> ?). But that would be more related to the browser behavior than CLoudFront or S3.