Search code examples
javascriptajaxamazon-web-servicesamazon-s3amazon-cloudfront

Loading file from CloudFront using AJAX causes 403 (Forbidden) error


I have an SVG file sitting in Amazon S3 and a Cloud Front distribution which points to my bucket as the origin.

I have enabled CORS on the bucket like below :

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

I also white listed below headers in the options of the behaviors of my cloud front distribution.

Access-Control-Request-Headers
Access-Control-Request-Method
Origin

In a single standalone HTML file, I can easily load the SVG like:

$(document).ready(function () {
            var settings = {
                "crossDomain": true,
                "url": "https://mycloudfront.cloudfront.net/images/one-TEST_1140924280.svg",
                "method": "GET"
            };

            $.ajax(settings).done(function (response) {
                var svg = document.importNode(response.documentElement,true);
                $("#svg").append(svg);
            });
        });

When I do this in standalone HTML, the origin of the request header is null. But when I try to do this in my project (Spring Boot 1.5.3) The origin of the request header is http://localhost:8080 and I get 403 response as a result :

XMLHttpRequest cannot load https://mycloudfront.cloudfront.net/images/one-TEST_1140924280.svg. Response to the preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8080' is therefore not allowed access. The response had HTTP status code 403.

Also, there is a header being added to the AJAX request access-control-request-headers:x-csrf-token

The exact same thing happens in my test environment on EC2. I thought localhost:8080 in origin is somehow the problem.

Am I missing a configuration somewhere in CloudFront or S3?


Solution

  • According to this :

    For a preflight request, if the request includes an Access-Control-Request-Headers header, verify that the CORSRule includes the AllowedHeader entries for each value in the Access-Control-Request-Headers header.

    I chose GET, HEAD, OPTIONS of Allowed HTTP Methods of the Cloud Front behavior and added below configuration to my S3 CORS configuration and it worked fine.

    <AllowedHeader>x-csrf-token</AllowedHeader>
    

    In my situation that x-csrf-token was being added to the headers cause the page in my project was in a protected area by spring security, It worked but just be aware that any other custom headers being added to the request, Cloud Front will return 403. So easier option would be allowing all headers in your CORS configuration.

    <AllowedHeader>*</AllowedHeader>