awslabs / aws-jwt-verify

JS library for verifying JWTs signed by Amazon Cognito, and any OIDC-compatible IDP that signs JWTs with RS256, RS384, and RS512
Apache License 2.0
594 stars 43 forks source link

Using this library in Lambda at Edge - Cloudfront #119

Closed dhamya closed 1 year ago

dhamya commented 1 year ago

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

hakanson commented 1 year ago

A couple follow up questions:

dhamya commented 1 year ago

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.

hakanson commented 1 year ago

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 ?

dhamya commented 1 year ago

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
};
hakanson commented 1 year ago

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

ottokruse commented 1 year ago

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.