Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Zappa Option for Enabling Cross-Origin Resource Sharing #494

Closed
AusIV opened this issue Nov 27, 2016 · 3 comments
Closed

Zappa Option for Enabling Cross-Origin Resource Sharing #494

AusIV opened this issue Nov 27, 2016 · 3 comments

Comments

@AusIV
Copy link

AusIV commented Nov 27, 2016

I'm building an application that I want to have IAM authenticated and accessed through a browser. I have my browser application set up to properly sign requests to IAM authenticated APIs, but there's a problem. The browser does pre-flight OPTIONS requests to the same URL as the XHR request, but there's no way to get the browser to sign the pre-flight request. So if the entire API is IAM authenticated, the pre-flight request will fail authentication and be rejected, at which point the browser will decide it shouldn't allow cross-origin requests for this URL.

This can be resolved manually by enabling CORS with some manual steps after doing the Zappa deployment (outlined here).

Those manual steps can pretty easily be taken care of in the CloudFormation template by adding a section along the lines of:

"OPTIONS0": {
  "Type": "AWS::ApiGateway::Method",
  "Properties": {
    "ResourceId": {
      "Fn::GetAtt": [
        "Api",
        "RootResourceId"
      ]
    },
    "RestApiId": {
      "Ref": "Api"
    },
    "AuthorizationType": "NONE",
    "HttpMethod": "OPTIONS",
    "Integration": {
      "Type": "MOCK",
      "IntegrationResponses": [
        {
          "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": "'GET,POST,OPTIONS'",
            "method.response.header.Access-Control-Allow-Origin": "'*'"
          },
          "ResponseTemplates": {
            "application/json": ""
          },
          "StatusCode": "200"
        }
      ],
      "PassthroughBehavior": "NEVER",
      "RequestTemplates": {
        "application/json": "{\"statusCode\": 200}"
      }
    },
    "MethodResponses": [
      {
        "ResponseModels": {
          "application/json": "Empty"
        },
        "ResponseParameters": {
          "method.response.header.Access-Control-Allow-Headers": true,
          "method.response.header.Access-Control-Allow-Methods": true,
          "method.response.header.Access-Control-Allow-Origin": true
        },
        "StatusCode": "200"
      }
    ]
  }
},
"OPTIONS1": {
  "Type": "AWS::ApiGateway::Method",
  "Properties": {
    "ResourceId": {
      "Ref": "ResourceAnyPathSlashed"
    },
    "RestApiId": {
      "Ref": "Api"
    },
    "AuthorizationType": "NONE",
    "HttpMethod": "OPTIONS",
    "Integration": {
      "Type": "MOCK",
      "IntegrationResponses": [
        {
          "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": "'GET,POST,OPTIONS'",
            "method.response.header.Access-Control-Allow-Origin": "'*'"
          },
          "ResponseTemplates": {
            "application/json": ""
          },
          "StatusCode": "200"
        }
      ],
      "PassthroughBehavior": "NEVER",
      "RequestTemplates": {
        "application/json": "{\"statusCode\": 200}"
      }
    },
    "MethodResponses": [
      {
        "ResponseModels": {
          "application/json": "Empty"
        },
        "ResponseParameters": {
          "method.response.header.Access-Control-Allow-Headers": true,
          "method.response.header.Access-Control-Allow-Methods": true,
          "method.response.header.Access-Control-Allow-Origin": true
        },
        "StatusCode": "200"
      }
    ]
  }
},

I'm currently working on a pull-request to add an "enable_cors" option to the Zappa config that will inject the OPTIONS sections into the CloudFormation template created with troposhere. I just have a few more things to test before I submit it.

@AusIV
Copy link
Author

AusIV commented Nov 27, 2016

It should also be noted that simply enabling CORS at the API gateway layer is necessary but not sufficient for an application that wants to do CORS requests against a Zappa API that is IAM authenticated (and likely authenticated using other API-gateway level authenticators). The application itself will still need to respond with the appropriate CORS related headers, but it doesn't get the opportunity to do that if API Gateway blocks the pre-flight request.

AusIV added a commit to AusIV/Zappa that referenced this issue Nov 27, 2016
As outlined here: Miserlou#494 setting
up a Zappa application to use CORS along with an api-gateway managed
authentication mechanism requires enabling cors at the api-gateway layer
to deal with the pre-flight options requests. There is a fairly simple
button to manage this in the API-gateway management console, but I'd
rather not have to take those steps after doing a deployment.

This commit gets it working with simple defaults for some of the headers.
Before I submit the pull request I want to extend it to support more fine
tuning of the available options.
@Miserlou
Copy link
Owner

This is a fantastic issue, diagnosis and solution. I look forward to merging your Pull Request!

@AusIV AusIV mentioned this issue Nov 28, 2016
@Miserlou
Copy link
Owner

👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants