Search code examples
amazon-web-servicesgoaws-lambdaserverlessaws-serverless

Serverless authorizer request does not provide methodArn, or any information about the calling lambda


I am having issues getting the methodArn from a request object in an authorizer lambda I have defined. I am using serverless with golang. Here is a redacted setup of the code that I have.

main.go - the authorizer handler function

func Handler(request events.APIGatewayCustomAuthorizerRequestTypeRequest) (events.APIGatewayCustomAuthorizerResponse, error) {
  // I have tried logging the entire request to cloud watch, see further down for the sample

  // i have code here to verify a jwt token
  return nil, nil
}

serverless.yml - my serverless setup to register the function and define the authorizer

functions:
  permission_verify:
    handler: bin/handlers/permission/verify

package:
  patterns:
    - "!./**"
    - ./bin/**

provider:
  httpApi:
    authorizers:
      custom:
        functionName: permission_verify
        type: request

With the above setup I am able to use the authorizer in other microservices to verify jwt tokens but now I would like to add more functionality to the authorizer and with that I need the methodArn on the request to be present.

Here is the output from cloud watch after hitting an endpoint that uses the authorizer

cloud watch - the request json

{
    "type": "REQUEST",
    "methodArn": "",
    "resource": "",
    "path": "",
    "httpMethod": "",
    "headers": {
        "accept": "*/*",
        "accept-encoding": "gzip, deflate, br",
        "authorization": "redacted",
        "content-length": "redacted",
        "content-type": "application/json",
        "host": "redacted",
        "postman-token": "redacted",
        "user-agent": "PostmanRuntime/7.31.3",
        "x-amzn-trace-id": "redacted",
        "x-forwarded-for": "redacted",
        "x-forwarded-port": "443",
        "x-forwarded-proto": "https"
    },
    "queryStringParameters": null,
    "pathParameters": null,
    "stageVariables": null,
    "requestContext": {
        "path": "",
        "accountId": "redacted",
        "resourceId": "",
        "stage": "$default",
        "requestId": "redacted",
        "identity": {
            "apiKey": "",
            "sourceIp": ""
        },
        "resourcePath": "",
        "httpMethod": "",
        "apiId": "redacted"
    }
}

I have scoured the internet looking for an explanation and cause for having no information about the calling lambda in the request to no avail. It has been quite a bit of time, any help would be immensely appreciated.


Solution

  • I found a solution that worked using REST instead of HTTP. I had to redo all my functions and define the serverless like the following;

    serverless.yaml

    custom:
      authorizer:
        type: token
        identitySource: method.request.header.Authorization
        identityValidationExpression: Bearer (.*)
        name: permission_verify
        # if this is in a different service, you can replace the name property with 'arn' having the arn of the function
    
    functions:
      permission_verify:
        handler: bin/handlers/permission/verify
    
      permission_read:
        events:
          -http: # i had httpApi before
            method: get
            path: /
            authorizer: ${self:custom.authorizer}
    

    This allowed me to change the function signature to something like below, and after checking the cloud watch logs, I was able to get the method ARN.

    func Handler(request events.APIGatewayCustomAuthorizerRequest) (events.APIGatewayCustomAuthorizerResponse, error)
    

    Here is an example of what I got in cloud watch;

    {
        "type": "TOKEN",
        "authorizationToken": "Bearer <redacted>",
        "methodArn": "arn:aws:execute-api:us-east-1:redacted/PUT/"
    }
    

    In summary, the cause of this was just inconsistent serverless config that did not fit the purpose of what I required. I'd say IMO, it is easy to think that serverless is a fool proof way of defining infrastructure but it's not and it's good to understand what you're going for against what is offered.