Search code examples
aws-lambdahttp-headersaws-api-gatewayamazon-cloudfront

Multiple Set-Cookie headers ignored by API Gateway in combination with Lambda integration and CloudFront


My setup looks like this:

|––––––––––––|                  |–––––––––––––|     |–––––––––––––––––|
|            |  <- origin 1 ->  | API Gateway | <-> | Lambda function |
|            |                  |–––––––––––––|     |–––––––––––––––––|
| CloudFront |  
|            |                  |–––––––––––––|
|            |  <- origin 2 ->  |  S3 bucket  |
|––––––––––––|                  |–––––––––––––|

I need CloudFront in front of the API Gateway to get automatic http->https redirection.
I'm using a custom login.example.com subdomain w/ CloudFront.
API Gateway's generated URL is the origin 1 for CloudFront distribution.

This all works as expected.

I can even return one Set-Cookie header from the lambda function and it will get passed on until it reaches the browser.

{
  "statusCode": 302,
  "body": "",
  "headers": {
    "location": "/test",
    "surrogate-control": "no-store",
    "cache-control": "no-store, no-cache, must-revalidate, proxy-revalidate",
    "pragma": "no-cache",
    "expires": "0",
    "content-length": "0",
    "date": "Fri, 19 Feb 2021 17:25:56 GMT",
    "connection": "keep-alive",
    "set-cookie": "cookie1=68abcdbefbef7d84c26e68; Max-Age=2592000; Domain=example.com; Path=/; HttpOnly; Secure; SameSite=Strict"
  },
  "isBase64Encoded": false
}

Adding another one isn't working - as expected when you look at the docs:

{
  "statusCode": 302,
  "headers": {
    "location": "/test",
    "set-cookie": [
      "cookie1=68abcdbefbef7d84c26e68; Max-Age=2592000; Domain=example.com; Path=/; HttpOnly; Secure; SameSite=Strict",
      "cookie2-login=; Max-Age=0; Path=/; Expires=Thu, 01 Jan 1970 00:00:00 GMT; HttpOnly; Secure"
    ],
    "surrogate-control": "no-store",
    "cache-control": "no-store, no-cache, must-revalidate, proxy-revalidate",
    "pragma": "no-cache",
    "expires": "0",
    "content-length": "0"
  }
}

Both of these will be ignored/removed.

But even when I'm using the multiValueHeaders object to return more than one of the same kind like this:

{
  "statusCode": 302,
  "body": "",
  "headers": {
    "location": "/test",
    "surrogate-control": "no-store",
    "cache-control": "no-store, no-cache, must-revalidate, proxy-revalidate",
    "pragma": "no-cache",
    "expires": "0",
    "content-length": "0",
    "date": "Fri, 19 Feb 2021 17:25:56 GMT",
    "connection": "keep-alive"
  },
  "isBase64Encoded": false,
  "multiValueHeaders": {
    "Set-Cookie": [
      "cookie1=68abcdbefbef7d84c26e68; Max-Age=2592000; Domain=example.com; Path=/; HttpOnly; Secure; SameSite=Strict",
      "cookie2-login=; Max-Age=0; Path=/; Expires=Thu, 01 Jan 1970 00:00:00 GMT; HttpOnly; Secure"
    ]
  }
}

the API Gateway removes/ignores them from the response it passes on to CloudFront.

What am I doing wrong?
Do I have to map something in the API Gateway when using the multiValueHeaders?
Normal headers['set-cookie'] is passed on automatically but multiValueHeaders not?
Are the additional attributes a problem?
Is it a problem that I'm trying to set the cookie for the root-domain and not the login.example.com domain?


Solution

  • Not sure how Philipp missed this, as it was on the same page he cited:

    To customize the response, your Lambda function should return a response with the following format.

    {
        "cookies" : ["cookie1", "cookie2"],
        "isBase64Encoded": true|false,
        "statusCode": httpStatusCode,
        "headers": { "headername": "headervalue", ... },
        "body": "Hello from Lambda!"
    }
    

    So just return cookies: ['name=value', 'name=value']

    Source: https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-lambda.html#http-api-develop-integrations-lambda.v2