2
votes

I have created some Lambda Functions and deployed them using SAM. The deployment is successful, but when trying to reach the endpoints I always obtain

{ message: "Unauthorized" }

Even I'm sending a correct Bearer token using the Authentication header. Then if I go to the Authorizer and run the test, it passes well and generates logs in CloudWatch, but when I run a request from my frontend app or a REST client app to the endpoint, I get the unauthorized message and checking CloudWatch, there's not an execution of the authorizer function.

Besides, checking the Authorizer function from the Lambda configuration, I can see that there's an error in the API Gateway Trigger, but don't know what it means.

I created the authorizer function using the guide provided by AWS: https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-use-lambda-authorizer.html#api-gateway-lambda-authorizer-lambda-function-create

Sharing my SAM configuration

Resources:
 SomeAPI:
    Type: AWS::Serverless::Api
    Properties:
      StageName: Prod
      TracingEnabled: true
      Auth:
        DefaultAuthorizer: MyLambdaTokenAuthorizer
        Authorizers:
          MyLambdaTokenAuthorizer:
            FunctionArn: !GetAtt AuthorizerFunction.Arn

  GetActivityStreamFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: get-activity-stream/ 
      Handler: index.handler
      Layers:
        - !Ref DepencenciesLayer
        - !Ref DatabaseLayer
      Events:
        GetActivityStream:
          Type: Api
          Properties:
            RestApiId: !Ref SomeAPI
            Path: /activity-stream
            Method: get

  ## Authorizer Function
  AuthorizerFunction:
    Type: AWS::Serverless::Function
    Properties:
      Layers:
        - !Ref DepencenciesLayer
      CodeUri: authorizer/ 
      Handler: index.handler

Regarding the response sent back by the Authorizer, it sends all the params requested by API Gateway

{
      principalId: decoded.sub,
      policyDocument: getPolicyDocument("Allow", params.methodArn),
      context: { scope: decoded.scope }
}

The runtime I'm using is nodejs12.x, and here are some screenshots of what a I get from AWS console.

Testing the Authorizer

Checking the API endpoint config

Error showed on Lambda console

2
Could you try in API gateway under your /activity-stream route, to open the method request -> in the authorizer dropdown: select any other value (none or another authorizer) and hit save, then go through the same process and reselect your authorizer. It should prompt you that it will re-add permissions to be allowed to invoke your authorizer function. This has worked for me before. - Tom Nijs

2 Answers

1
votes

After lots of hours testing different things found by Internet, I started to have improvements when I noticed that the policy document was wrong:

Before

  const policyDocument = {
    "Version": "2012-10-17",
    "Statement": [
      {
        "Effect": effect,
        "Action": "execute-api:Invoke",
        "Resource": resource
      }
    ]
  };

After

  const policyDocument = {
    "Version": "2012-10-17",
    "Statement": [
      {
        "Effect": effect,
        "Action": [
          "execute-api:Invoke"
        ],
        "Resource": [
          resource
        ]
      }
    ]
  };

Where Action and Resource should be arrays. Also I set the resource variable to be '*' instead of event.methodArn, because when caching the authorizations the policy cached matches only the first endpoints reached, while next calls to other endpoints result in the error: user not authorized for the method requested.

Other change was in the template.yaml

Resources:
  SomeAPI:
    Type: AWS::Serverless::Api
      Auth:
        DefaultAuthorizer: MyLambdaTokenAuthorizer
        AddDefaultAuthorizerToCorsPreflight: false
        Authorizers:
          MyLambdaTokenAuthorizer:
            FunctionArn: !GetAtt AuthorizerFunction.Arn
            Identity:
              Header: Authorization
              ValidationExpression: Bearer.*

AddDefaultAuthorizerToCorsPreflight with false value makes the preflight calls (OPTIONS), to not be verified, because the preflight request are done by the browser, otherwise all the calls from Axios also fails.

0
votes

I had the same thing. If the authorizer Lambda is not being called, I think it is because the auth is cached or the config thinks that no identity material was in the request.

Have a look at the https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/api_gateway_authorizer#identity_source setting: only certain headers are considered to contain identity material, and they are used as cache keys