AWS API Gateway is a simple way to provision a serverless API, it comes with plenty of features which are configuration driven. At times there is a need to extend API Gateway when more complex requirements need to be supported. One such example is supporting Cross Origin Resource Sharing (CORS) for multiple Origins.
A bit about CORS
The purpose behind CORS is to provide a policy to the browser which HTTP methods, headers, and origins may be invoked from a different domain. This gives the web application the ability to choose if the request can be served. Often with CORS you will see an error like the one below concerning why your cross site request could not be fulfilled.
Access to XMLHttpRequest at ‘https://www.website.com/login' from origin ‘https://dev.website.com' has been blocked by CORS policy: Response to preflight request doesn’t pass access control check: The ‘Access-Control-Allow-Origin’ header has a value ‘https://dev.website.com' that is not equal to the supplied origin.
When you have multiple origins that may call your API you need a way to ensure they have all been given access via CORS Origins. Let’s assume you have two test environments, dev.website.com and qa.website.com which interact with your web application. You might think to set the CORS Origin value as “https://*.website.com” but unfortunately this isn’t supported. The less desired option is to do wildcard access from all origins; the principle of least privilege here isn’t followed and can lead to huge security concerns.
How to handle multiple CORS Origins in API Gateway
The best approach is to programmatically set the CORS Origin value based on the request in the pre-flight call. This is accomplished using the AWS Lambda integration.
When the browser calls our API now the pre-flight request will first be served by the CORS handler Lambda. At that time we can use pattern matching capabilities to verify that the Origin by the requester is approved.
The code behind the CORS handler Lambda is straight-forward. We inspect the request event and obtain the origin from the headers. We then pattern match using Regex. If the Origin is approved by our pattern then we would return the same value in the CORS Origin header. Otherwise, we would substitute a different Origin value which would instruct the browser to prevent the request.
What we demonstrated was an easy way to extend the AWS API Gateway infrastructure to handle some of the common needs when dealign with CORS Origins.