awslabs/aws-jwt-verify

Using this library in Lambda at Edge - Cloudfront

dhamya opened this issue · 6 comments

Question
Based on https://github.com/awslabs/aws-jwt-verify#cloudfront-lambdaedge - I included the code in a edge lambda function, however, I got following error >>

"errorType": "Runtime.ImportModuleError",
"errorMessage": "Error: Cannot find module 'aws-jwt-verify'\nRequire stack:\n- /var/task/EdgeAuth.js\n- /var/runtime/index.mjs",
"stack": [
    "Runtime.ImportModuleError: Error: Cannot find module 'aws-jwt-verify'"

What do I need to do to include this in my lambda function (this is Viewer request lambda function on Cloudfront)

Versions
Which version of aws-jwt-verify are you using?

latest
Are you using the library in Node.js or in the Web browser?
Node.js, I think (using it in Lambda at Edge function)
If Node.js, which version of Node.js are you using? (Should be at least 14)
16

A couple follow up questions:

  • Can you provide details on how you are building and deploying this Lambda function?
  • Can you share any webpack or TypeScript config files that impact that build?
  • Does the code work locally (e.g. when you unit test)?
  • Its a lambda function that's tied to a Cloudfront distribution & gets triggered on "viewer request"
  • I use CDK to bundle all my infrastructure - including CF distribution and the lambdas
  • There's no "build" phase - as the code gets zipped up & deployed as part of cdk synth & deploy phases (through AWS Codepipeline, actually) Given lambda at edge does not allow any layers, I can't "include" custom libraries

Has anyone tried to successfully integrate this with lamda-at-edge (Cloudtfront)?

Refer this link for the default modules present for CF lambda functions https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/functions-javascript-runtime-features.html#writing-functions-javascript-features-builtin-modules

I was hoping this library would be "integrated" in above list of modules so its available for all JS CF functions.

CloudFront provides two ways to write and manage edge functions: CloudFront Functions and Lambda@Edge. The link above refers to CloudFront Functions. NodeJS dependencies included in package.json should work with that CDK build - it doesn't require Lambda Layers.

Can you share the snippet of your CDK code for this Lambda@Edge and the dependencies from your package.json ?

here's package.json >>

"dependencies": {
   "aws-cdk-lib": "2.59.0",
   "aws-jwt-verify": "^4.0.0",
   "constructs": "^10.0.0",
   "source-map-support": "^0.5.21"
 }

& CDK extract:

const cloudfront_handler = new lambda.Function(this, "CDNAuthorizer", {
      functionName: "CDNAuthorizer",
      runtime: lambda.Runtime.NODEJS_16_X,
      handler: "EdgeAuth.handler",
      description:
        "A lambda function for checking authZ for cloudfront requsts",
      code: lambda.Code.fromAsset("lambdas"),
      logRetention:
        stageName == "prod" ? RetentionDays.ONE_YEAR : RetentionDays.FIVE_DAYS,
    });

...

<other CF code>
 edgeLambdas: [
          {
            functionVersion: cloudfront_handler.currentVersion,
            eventType: cloudfront.LambdaEdgeEventType.VIEWER_REQUEST,
          },
        ],

& the js >>

const { CognitoJwtVerifier } = require("aws-jwt-verify");
const jwtVerifier = CognitoJwtVerifier.create({
  userPoolId: "xxxx",
  tokenUse: "access",
  clientId: "zzzzz",
  scope: "read",
});

exports.handler = async (event) => {
  const request = event.Records[0].cf.request;
  const params = querystring.parse(request.querystring);
  const accessToken = params.token; 
  try {
    await jwtVerifier.verify(accessToken);
  } catch {
    return {
      status: "403",
      body: "Unauthorized",
    };
  }
  return request; // allow request to proceed
};

I recommend you switch to NodejsFunction which extends lambda.Function and represents "A Node.js Lambda function bundled using esbuild"

import { NodejsFunction } from 'aws-cdk-lib/aws-lambda-nodejs';

Otherwise, I suspect your build doesn't do a build step for the lambda function - something like cd lambdas && npm install

There is nothing special about this library in Lambda@Edge, if will work as any other dependency: you just need to include it in your Lambda deployment package.

There's various ways to do that: e.g. @hakanson suggestion to use NodejsFunction as that automatically does installation of dependencies into the Lambda deployment package.

An example of using this library in Lambda@Edge code can be seen here: https://github.com/aws-samples/cloudfront-authorization-at-edge/blob/c4251988dc4b8d4e858c580e2f95f6577284111c/src/lambda-edge/shared/shared.ts#L12
In that repo we use webpack to bundle the dependency into the Lambda deployment package.