How do I configure CORS in Amazon S3 and confirm the CORS rules using cURL?

Last updated: 2021-12-07

I want to allow cross-origin access to resources in my Amazon Simple Storage Service (Amazon S3) bucket, but I'm getting an error. How do I resolve this issue?

Short description

You can apply Cross-Origin Resource Sharing (CORS) rules to your bucket using either the Amazon S3 console or AWS Command Line Interface (AWS CLI). To test the CORS rules on your Amazon S3 bucket, use the cURL command.

Resolution

CORS is a feature of HTTP that uses headers to allow browsers to display content which a web server requested from a different origin. If you make a cross-origin request to an Amazon S3 bucket that isn't defined by a CORS rule, then the CORS header isn't returned.

For example:

curl -i http://mycorsbucket.s3.amazonaws.com/cors-test.html -H "Origin: example.com"

HTTP/1.1 200 OK
x-amz-id-2: Va106gWx1uUDGbouopXfpjvjHW0VXydI8/VGlraf/62f2vvxtI+iAnmu7lF4MK2B6CxuzReyfRI=
x-amz-request-id: QWNNX1Y0MWFM152H
Date: Thu, 04 Nov 2021 18:52:55 GMT
Last-Modified: Thu, 04 Nov 2021 16:03:50 GMT
ETag: "cd4276d2cd5a2dc8ebcc1e04746680f6"
Accept-Ranges: bytes
Content-Type: text/html
Server: AmazonS3
Content-Length: 55

If a web server made a similar request to a website, the content retrieved from your bucket won't appear in your browser. To allow your content to appear, configure a CORS policy on your Amazon S3 bucket. Proper configuration of the CORS policy makes sure that the appropriate headers are returned. You can configure a CORS rule on your bucket using the Amazon S3 console or AWS CLI.

Configuring a CORS rule using the Amazon S3 console

To configure a CORS rule on your bucket using the Amazon S3 console, perform the following steps:

1.    Sign in to the AWS Management Console.

2.    Open the Amazon S3 console.

3.    Select your bucket.

4.    Choose the Permissions tab.

5.    In the Cross-origin resource sharing pane, choose Edit.

6.    In the text box, enter the JSON CORS rule that you want to activate:

Example:

[
    {
        "AllowedHeaders": [
            "Authorization"
        ],
        "AllowedMethods": [
            "GET",
            "HEAD"
        ],
        "AllowedOrigins": [
            "example.com"
        ],
        "ExposeHeaders": [
            "Access-Control-Allow-Origin"
        ]
    }
]

For more information about each of the CORS rule elements or example rules, see CORS configuration.

7.    Choose Save.

Configuring a CORS rule using the AWS CLI

To configure a CORS rule on your bucket using the AWS CLI, run the following command:

aws s3api put-bucket-cors --bucket mycorsbucket --cors-configuration '{"CORSRules" : [{"AllowedHeaders":["Authorization"],"AllowedMethods":["GET","HEAD"],"AllowedOrigins":["example.com"],"ExposeHeaders":["Access-Control-Allow-Origin"]}]}'

Note: If you receive errors when running AWS CLI commands, make sure that you’re using the most recent version of the AWS CLI.

Testing the CORS rule

To test the CORS rule, use the cURL command, like this:

curl -i http://mycorsbucket.s3.amazonaws.com/index.html -H "Origin: example.com"

HTTP/1.1 200 OK
x-amz-id-2: d5Jsw1vCf8tR3cMdXrtcTKYgczU/1pjxahnrw7C6jU1fLo8py2Nv2kpeFs8pYPruVZg6Y3JuRUA=
x-amz-request-id: BMCCY18E58B3GBWV
Date: Thu, 04 Nov 2021 19:12:26 GMT
Access-Control-Allow-Origin: example.com
Access-Control-Allow-Methods: GET, HEAD
Access-Control-Expose-Headers: Access-Control-Allow-Origin
Access-Control-Allow-Credentials: true
Vary: Origin, Access-Control-Request-Headers, Access-Control-Request-Method
Last-Modified: Thu, 04 Nov 2021 16:03:50 GMT
ETag: "cd4276d2cd5a2dc8ebcc1e04746680f6"
Accept-Ranges: bytes
Content-Type: text/html
Server: AmazonS3
Content-Length: 55

If the CORS rule is correctly configured, you receive a 200 OK response.

Troubleshooting CORS methods

You can also use the cURL command to make requests using specific CORS methods by adding the -H "Access-Control-Request-Method: <Method>" flag. This flag specifies the CORS method to be tested. Use the --request OPTIONS flag to perform a preflight check of the request.

Note: Amazon S3 supports the GET, HEAD, PUT, POST, and DELETE methods.

curl -i http://mycorsbucket.s3.amazonaws.com/cors-test.html -H "Access-Control-Request-Method: POST" --request OPTIONS -H "Origin: example.com"
HTTP/1.1 403 Forbidden
x-amz-request-id: 190J4Q6222HA2KZ5
x-amz-id-2: 6oEci3qg88OeoLvBGwkN8K9AGdxyVela8ZKxftXMqyWrtZFfiKMrBwpTAeRiOth8amovJMtAAdA=
Content-Type: application/xml
Transfer-Encoding: chunked
Date: Fri, 19 Nov 2021 18:43:38 GMT
Server: AmazonS3

<?xml version="1.0" encoding="UTF-8"?>
<Error><Code>AccessForbidden</Code><Message>CORSResponse: This CORS request is not allowed. This is usually because the evalution of Origin, request method / Access-Control-Request-Method or Access-Control-Request-Headers are not whitelisted by the resource's CORS spec.</Message><Method>POST</Method><ResourceType>OBJECT</ResourceType><RequestId>190J4Q6222HA2KZ5</RequestId><HostId>6oEci3qg88OeoLvBGwkN8K9AGdxyVela8ZKxftXMqyWrtZFfiKMrBwpTAeRiOth8amovJMtAAdA=</HostId></Error>

If the request returns an error, then add the required method to the CORS rule on your bucket:

aws s3api put-bucket-cors --bucket mycorsbucket --cors-configuration '{"CORSRules" : [{"AllowedHeaders":["Authorization"],"AllowedMethods":["GET","HEAD","POST"],"AllowedOrigins":["example.com"],"ExposeHeaders":["Access-Control-Allow-Origin"]}]}'

Test the updated CORS rule. If your method works as expected, you receive the following response:

curl -i http://mycorsbucket.s3.amazonaws.com/index.html -H "Access-Control-Request-Method: POST" -X OPTIONS -H "Origin: example.com"
HTTP/1.1 200 OK
x-amz-id-2: Cx4kuM31KPVE19woEPRRYxF+85vEWkLk8+M0p6BIb72T550njMnmLtjqRgYzuxKelR0f+cxhFqI=
x-amz-request-id: QBSHV46QK43HGW15
Date: Fri, 19 Nov 2021 18:48:21 GMT
Access-Control-Allow-Origin: example.com
Access-Control-Allow-Methods: GET, HEAD, POST
Access-Control-Expose-Headers: Access-Control-Allow-Origin
Access-Control-Allow-Credentials: true
Vary: Origin, Access-Control-Request-Headers, Access-Control-Request-Method
Server: AmazonS3
Content-Length: 0