Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Api Gateway with Lambda and Cognito Authorizer #990

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions typescript/api-gateway-lambda-cognito-authorizer/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
*.js
!jest.config.js
*.d.ts
node_modules

# CDK asset staging directory
.cdk.staging
cdk.out
6 changes: 6 additions & 0 deletions typescript/api-gateway-lambda-cognito-authorizer/.npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
*.ts
!*.d.ts

# CDK asset staging directory
.cdk.staging
cdk.out
135 changes: 135 additions & 0 deletions typescript/api-gateway-lambda-cognito-authorizer/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
## <!--BEGIN STABILITY BANNER-->

![Stability: Stable](https://img.shields.io/badge/stability-Stable-success.svg?style=for-the-badge)

> **This is a stable example. It should successfully build out of the box**
>
> This example is built on Construct Libraries marked "Stable" and does not have any infrastructure prerequisites to build.

---

<!--END STABILITY BANNER-->

This project is intended to be sample code only. Not for use in production.

## Architecture

<img src="./assets/architecture.png" width=700>

This project will create the following in your AWS cloud environment:

- REST Api Gateway
- Example lambda function

This is an example to showcase how to add a Cognito authorizer in an REST Api Gateway with a Lambda Integration.

## Deploy

---

Requirements:

- git
- npm (node.js)
- AWS access key & secret for AWS user with permissions to create resources listed above
- Cognito User Pool

---

First, you will need to install the AWS CDK:

```
$ npm install -g aws-cdk
```

You can check the toolkit version with this command:

```
$ cdk --version
```

Next, you will want to create a project directory:

```
$ mkdir ~/cdk-samples
```

Now you're ready to clone this repo and change to this sample directory:

```
$ git clone https://github.com/aws-samples/aws-cdk-examples.git
$ cd typescript/api-gateway-lambda-cognito-authorizer
```

Install the required dependencies:

```
$ npm install
```

Go to `bin/apigw-lambda-cognito-authorizer.ts` and update the Cognito User Pool Id with yours.

```ts
//....
const app = new cdk.App();
new ApigwLambdaCognitoAuthorizerStack(
app,
"ApigwLambdaCognitoAuthorizerStack",
{
cognitoUserPoolId: "<your-cognito-userpool-id>",
}
);
```

At this point you can now synthesize the CloudFormation template for this code.

```
$ cdk synth
```

If everything looks good, go ahead and deploy! This step will actually make
changes to your AWS cloud environment.

```
$ cdk bootstrap
$ cdk deploy
```

## Testing the app

To test this application:

1. Note the endpoint of the newly created Api Gateway.
2. Retrieve the Cognito access token.
3. Make the following call in your cli:

```bash
curl --location --request GET '<https://<api-gateway-endpoint>/<stage>/test' \
--header 'Authorization: Bearer <your-cognito-access-token>' \
```

4. After this call you will see:

```bash
{"message":"Hello World"}
```

To clean up, issue this command (this will NOT remove CloudWatch logs -- you will need to do those manually)

Also, you will need to empty the bucket before deleting the stack.

```
$ cdk destroy
```

# Useful commands

- `cdk ls` list all stacks in the app
- `cdk synth` emits the synthesized CloudFormation template
- `cdk deploy` deploy this stack to your default AWS account/region
- `cdk diff` compare deployed stack with current state
- `cdk docs` open CDK documentation

---

This code has been tested and verified to run with AWS CDK 2.81.0
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/usr/bin/env node
import "source-map-support/register";
import * as cdk from "aws-cdk-lib";
import { ApigwLambdaCognitoAuthorizerStack } from "../lib/apigw-lambda-cognito-authorizer-stack";

const app = new cdk.App();
new ApigwLambdaCognitoAuthorizerStack(
app,
"ApigwLambdaCognitoAuthorizerStack",
{
cognitoUserPoolId: "XXXXXXXXXXXXXX",
}
);
64 changes: 64 additions & 0 deletions typescript/api-gateway-lambda-cognito-authorizer/cdk.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
{
"app": "npx ts-node --prefer-ts-exts bin/apigw-lambda-cognito-authorizer.ts",
"watch": {
"include": [
"**"
],
"exclude": [
"README.md",
"cdk*.json",
"**/*.d.ts",
"**/*.js",
"tsconfig.json",
"package*.json",
"yarn.lock",
"node_modules",
"test"
]
},
"context": {
"@aws-cdk/aws-lambda:recognizeLayerVersion": true,
"@aws-cdk/core:checkSecretUsage": true,
"@aws-cdk/core:target-partitions": [
"aws",
"aws-cn"
],
"@aws-cdk-containers/ecs-service-extensions:enableDefaultLogDriver": true,
"@aws-cdk/aws-ec2:uniqueImdsv2TemplateName": true,
"@aws-cdk/aws-ecs:arnFormatIncludesClusterName": true,
"@aws-cdk/aws-iam:minimizePolicies": true,
"@aws-cdk/core:validateSnapshotRemovalPolicy": true,
"@aws-cdk/aws-codepipeline:crossAccountKeyAliasStackSafeResourceName": true,
"@aws-cdk/aws-s3:createDefaultLoggingPolicy": true,
"@aws-cdk/aws-sns-subscriptions:restrictSqsDescryption": true,
"@aws-cdk/aws-apigateway:disableCloudWatchRole": true,
"@aws-cdk/core:enablePartitionLiterals": true,
"@aws-cdk/aws-events:eventsTargetQueueSameAccount": true,
"@aws-cdk/aws-iam:standardizedServicePrincipals": true,
"@aws-cdk/aws-ecs:disableExplicitDeploymentControllerForCircuitBreaker": true,
"@aws-cdk/aws-iam:importedRoleStackSafeDefaultPolicyName": true,
"@aws-cdk/aws-s3:serverAccessLogsUseBucketPolicy": true,
"@aws-cdk/aws-route53-patters:useCertificate": true,
"@aws-cdk/customresources:installLatestAwsSdkDefault": false,
"@aws-cdk/aws-rds:databaseProxyUniqueResourceName": true,
"@aws-cdk/aws-codedeploy:removeAlarmsFromDeploymentGroup": true,
"@aws-cdk/aws-apigateway:authorizerChangeDeploymentLogicalId": true,
"@aws-cdk/aws-ec2:launchTemplateDefaultUserData": true,
"@aws-cdk/aws-secretsmanager:useAttachedSecretResourcePolicyForSecretTargetAttachments": true,
"@aws-cdk/aws-redshift:columnId": true,
"@aws-cdk/aws-stepfunctions-tasks:enableEmrServicePolicyV2": true,
"@aws-cdk/aws-ec2:restrictDefaultSecurityGroup": true,
"@aws-cdk/aws-apigateway:requestValidatorUniqueId": true,
"@aws-cdk/aws-kms:aliasNameRef": true,
"@aws-cdk/aws-autoscaling:generateLaunchTemplateInsteadOfLaunchConfig": true,
"@aws-cdk/core:includePrefixInUniqueNameGeneration": true,
"@aws-cdk/aws-efs:denyAnonymousAccess": true,
"@aws-cdk/aws-opensearchservice:enableOpensearchMultiAzWithStandby": true,
"@aws-cdk/aws-lambda-nodejs:useLatestRuntimeVersion": true,
"@aws-cdk/aws-efs:mountTargetOrderInsensitiveLogicalId": true,
"@aws-cdk/aws-rds:auroraClusterChangeScopeOfInstanceParameterGroupWithEachParameters": true,
"@aws-cdk/aws-appsync:useArnForSourceApiAssociationIdentifier": true,
"@aws-cdk/aws-rds:preventRenderingDeprecatedCredentials": true,
"@aws-cdk/aws-codepipeline-actions:useNewDefaultBranchForCodeCommitSource": true
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import * as cdk from "aws-cdk-lib";
import { Construct } from "constructs";
import * as apigateway from "aws-cdk-lib/aws-apigateway";
import * as logs from "aws-cdk-lib/aws-logs";
import { Runtime } from "aws-cdk-lib/aws-lambda";
import * as lambda from "aws-cdk-lib/aws-lambda";
import * as cognito from "aws-cdk-lib/aws-cognito";

type RestApiProps = {
cognitoUserPoolId: string;
};

export class ApigwLambdaCognitoAuthorizerStack extends cdk.Stack {
constructor(scope: Construct, id: string, props: RestApiProps) {
super(scope, id);

//Define Cloudwatch log group for the api
const logGroup = new logs.LogGroup(this, "ApiLogs");

//Define API gateway
const api = new apigateway.RestApi(this, "ExampleRestAPI", {
restApiName: "ExampleRestAPI",
description: "Example Rest API with Cognito Authorizer",
endpointTypes: [apigateway.EndpointType.REGIONAL],
defaultCorsPreflightOptions: {
allowOrigins: apigateway.Cors.ALL_ORIGINS,
allowMethods: apigateway.Cors.ALL_METHODS,
},
deployOptions: {
accessLogDestination: new apigateway.LogGroupLogDestination(logGroup),
accessLogFormat: apigateway.AccessLogFormat.jsonWithStandardFields(),
},
});

//Define the authorizer
const authorizer = new apigateway.CognitoUserPoolsAuthorizer(
this,
"Authorizer",
{
cognitoUserPools: [
cognito.UserPool.fromUserPoolId(
this,
"UserPool",
props.cognitoUserPoolId
),
],
}
);

// Define the lambda function
const lambdaFunction = new lambda.Function(this, "validator", {
runtime: lambda.Runtime.NODEJS_18_X,
handler: "index.handler",
code: lambda.Code.fromAsset("lambda"),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where is your lambda code?

});

// Define the lambda integration
const validatorIntegration = new apigateway.LambdaIntegration(
lambdaFunction,
{
proxy: true,
}
);

// Define the resources and methods of the APi gateway
const newGenAIValidationResource = api.root.addResource("test");
newGenAIValidationResource.addMethod("GET", validatorIntegration, {
authorizer: authorizer,
authorizationType: apigateway.AuthorizationType.COGNITO,
});
}
}
24 changes: 24 additions & 0 deletions typescript/api-gateway-lambda-cognito-authorizer/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"name": "apigw-lambda-cognito-authorizer",
"version": "0.1.0",
"bin": {
"apigw-lambda-cognito-authorizer": "bin/apigw-lambda-cognito-authorizer.js"
},
"scripts": {
"build": "tsc",
"watch": "tsc -w",
"cdk": "cdk"
},
"devDependencies": {
"@types/jest": "^29.5.8",
"@types/node": "20.9.0",
"aws-cdk": "2.110.0",
"ts-node": "^10.9.1",
"typescript": "~5.2.2"
},
"dependencies": {
"aws-cdk-lib": "2.110.0",
"constructs": "^10.0.0",
"source-map-support": "^0.5.21"
}
}
31 changes: 31 additions & 0 deletions typescript/api-gateway-lambda-cognito-authorizer/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"compilerOptions": {
"target": "ES2020",
"module": "commonjs",
"lib": [
"es2020",
"dom"
],
"declaration": true,
"strict": true,
"noImplicitAny": true,
"strictNullChecks": true,
"noImplicitThis": true,
"alwaysStrict": true,
"noUnusedLocals": false,
"noUnusedParameters": false,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": false,
"inlineSourceMap": true,
"inlineSources": true,
"experimentalDecorators": true,
"strictPropertyInitialization": false,
"typeRoots": [
"./node_modules/@types"
]
},
"exclude": [
"node_modules",
"cdk.out"
]
}
Loading