Enabling CORS on AWS API Gateway

Published on 09 December 2021

Introduction

If you have a website that is trying to call an API on AWS API Gateway, you probably want CORS (Coss-Origin Region Sharing) enabled. This is to allow cross-domain access (you may know it from S3), or more specifically, if you have a website https://www.domain.com that wants to run an API from another site (let's say https://3fdssdfgxfscil.execute-api.us-east-1.amazonaws.com/Prod/films), that isn't going to work without CORS, as the the browser will look for some headers that allow this, and will not find them.

There is such a pain at times, that there is actually a Chrome plug-in to try and get around this limitation. Really though, the solution is to enable CORS. So that is what I decided to do for my POST API. One other note about doing a POST, don't try and use the URL in the browser like you can do with a GET! You will need to use Postman, or CURL, or invoke-webrequest, or similar.

How to Enable CORS on the Gateway

This is actually not that difficult. You will need to just choose "Enable CORS" and then accept the defaults in most cases.

cors1

Where you will need to definitely change it, is if you only want to restrict access from a particular domain. So if you ONLY want to allow the API to be run from https://www.domain.com, you want to put the domain name (www.domain.com) here, rather than the '*'. In my case, I left it as a *.

cors2

When you press "enable", it will then try and make the changes for you. In my experience, it will be able to do some of those changes, and some might fail. I found that I needed to go back into OPTIONS, go to "Integration Response", expand my response, and then add the headers manually.

cors3

So far so good, but if you test this, it might still not work as there is something else we need to do (depending on your API backend, but it still didn't work for a Lambda proxy integration API). And as an amateur, I found this is where a lot of documentation and videos stopped.

The basic issue is that for CORS to work, there is the preflight check, and then the response from the resource (the lambda function in our case). In short, enabling CORS on the API Gateway will (hopefully) do the configuration for the preflight check, but will not modify what is returned from the Lambda function (the response). You will also need to do that.

Return Headers back to the Browser

You will also need to return the required headers back to the browser. So when the browser hits https://www.domain.com and try to run https://3fdssdfgxfscil.execute-api.us-east-1.amazonaws.com/Prod/films, your RETURN back to the browser basically needs to allow the API Gateway to say, "Yep, this is fine", and this is done via headers.

So in my case, as my API was calling a Lambda function, I also needed to add the headers to my response within the function. At the time, I didn't have any headers being returned, so I added this entire 'headers' section to my return function (this was done in Python):

        return {
            'headers': {
                "Access-Control-Allow-Origin": "*",
                "Access-Control-Allow-Methods": "GET,POST,OPTIONS",
                "Access-Control-Allow-Headers": "Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token",
                "Content-Type": "application/json"
                
            },
            'statusCode': response['ResponseMetadata']['HTTPStatusCode'],
            'body': 'Address ' + event['queryStringParameters']['payload1'] + ' completed.'
        }

When you have updated your lambda function, you then then test your API from within the API Gateway, and verify that you are seeing the headers being returned.

cors4

Finally, you can test it from the browser, and using the Developer Tools, see the headers in the response there.

cors5

These headers, and more information about enabling CORS can be found here. I do not do development for my day-to-day job, but it is good to learn, so hopefully this will help someone in a similar situation!

comments powered by Disqus