mattstuehler
mattstuehler

Reputation: 9282

AWS API Gateway: Can't use CORS and API Key authentication together?

I'm using AWS SAM to create a few Lambda functions that get triggered by API-Gateway events.

In general, it's working, but I need to add two features: CORS, and API key authentication.

I've been able to set it so that an API Key is required to call the API.

Here is the Globals section of my template.yaml:

Globals:
  Api:
    Auth:
      ApiKeyRequired: true

This works perfectly.

I've also been able to set it so that it supports CORS.

Here is the Resources/Api section my my template.yaml:

Resources:
  MyApi:
    Type: AWS::Serverless::Api
    Properties:
      StageName: Prod
      Cors:
        AllowMethods: "'*'"
        AllowHeaders: "'*'"
        AllowOrigin: "'*'"
        AllowCredentials: "'*'"

However, it only works if I do one or the other.

In other words, if I do both:

Globals:
  Api:
    Auth:
      ApiKeyRequired: true
Resources:
  MyApi:
    Type: AWS::Serverless::Api
    Properties:
      StageName: Prod
      Cors:
        AllowMethods: "'*'"
        AllowHeaders: "'*'"
        AllowOrigin: "'*'"
        AllowCredentials: "'*'"

... it stops working.

Specifically, the sam CLI tool builds and deploys the sam app; however, if I call the API in a browser, the requests fail:

enter image description here

Here is the specific error message:

Access to XMLHttpRequest at 'https://75hkwcgiy.execute-api.us-east-1.amazonaws.com/Prod/plans/35580' from origin 'http://[mydomain].com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

GET https://75hkwcgiy.execute-api.us-east-1.amazonaws.com/Prod/plans/35580 net::ERR_FAILED

Any insight on why this is the case, and how to fix it so I can support both CORS and API key authentication?

Upvotes: 1

Views: 704

Answers (3)

Daniel
Daniel

Reputation: 21

The reason it fails with ApiKeyRequired true and CORS turned on is that the ApiKeyRequired is adding the api key required attribute to all the options calls, which causes the preflight to fail as it's not standard to have authentication details in an options call.

If you're trying to define all the integrations in a swagger/openapi template, I don't have the solution to get around this.

You can get around this by defining the integrations using events in the lambda and specifying which methods should have api key enabled, then remove the ApiKeyRequired from the gateway.

On your lambda have

Events:
    HttpGet:
      Type: Api 
      Properties:
        Path: "/jobs"
        Method: GET
        RestApiId: !Ref ApiGateway
        Auth:
          ApiKeyRequired: True

Upvotes: 2

garlic_rat
garlic_rat

Reputation: 109

You mention "if I call the API in a browser" it generates an error.

The error stems from a security mechanism that browsers implement called the same-origin policy. See David Katz's Medium post.

Katz provides more detailed information on the error, its causes, and some solution options. These include using a browser plugin or a proxy server (yours or someone else's).

Upvotes: 0

Derrops
Derrops

Reputation: 8117

Shouldn't AllowCredentials be true?

Upvotes: 2

Related Questions