AWS API Gateway - CORS “access-control-allow-origin” - multiple entries

岁酱吖の 提交于 2020-01-02 02:05:08

问题


I have a AWS Lambda instance that connects to a defined AWS API Gateway. If I enable CORS and give the access-control-allow-origin a definition of http://example.com, then I am able to access the Lambda instance from http://example.com. However, if I use https://example.com, it doesn't work.

So in AWS, how can I define using multiple access-control-allow-origin values without using a wildcard? I tried using something like *.example.com, but that doesn't work.

EDIT: If I use '*' as my value on the API gateway, but setup CORS rules on my S3 bucket, would that be secure? Example for bucket rules:

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
    <CORSRule>
        <AllowedOrigin>http://example.com</AllowedOrigin>
        <AllowedMethod>GET</AllowedMethod>
        <AllowedMethod>POST</AllowedMethod>
        <AllowedMethod>PUT</AllowedMethod>
        <MaxAgeSeconds>3000</MaxAgeSeconds>
        <AllowedHeader>*</AllowedHeader>
    </CORSRule>
    <CORSRule>
        <AllowedOrigin>https://example.com</AllowedOrigin>
        <AllowedMethod>GET</AllowedMethod>
        <AllowedMethod>POST</AllowedMethod>
        <AllowedMethod>PUT</AllowedMethod>
        <MaxAgeSeconds>3000</MaxAgeSeconds>
        <AllowedHeader>*</AllowedHeader>
    </CORSRule>
    <CORSRule>
        <AllowedOrigin>https://www.example.com</AllowedOrigin>
        <AllowedMethod>GET</AllowedMethod>
        <AllowedMethod>POST</AllowedMethod>
        <AllowedMethod>PUT</AllowedMethod>
        <MaxAgeSeconds>3000</MaxAgeSeconds>
        <AllowedHeader>*</AllowedHeader>
    </CORSRule>
</CORSConfiguration>

回答1:


Unfortunately this is not possible today. The CORS spec does not allow for partial wild cards and currently API Gateway only allows a single static value for the header.

You may be able to overload your OPTIONS method to return this value dynamically based on the incoming host header.




回答2:


This has always been an annoyance with CORS if you want to enable several Origins.

The common workaround in other systems (e.g. express/nginx etc) is to:

  • inspect the Origin header sent by the browser
  • check it against a whitelist of origins
  • if it matches, return the incoming Origin as the Access-Control-Allow-Origin header, else return a placeholder (default origin)

This isn't possible using AWS-Gateway's autowired CORS support as uses a mock integration, it is however possible if you write your own code to process the OPTIONS request.

Below is example code written with lambda proxy integrations:

const allowedOrigins = [
    "http://example.com",
    "http://example.com:8080",
    "https://example.com",
    "https?://[a-z]*.?myapp.com",
    "http://localhost:[0-9]*"
];

exports.handler = (event, context) => {
    const origin = event.headers.Origin || event.headers.origin;
    var goodOrigin = false;

    if (origin) {
        allowedOrigins.forEach( allowedOrigin => {
            if (!goodOrigin && origin.match(allowedOrigin)) {
                goodOrigin = true;
            }
        });
    }

    context.succeed({
        headers: {
            "Access-Control-Allow-Headers": "Accept,Accept-Language,Content-Language,Content-Type,Authorization,x-correlation-id",
            "Access-Control-Expose-Headers": "x-my-header-out",
            "Access-Control-Allow-Methods": "DELETE,GET,HEAD,OPTIONS,PATCH,POST,PUT",
            "Access-Control-Allow-Origin": goodOrigin ? origin : allowedOrigins[0]
        },
        statusCode: 204
    });
};

Save this as a lambda function. To set this up in API-Gateway add an OPTIONS method and for the Integration Request choose Lambda Function with Use Lambda Proxy integration ticked.

Of course the downside to this is that you are paying for the lambda functions, and calling the lambda function will probably be an extra 50ms latency over the mock integration.




回答3:


You can get API Gateway to return a comma delimited list of domains, but the browser only expects one. This is implied in the other answers, just stating it explicitely.

Here is reference on browser only accepting one domain in the CORS header: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS/Errors/CORSMultipleAllowOriginNotAllowed

And just for kicks, here is how you return multiple (though not sure why you'd want to). Put single quotes around your comma delimited list. I just did it one of my APIs and it worked (as in it returns multiple domains and the API breaks).

First click here:

Fill in as follows (using your values):

Note the use of single quotes only at the beginning and end. You'll return multiple domains, but the browser won't make the next call because it doesn't parse them to do a match.

And here is a screenshot from POSTman showing both values returned in the header:



来源:https://stackoverflow.com/questions/39628640/aws-api-gateway-cors-access-control-allow-origin-multiple-entries

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!