DEV Community

Anzhari Purnomo
Anzhari Purnomo

Posted on

2

Parse cookie information from AWS Lambda

Recently I had a chance to work with a lot of AWS Lambda based service. I found out somehow there are not a lot of library to help extract the cookies out of lambda's request?

I ended up writing an NPM module for this issue:
https://www.npmjs.com/package/@anzp/aws-lambda-cookie

An example on how to use it:

API Gateway HTTP API Proxy Event

Consider this as your event:

{
  "version": "2.0",
  "routeKey": "$default",
  "rawPath": "/path/to/resource",
  "rawQueryString": "parameter1=value1&parameter1=value2&parameter2=value",
  "cookies": [
    "nevergonnagiveyouup",
    "nevergonna=bringyoudown; secure; httponly; samesite=strict; path=/; domain=.example.com; max-age=3600; expires=Mon, 01-Jan-2020 00:00:00 GMT; version=1; comment=something; commenturl=http://example.com/"
  ],
  "headers": {
    "Header1": "value1",
    "Header2": "value1,value2"
  },
  "queryStringParameters": {
    "parameter1": "value1,value2",
    "parameter2": "value"
  },
  "requestContext": {
    "accountId": "123456789012",
    "apiId": "api-id",
    "authentication": {
      "clientCert": {
        "clientCertPem": "CERT_CONTENT",
        "subjectDN": "www.example.com",
        "issuerDN": "Example issuer",
        "serialNumber": "a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1",
        "validity": {
          "notBefore": "May 28 12:30:02 2019 GMT",
          "notAfter": "Aug  5 09:36:04 2021 GMT"
        }
      }
    },
    "authorizer": {
      "jwt": {
        "claims": {
          "claim1": "value1",
          "claim2": "value2"
        },
        "scopes": [
          "scope1",
          "scope2"
        ]
      }
    },
    "domainName": "id.execute-api.us-east-1.amazonaws.com",
    "domainPrefix": "id",
    "http": {
      "method": "POST",
      "path": "/path/to/resource",
      "protocol": "HTTP/1.1",
      "sourceIp": "192.168.0.1/32",
      "userAgent": "agent"
    },
    "requestId": "id",
    "routeKey": "$default",
    "stage": "$default",
    "time": "12/Mar/2020:19:03:58 +0000",
    "timeEpoch": 1583348638390
  },
  "body": "eyJ0ZXN0IjoiYm9keSJ9",
  "pathParameters": {
    "parameter1": "value1"
  },
  "isBase64Encoded": true,
  "stageVariables": {
    "stageVariable1": "value1",
    "stageVariable2": "value2"
  }
}
Enter fullscreen mode Exit fullscreen mode

And this is your lambda code:

let response;
const {
  ApiGatewayHttpApiProxyEventHandler,
} = require("@anzp/aws-lambda-apig-cookie");
exports.lambdaHandler = async (event, context) => {
  try {
    const handler = new ApiGatewayHttpApiProxyEventHandler(event);
    const cookies = handler.getCookies();
    console.log({ cookies });
    response = {
      statusCode: 200,
      body: JSON.stringify({
        message: JSON.stringify(cookies),
        // location: ret.data.trim()
      }),
    };
  } catch (err) {
    console.log(err);
    return err;
  }

  return response;
};

Enter fullscreen mode Exit fullscreen mode

This will be the parsed cookies:

const cookies = {
  cookieObjects: [
    { name: "nevergonnagiveyouup", value: "" },
    {
      name: "nevergonna",
      value: "bringyoudown",
      comment: "something",
      commenturl: "http://example.com/",
      domain: ".example.com",
      expires: new Date("2020-01-01T00:00:00.000Z"),
      httpOnly: true,
      maxAge: 3600,
      path: "/",
      sameSite: "strict",
      secure: true,
      version: "1",
    },
  ],
  cookieStrings: [
    "nevergonnagiveyouup",
    "nevergonna=bringyoudown; secure; httponly; samesite=strict; path=/; domain=.example.com; max-age=3600; expires=Mon, 01-Jan-2020 00:00:00 GMT; version=1; comment=something; commenturl=http://example.com/",
  ],
};
Enter fullscreen mode Exit fullscreen mode

Cloudfront Viewer Request Event (Lambda@Edge)

Consider this as your event:

{
    "Records": [
        {
            "cf": {
                "config": {
                    "distributionId": "EXAMPLE"
                },
                "request": {
                    "uri": "/test",
                    "method": "GET",
                    "clientIp": "2001:cdba::3257:9652",
                    "headers": {
                        "user-agent": [
                            {
                                "key": "User-Agent",
                                "value": "Test Agent"
                            }
                        ],
                        "host": [
                            {
                                "key": "Host",
                                "value": "d123.cf.net"
                            }
                        ],
                        "cookie": [
                            {
                                "key": "Cookie",
                                "value": "nevergonnagiveyouup"
                            },
                            {
                                "key": "Cookie",
                                "value": "nevergonna=bringyoudown; secure; httponly; samesite=strict; path=/; domain=.example.com; max-age=3600; expires=Mon, 01-Jan-2020 00:00:00 GMT; version=1; comment=something; commenturl=http://example.com/"
                            }
                        ]
                    }
                }
            }
        }
    ]
}
Enter fullscreen mode Exit fullscreen mode

And this is your lambda code:

let response;
const {
  CloudfrontViewerRequestEventHandler,
} = require("@anzp/aws-lambda-apig-cookie");
exports.lambdaHandler = async (event, context, callback) => {
  try {
    const request = event.Records[0].cf.request;
    const handler = new CloudfrontViewerRequestEventHandler(event);
    const cookies = handler.getCookies();
    console.log({ cookies });
  } catch (err) {
    console.log(err);
    response = {
      statusCode: 500,
    };
    callback(null, response)
  }
  callback(null, request)
};

Enter fullscreen mode Exit fullscreen mode

This will be the parsed cookies:

const cookies = {
  cookieObjects: [
    { name: "nevergonnagiveyouup", value: "" },
    {
      name: "nevergonna",
      value: "bringyoudown",
      comment: "something",
      commenturl: "http://example.com/",
      domain: ".example.com",
      expires: new Date("2020-01-01T00:00:00.000Z"),
      httpOnly: true,
      maxAge: 3600,
      path: "/",
      sameSite: "strict",
      secure: true,
      version: "1",
    },
  ],
  cookieStrings: [
    "nevergonnagiveyouup",
    "nevergonna=bringyoudown; secure; httponly; samesite=strict; path=/; domain=.example.com; max-age=3600; expires=Mon, 01-Jan-2020 00:00:00 GMT; version=1; comment=something; commenturl=http://example.com/",
  ],
};
Enter fullscreen mode Exit fullscreen mode

Hopefully it can help anybody struggling with the similar issue.

Image of Timescale

Timescale – the developer's data platform for modern apps, built on PostgreSQL

Timescale Cloud is PostgreSQL optimized for speed, scale, and performance. Over 3 million IoT, AI, crypto, and dev tool apps are powered by Timescale. Try it free today! No credit card required.

Try free

Top comments (0)

Postmark Image

Speedy emails, satisfied customers

Are delayed transactional emails costing you user satisfaction? Postmark delivers your emails almost instantly, keeping your customers happy and connected.

Sign up