Last updated: Jan 27, 2024
Reading time·5 min
CORS is a mechanism that allows a server to use a combination of HTTP headers to indicate from which domains, other than its own, it receives requests.
Setting CORS configuration is important when we access resources from a different domain.
All S3 buckets are hosted on the https://amazonaws.com
domain, which is
different from where we host our client applications, so we have to set up
CORS.
We often have to set up CORS when working with S3 buckets, an example being when our backend generates an S3 presigned URL, which our frontend then uses to upload a file to S3.
Since our frontend is hosted on a different domain than the S3 bucket, we have to set up CORS.
In order to set CORS on an S3 bucket we have to pass the cors
prop to the
Bucket construct.
To demo setting up CORS, let's create a CDK app that consists of a single S3 bucket.
import * as s3 from 'aws-cdk-lib/aws-s3'; import * as cdk from 'aws-cdk-lib'; export class MyCdkStack extends cdk.Stack { constructor(scope: cdk.App, id: string, props: cdk.StackProps) { super(scope, id, props); const s3Bucket = new s3.Bucket(this, id, { // 👇 Setting up CORS cors: [ { allowedMethods: [ s3.HttpMethods.GET, s3.HttpMethods.POST, s3.HttpMethods.PUT, ], allowedOrigins: ['http://localhost:3000'], allowedHeaders: ['*'], }, ], }); } } const app = new cdk.App(); new MyCdkStack(app, 'my-cdk-stack', { stackName: 'my-cdk-stack', env: { region: process.env.CDK_DEFAULT_REGION, account: process.env.CDK_DEFAULT_ACCOUNT, }, });
In the code sample, we:
Used the Bucket construct to create an S3 bucket
Set the CORS configuration of the bucket, where:
The allowedMethods
property is an array of the HTTP methods the domains in
allowedOrigins
are allowed to issue.
The allowedOrigins
property is an array of the domains that have permission
to access the bucket. If you own a domain https://example.com
, that's what
you should specify here.
The allowedHeaders
property specifies the response headers we want to be
able to access in our frontend code.
Depending on the HTTP methods your frontend needs to use when making requests to the bucket, you might have to tweak the options.
For example, if you're only making GET requests - just set GET
as an allowed
method.
Let's deploy the CDK stack and look at the results:
npx aws-cdk deploy
Our CloudFormation stack has been provisioned successfully:
If we open the S3 console and look at the CORS config in the Permissions
section, we can see that CORS is successfully configured.
CORS
errors when making HTTP requests to S3 buckets or APIs, when we type in the endpoint or the HTTP method wrong.For instance, if I make a POST request to aws.amazon.com/wrong-path
I'll get a
CORS error in the console of my browser.
The same happens if I send the request with a wrong HTTP method that the endpoint does not support, I'll still get a CORS error.
Here is an example of configuring CORS outside of CDK.
CORS is a mechanism that allows a server to use a combination of HTTP headers to indicate from which domains, other than its own, it receives requests.
By default servers only take requests made from applications hosted on the same domain.
All S3 buckets are hosted on the https://amazonaws.com
domain, which is
different from where we host our client applications, so we have to set up
CORS.
To configure an S3 bucket to allow cross-origin requests, you have to:
Permissions
tabCross-origin resource sharing (CORS)
section and click
on the Edit
button[ { "AllowedHeaders": [ "*" ], "AllowedMethods": [ "GET", "HEAD", "PUT", "POST" ], "AllowedOrigins": [ "*" ], "MaxAgeSeconds": 3000 } ]
The CORS configuration consists of the following properties:
AllowedHeaders
- which headers are allowed to be sent in a preflight
(OPTIONS
) request.
In the example above we've used the *
wildcard character to specify that all
headers are allowed in a preflight request.
AllowedMethods
- which HTTP methods the specified origins are allowed to
perform on the S3 bucket.
You might have to tweak this value, e.g. if your frontend only needs to make
GET
requests to the S3 bucket, you can remove the PUT
and POST
methods.
Conversely, if you need to make DELETE
requests to the S3 bucket, add the
method.
AllowedOrigins
- which origins (domains) are allowed to make requests to
the S3 bucket.
In our case we've set the value to a wildcard, meaning all domains. However,
it's a best practice to only allow requests from known origins. If you own a
domain https://example.com
this is what you would specify here.
You can pass multiple origins in the array, however, note that each origin can
contain a maximum of 1 wildcard character. For example, specifying an origin
of https://*.example.com
, would enable requests to your S3 bucket from all
subdomains, e.g. - https://wwww.example.com
and https://blog.example.com
.
MaxAgeSeconds
- this is an optional element. It defines the time in
seconds that the browser caches an S3 response to a preflight OPTIONS
request for the specified resource.
If the response is cached, the browser doesn't have to send OPTIONS
requests
for the same resource over and over.
We can provide multiple rule objects in a CORS configuration, in fact up to 100 rules can be defined in a single CORS configuration.
Let's look at an example with 2 rules. The configuration allows PUT
, POST
and DELETE
requests from a specific origin and GET
requests from all
origins.
[ { "AllowedHeaders": [ "*" ], "AllowedMethods": [ "POST", "PUT", "DELETE" ], "AllowedOrigins": [ "https://www.example.com" ] }, { "AllowedHeaders": [ "*" ], "AllowedMethods": [ "GET", "HEAD" ], "AllowedOrigins": [ "*" ], "MaxAgeSeconds": 3000 } ]
In the CORS configuration above, we've specified that all origins can make GET
requests to our S3 bucket.
However, only the https://www.example.com
origin can perform POST
, PUT
and
DELETE
operations on the bucket.
AllowedMethods
and AllowedOrigins
that your application needs to function properly.I've also written an article on how to enable CORS for API Gateway or HTTP API in AWS CDK.
You can learn more about the related topics by checking out the following tutorials: