Search code examples
corsaws-cloudformationaws-api-gatewaypreflightsam

Preflight response 403 forbidden. How can I allow options method without x-api-key?


I'm using SAM to create my API in cloudformation.

I'm getting a 403 FORBIDDEN on my options method (thus also my preflight for my get method).

How can I allow my options method to reply with 200 OK without my x-api-key?

I've tried so many stackoverflow answers but none fit my SAM template format. I've tried all the different combinations of my AllowHeaders. I've ommited the x-api-key - still the same 403 FORBIDDEN.

If I send my x-api-key in postman with my request I get a 200 OK, but in my reactjs application it still gives the same error as below that my preflight does not pass.

Console log response to the get method enter image description here

Postman response to the options method (preflight testing) enter image description here

Cloudwatch error enter image description here

template.yaml

Globals:
  Function:
    Timeout: 10
  Api:
    Cors:
      AllowMethods: "'DELETE,GET,HEAD,OPTIONS,PATCH,POST,PUT'"
      AllowHeaders: "'Content-Type,X-Amz-Date,X-Amz-Security-Token,x-api-key,Authorization,Origin,Host,X-Requested-With,Accept,Access-Control-Allow-Methods,Access-Control-Allow-Origin,Access-Control-Allow-Headers'"
      AllowOrigin: "'*'"

Resources:
  BSApi:
    Type: AWS::Serverless::Api
    Properties:
      StageName: Prod
      Auth:
        ApiKeyRequired: true
        AddDefaultAuthorizerToCorsPreflight: false

  GrondvogFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: grondvog/
      Handler: app.lambdaHandler
      Runtime: nodejs12.x
      Policies:
        - LambdaInvokePolicy: {
          'FunctionName': !Ref RDBQueryFunction
        }
      Environment:
        Variables:
          "RDBQueryFunctionName": !Ref RDBQueryFunction
      Events:
        KryGrondvog:
          Type: Api
          Properties:
            RestApiId: !Ref BSApi
            Path: /grondvog
            Method: get
        OptionsGrondvog:
          Type: Api
          Properties:
            RestApiId: !Ref BSApi
            Path: /grondvog
            Method: options

Lambda function

if (event.httpMethod == 'OPTIONS') {
        rekords = {
            statusCode: 200,
            headers: {
                "Access-Control-Allow-Headers": "Content-Type,X-Amz-Date,X-Amz-Security-Token,x-api-key,Authorization,Origin,Host,X-Requested-With,Accept,Access-Control-Allow-Methods,Access-Control-Allow-Origin,Access-Control-Allow-Headers",
                "Access-Control-Allow-Origin": "*",
                "Access-Control-Allow-Methods": "DELETE,GET,HEAD,OPTIONS,PATCH,POST,PUT",
                "X-Requested-With": "*"
            },
            body: JSON.stringify({ statusText: "OK" })
        };
    }

Solution

  • Alright, I found the solution.

    I missed the part where I should tell my SAM application that for the options method I must specify that I don't want the api key. I just added the following to each options method:

    Auth:
      ApiKeyRequired: false
    
    GrondvogFunction:
        Type: AWS::Serverless::Function
        Properties:
          CodeUri: grondvog/
          Handler: app.lambdaHandler
          Runtime: nodejs12.x
          Policies:
            - LambdaInvokePolicy: {
              'FunctionName': !Ref RDBQueryFunction
            }
          Environment:
            Variables:
              "RDBQueryFunctionName": !Ref RDBQueryFunction
          Events:
            KryGrondvog:
              Type: Api
              Properties:
                RestApiId: !Ref BSApi
                Path: /grondvog
                Method: get
            OptionsGrondvog:
              Type: Api
              Properties:
                RestApiId: !Ref BSApi
                Path: /grondvog
                Method: options
                Auth:
                  ApiKeyRequired: false