Is it possible to add an HTTP header from AWS Custom Auth on API gateway?

11,696

Solution 1

We recently added support for this. Docs should be up soon.

Now you can return an object like this from the authorizer function:

{
  "principalId": "xxxxxxxx", // The principal user identification associated with the token send by the client.
  "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" : {
    "key" : "value",
    "numKey" : 1,
    "boolKey" : true
  }
}

Arrays and objects aren't allowed, only string/number/boolean as valid JSON. The root key must be named context.

You can access those values in the request $context like so:

$context.authorizer.key -> value 
$context.authorizer.numKey -> 1
$context.authorizer.boolKey -> true

So to answer your question, you wont' be able to conditionally add the header, but you could set the header value to $context.authorizer.yourKey and if yourKey isn't set in the authorizer response, the header value would be blank (but the header would still be sent).

Edit:

Docs are live http://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-lambda-authorizer-output.html

Solution 2

I was able to get this working after a day of pulling my hair out and hopefully I can save someone from that. It adds a bit more to Jacks' response. Basically, you can dynamically add headers by using Body Mapping Templates

  1. Create and Authorizer Lambda (you can use the authorizer blueprint lambda to get started), do your business logic to create the AuthPolicy and populate the context object with the key/values.
  2. On the API Gateway, select the resource, click on Method Request and set the Auth to your Authorizer lambda
  3. Open Method Execution, select the Integration type and make sure to unselect Use Lambda Proxy integration (if your request points to a lambda)
  4. Add a Body Mapping Template - create one from the template and this is where you have access to $context.authorizer.key
  5. Add the following to your template (just under "body-json" : $input.json('$')," is fine)
"headers": {
     "key-header" : "$util.escapeJavaScript($context.authorizer.key)",
     #foreach($param in $input.params().header.keySet())
         "$param": "$util.escapeJavaScript($input.params().header.get($param))" 
         #if($foreach.hasNext),#end
     #end },

This will add a new header called "key-header" and also forward all the original headers allowing you to append additional information like user_id, user_role, etc to the upstream service.

Solution 3

I tried Emanuel Canha's answer above, but that no longer seems to work. The way I got it to work yesterday (5 June 2019) is to

  1. Create the lambda
  2. Add the lambda under Method Request as your authorizer
  3. Open Integration Request
  4. Open HTTP Headers
  5. Add a header with the name you want (key-header in the above example)
  6. Use context.authorizer.yourKey as the mapped from entry. (Note that you do not use the $ in this field.)

Solution 4

You can only get PrincipalId from authorizer result, in your integration request, you can map a header value using context.authorizer.principalId

Share:
11,696
Admin
Author by

Admin

Updated on June 17, 2022

Comments

  • Admin
    Admin almost 2 years

    I am using Custom Auth on AWS API Gateway, but I would like to add an extra HTTP header depending on the result. Does anyone know if this is possible, or how to do it. If it is not, is there an idea of if or when this will be possible?

    Many thanks.

  • jackko
    jackko over 7 years
    Mind marking as correct answer? This might be the most complete documentation on the new functionality until our docs go live :)
  • Greg Fennell
    Greg Fennell over 7 years
    @JackKohn-AWS, does this work if your using Mock? I'm trying to use $context.authorizer.principalId in the Integration Request body mapping and it's throwing an error.
  • jackko
    jackko over 7 years
    The Integration Request body mapping has to be exactly like { "statusCode":200} for Mock integration. If you need to mock the response payload, you should use a Integration Response mapping template.
  • dinvlad
    dinvlad over 6 years
    Just a caveat, Lambda proxy integration loses the type of context values, i.e. all of string, number and boolean values would be passed as strings.