Troubleshooting AWS API Gateway & CORS issues

What is CORS?

CORS (Cross-Origin Resource Sharing) is a mechanism that allows restricted resources on a web page to interact with other origins outside the domain from which the first resource was served. In simpler terms, it lets your API interact with different domains.

The problem

Setting CORS while using AWS API Gateway can be confusing as the Enable CORS option in the Action menu doesn't work out of the box. The problem occurs during the pre-flight call that fail as it is. A solution to this issue is simply to create a MOCK endpoint for such API and make sure the response headers are set appropriately.

Mock integrations are a quick and easy way to enable CORS

A mock integration can be implemented either on the console or better yet using a Cloudformation template.

Solution: Implement a Mock Endpoint

A mock endpoint is a temporary replacement for an actual backend function that simulates the API response.

Here's how you can enable CORS using the AWS console:

Step 1: Add the OPTIONS method:

  • Go to each CORS-enabled endpoint.
  • Configure the endpoint as a Mock Integration.

Step 2: Configure the Method Response:

In the Method Response (Left bottom) block add Status 200 and the corresponding Response Headers

Access-Control-Allow-Headers, Access-Control-Allow-Methods, Access-Control-Allow-Origin

Step 3: Configure the Method Execution:

In the Method Execution (Right Bottom) block, use the 200 response status created in step 2 and map headers as shown below.

Access-Control-Allow-Headers: 'Access-Control-Allow-Origin, Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token' 

Access-Control-Allow-Methods: 'OPTIONS'

Access-Control-Allow-Origin: '*'

Mapping Template: application/json
{
    statusCode: 200,
    headers: {
        "Access-Control-Allow-Origin": "*"
    },
        body: ''
};

Some sources advise explicitly setting the header in the mapping template too.

Step 4: Save and Deploy:

As mentioned in step 1, this should be repeated for each CORS-enabled endpoint, that includes GET requests.

You also need to add the Access-Control-Allow-Origin: '*' mapping to your GET, POST, PUT, DELETE methods (steps 2, 3)

Add more response codes (4xx, 5xx) by repeating steps 2 and 3 🔄

Advanced: CloudFormation Template

For a more IaC-compliant solution, utilize a CloudFormation template. This approach defines an integration for the OPTIONS method, including the status code, response parameters, and Mock type.

Benefits of using CloudFormation:

  • Automated and reusable configuration.
  • Centralized definition of CORS settings.
  • Improved readability and maintainability.
OptionsMethod:
  Type: AWS::ApiGateway::Method
  Properties:
    AuthorizationType: NONE
    RestApiId:
      Ref: ApiIdentifier
    ResourceId:
      Ref: ResourceIdentifier
    HttpMethod: OPTIONS
    Integration:
      IntegrationResponses:
      - StatusCode: 200
        ResponseParameters:
          method.response.header.Access-Control-Allow-Headers: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'"
          method.response.header.Access-Control-Allow-Methods: "'POST,OPTIONS'"
          method.response.header.Access-Control-Allow-Origin: "'*'"
        ResponseTemplates:
          application/json: ''
      PassthroughBehavior: WHEN_NO_MATCH
      RequestTemplates:
        application/json: '{"statusCode": 200}'
      Type: MOCK
    MethodResponses:
    - StatusCode: 200
      ResponseModels:
        application/json: 'Empty'
      ResponseParameters:
          method.response.header.Access-Control-Allow-Headers: false
          method.response.header.Access-Control-Allow-Methods: false
          method.response.header.Access-Control-Allow-Origin: false

The last three lines specify whether the headers are required.

  • Repeat the process for each CORS-enabled endpoint.
  • Include other response codes (4xx, 5xx) by following the steps above.

With these steps in place, you can seamlessly enable CORS for your AWS API Gateway and enjoy seamless cross-origin interactions!