17
votes

I have successfully implemented a Lambda authorizer for my AWS API Gateway, but I want to pass a few custom properties from it to my Node.js endpoint.

My output from my authorizer follows the format specified by AWS, as seen below.

{
  "principalId": "yyyyyyyy",
  "policyDocument": {
    "Version": "2012-10-17",
    "Statement": [
      {
        "Action": "execute-api:Invoke",
        "Effect": "Allow|Deny",
        "Resource": "arn:aws:execute-api:<regionId>:<accountId>:<appId>/<stage>/<httpVerb>/[<resource>/<httpVerb>/[...]]"
      }
    ]
  },
  "context": {
    "company_id": "123",
    ...
  }
}

In my case, context contains a few parameters, like company_id, that I would like to pass along to my Node endpoint.

If I was to use a Lambda endpoint, I understand that this is done with Mapping Template and something like this:

{
  "company_id": "$context.authorizer.company_id"
}

However, Body Mapping Template is only available under Integration Request if Lambda is selected as Integration type. Not if HTTP is selected.

In short, how do I pass company_id from my Lambda authorizer to my Node API?

2
What about dropping these values into HTTP request headers? - Michael - sqlbot
@Michael-sqlbot That's pretty much what I would like to do. Headers, url or body doesn't really matter. Anything would be fine. The question is how one would do that? - Magnus Engdal
Create a header in the integration request, then specify, e.g. context.identity.whatever without a $ at the beginning. I'm not using a custom authorizer, but this works for me accessing other things in the context object and dropping them into headers that get forwarded to the origin... for example, I tried context.stage and context.apiId and they both forward as expected, as HTTP headers. Try that? - Michael - sqlbot
Also, the "Use HTTP Proxy Integration" option seems very poorly named. If you want to use request body mapping templates... just uncheck that option. It appears that option actually means "You know what? Just stay out of my way and proxy the request, as is, whatever it is, so that I can avoid messing with body mapping templates." You can proxy a request to your back-end with or without that option checked. - Michael - sqlbot
@Michael-sqlbot Thank you Michael! Finally got it to work with the help of your answer and aws support. I needed to set context.authorizer.company_id as HTTP Headers under Integration Request and company_id as HTTP Request Headers under Method Execution. - Magnus Engdal

2 Answers

33
votes

Most of the credit goes out to @Michael-sqlbot in the comments to my question, but I'll put the complete answer here if someone else finds this question.

Authorizer Lambda

It has to return an object in this format, where context contains the parameters you want to forward to your endpoint, as specified in the question.

{
  "principalId": "yyyyyyyy",
  "policyDocument": {
    "Version": "2012-10-17",
    "Statement": [{
      "Action": "execute-api:Invoke",
      "Effect": "Allow|Deny",
      "Resource": "arn:aws:execute-api:<regionId>:<accountId>:<appId>/<stage>/<httpVerb>/[<resource>/<httpVerb>/[...]]"
    }]
  },
  "context": {
    "company_id": "123", <-- The part you want to forward
    ...
  }
}

Method Request

Under Method Request / HTTP Request Headers, add the context property you want to forward:

  • Name: company_id
  • Required: optional
  • Cashing: optional

Integration Request

And under Integration Request / HTTP Headers, add:

  • Name: company_id
  • Mapped from: context.authorizer.company_id
  • Cashing: optional
3
votes

If you're using lamda-proxy, you can access the context from your event.requestContext.authorizer.context.

So your company_id can be accessed using event.requestContext.authorizer.context.company_id.