aws-api-gatewayaws-samaws-sam-cli

403 on Options request within SAM local invoke, but not when deployed?


Why does curl say "missing auth token"? As far as I know I definitely enabled the options method to return a default 200. I definitely have "AuthorizationType": "NONE" in my options setup.

I am running a frontend via set PORT=4000 && react-scripts start and a backend with sam local start-api --template lambdas_sam.json.

When I test the options method via curl I get:

curl -i -X OPTIONS http://127.0.0.1:3000/scanRecords -H "Origin: http://localhost:4000" -H "Access-Control-Request-Method: POST"

HTTP/1.1 403 FORBIDDEN
Server: Werkzeug/3.0.1 Python/3.11.8
Date: Wed, 11 Sep 2024 02:47:58 GMT
Content-Type: application/json
Content-Length: 43
Connection: close

{"message":"Missing Authentication Token"}

lambdas_sam.json snippet:

"scanRecords": {
      "Type": "AWS::Serverless::Function",
      "Properties": {
        "Handler": "dist/dynamo/CRUD.scanRecords",
        "CodeUri": "./backend",
        "Policies": [
          "AmazonDynamoDBFullAccess",
          "CloudWatchLogsFullAccess"
        ],
        "Events": {
          "0": {
            "Type": "Api",
            "Properties": {
              "Path": "/scanRecords",
              "Method": "post"
            }
          }
        }
      }
    },
    "scanRecordsResource": {
      "Type": "AWS::ApiGateway::Resource",
      "Properties": {
        "ParentId": {
          "Fn::GetAtt": [
            "apiGatewayRestApi",
            "RootResourceId"
          ]
        },
        "PathPart": "scanRecords",
        "RestApiId": {
          "Ref": "apiGatewayRestApi"
        }
      }
    },
    "scanRecordsGatewayMethod": {
      "Type": "AWS::ApiGateway::Method",
      "Properties": {
        "AuthorizationType": "COGNITO_USER_POOLS",
        "AuthorizerId": {
          "Ref": "CognitoAuthorizer"
        },
        "HttpMethod": "post",
        "Integration": {
          "IntegrationHttpMethod": "POST",
          "Type": "AWS_PROXY",
          "Uri": {
            "Fn::Sub": [
              "arn:aws:apigateway:us-east-1:lambda:path/2015-03-31/functions/${lambdaArn}/invocations",
              {
                "lambdaArn": {
                  "Fn::GetAtt": [
                    "scanRecords",
                    "Arn"
                  ]
                }
              }
            ]
          }
        },
        "ResourceId": {
          "Ref": "scanRecordsResource"
        },
        "RestApiId": {
          "Ref": "apiGatewayRestApi"
        }
      }
    },
    "scanRecordsOptionsMethod": {
      "Type": "AWS::ApiGateway::Method",
      "Properties": {
        "AuthorizationType": "NONE",
        "HttpMethod": "OPTIONS",
        "ResourceId": {
          "Ref": "scanRecordsResource"
        },
        "RestApiId": {
          "Ref": "apiGatewayRestApi"
        },
        "Integration": {
          "Type": "MOCK",
          "IntegrationResponses": [
            {
              "StatusCode": 200,
              "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": "'POST,OPTIONS'",
                "method.response.header.Access-Control-Allow-Origin": "'*'"
              },
              "ResponseTemplates": {
                "application/json": ""
              }
            }
          ],
          "PassthroughBehavior": "WHEN_NO_MATCH",
          "RequestTemplates": {
            "application/json": "{}"
          }
        },
        "MethodResponses": [
          {
            "StatusCode": 200,
            "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
            }
          }
        ]
      }
    },
    "ApiGatewayInvokeLambdaPermissionscanRecords": {
      "Type": "AWS::Lambda::Permission",
      "Properties": {
        "Action": "lambda:InvokeFunction",
        "FunctionName": {
          "Fn::GetAtt": [
            "scanRecords",
            "Arn"
          ]
        },
        "Principal": "apigateway.amazonaws.com",
        "SourceArn": {
          "Fn::Sub": "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${apiGatewayRestApi}/*/*/*"
        }
      }
    }

Solution

  • AFAIK the Cognito authorizer is not supported yet in aws-sam-cli for local testing, the only supported authorizer in local mode is the lambda authoizer.

    In the code we can see:

    LOG.debug("Authorizer '%s' is currently unsupported (must be a Lambda Authorizer), skipping", auth_name) 
    

    Another way is to test resources deployed remotly with sam sync.