-
Notifications
You must be signed in to change notification settings - Fork 1k
New serverless pattern APIGW-APIKey-tenantid-mapping #3124
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
Open
Lavanya0513
wants to merge
20
commits into
aws-samples:main
Choose a base branch
from
Lavanya0513:main
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 11 commits
Commits
Show all changes
20 commits
Select commit
Hold shift + click to select a range
004c876
added new pattern for using Lambda Authorizer to map API Keys to tenant
Lavanya0513 9397873
Revert "added new pattern for using Lambda Authorizer to map API Keys…
Lavanya0513 0c7a68f
added new pattern for tenant to apikey
Lavanya0513 5e69d50
changes to add cognito
Lavanya0513 1739bc0
Added jpg file and updated readme
Lavanya0513 c6e8226
Updated readme
Lavanya0513 e78d895
changed link
Lavanya0513 6bf4bc5
apigw tenantid pattern
Lavanya0513 b048c4e
Merge pull request #1 from Lavanya0513/lavatang-feature-tenantbasedAP…
Lavanya0513 431e3ee
removed old directory
Lavanya0513 c17ba2c
added bio
Lavanya0513 455247a
Addressed comments on pull request
Lavanya0513 717db4c
added usage plan
Lavanya0513 5d50c5b
removed bio
Lavanya0513 caff571
added proper API key name
Lavanya0513 fc92614
changed folder name
Lavanya0513 9d027a4
Added bio
Lavanya0513 3030a71
changed bio
Lavanya0513 ab65600
added pattern arch
Lavanya0513 9ccef3d
added instructions
Lavanya0513 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,124 @@ | ||
| # Amazon API Gateway with Cognito, Lambda Authorizer, and DynamoDB for Tenant API Key Authentication | ||
|
|
||
| API Gateway's usage plans and API keys are fundamentally disconnected from authorization tokens. | ||
| Usage plans enforce rate limits via API keys, but auth tokens (JWTs from Cognito, Auth0, etc.) carry identity and permissions — these are two separate systems with no native link. This means customers cannot simply issue an auth token that inherently comes with rate-limiting attached. At scale (millions of auth tokens across thousands of tenants), managing this disconnect manually becomes untenable. | ||
|
|
||
| This pattern demonstrates how to implement a secure tenant-based API key authorization system using Amazon Cognito, Amazon API Gateway, AWS Lambda Authorizer, and Amazon DynamoDB. Cognito authenticates users and issues JWTs containing a custom `tenantId` claim. The Lambda authorizer extracts the tenant ID from the JWT, looks up the corresponding API key in DynamoDB, and returns a policy document enabling API Gateway access. | ||
|
|
||
| What this pattern solves: | ||
| - Bridges the auth–throttling gap — The Lambda authorizer acts as the glue between identity (JWT tenantId) and rate-limiting (API Gateway API key). By looking up the tenant's API key in DynamoDB and returning it via [usageIdentifierKey](https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-lambda-authorizer-output.html), a single auth token automatically activates the correct usage plan. Auth and throttling become one unified flow rather than two disconnected systems. | ||
| - Scales to millions of tokens per tenant — Any number of JWTs can map to the same tenant's API key. You don't need a 1:1 relationship between auth tokens and API keys. A tenant can have millions of active tokens, but they all resolve to one API key and one rate-limit policy — making management tractable at scale. | ||
| - Eliminates per-application auth logic — Backend services no longer independently validate tenants or enforce limits. The gateway handles both centrally, preventing inconsistency and reducing overhead. | ||
| - Prevents noisy neighbors transparently — Tenants only interact with their auth credentials. The API key mapping and usage plan enforcement happen internally, so rate-limiting is invisible to consumers but enforced consistently. | ||
| - Makes auth and usage a single operational concern — Onboarding a new tenant means: create identity (Cognito/Auth0), create API key with a usage plan, store the mapping in DynamoDB. One workflow governs both auth and throttling, rather than managing them as separate systems that drift apart over time. | ||
|
|
||
|
|
||
| Important: this application uses various AWS services and there are costs associated with these services after the Free Tier usage - please see the [AWS Pricing page](https://aws.amazon.com/pricing/) for details. You are responsible for any AWS costs incurred. No warranty is implied in this example. | ||
|
|
||
| ## Requirements | ||
|
|
||
| * [Create an AWS account](https://portal.aws.amazon.com/gp/aws/developer/registration/index.html) if you do not already have one and log in. The IAM user that you use must have sufficient permissions to make necessary AWS service calls and manage AWS resources. | ||
| * [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2.html) installed and configured | ||
| * [Git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) installed | ||
| * [Node.js and npm](https://nodejs.org/) installed | ||
| * [AWS CDK](https://docs.aws.amazon.com/cdk/latest/guide/getting_started.html) installed | ||
|
|
||
| ## Deployment Instructions | ||
|
|
||
| 1. Create a new directory, navigate to that directory in a terminal and clone the GitHub repository: | ||
| ``` | ||
| git clone https://github.com/aws-samples/serverless-patterns | ||
| ``` | ||
| 1. Change directory to the pattern directory: | ||
| ``` | ||
| cd apigw-APIKey-tenantid-cdk | ||
| ``` | ||
| 1. Install dependencies: | ||
| ``` | ||
| npm install | ||
| ``` | ||
| 1. Deploy the stack: | ||
| ``` | ||
| cdk deploy | ||
| ``` | ||
|
|
||
| Note the outputs from the CDK deployment process. The output will include the API Gateway URL, DynamoDB table name, Cognito User Pool ID, and User Pool Client ID. | ||
|
|
||
| ## How it works | ||
|
|
||
|  | ||
|
|
||
| 1. Client authenticates with Amazon Cognito and receives a JWT (ID token) containing the custom `tenantId` claim | ||
| 2. Client makes a request to the API with the JWT in the `Authorization` header | ||
| 3. API Gateway forwards the token to the Lambda Authorizer | ||
| 4. The Lambda Authorizer decodes the JWT, extracts the `custom:tenantId` claim, and looks up the tenant in the DynamoDB table | ||
| - If the tenant exists, the associated API key is retrieved and returned in the authorization context via `usageIdentifierKey` | ||
| - If the tenant does not exist or the token is invalid, the request is denied | ||
| 5. The API Gateway allows or denies access to the protected endpoint based on the policy returned by the authorizer | ||
|
|
||
| The DynamoDB table uses `tenantId` as the partition key and stores the corresponding `apiKey` for each tenant. | ||
|
|
||
| ## Testing | ||
|
|
||
| 1. Get the outputs from the deployment: | ||
| ```bash | ||
| # The outputs will be similar to | ||
| ApigwDynamodbApikeyCdkStack.ApiUrl = https://abc123def.execute-api.us-east-1.amazonaws.com/prod/ | ||
| ApigwDynamodbApikeyCdkStack.TableName = ApigwDynamodbApikeyCdkStack-TenantApiKeyTableXXXXXX-YYYYYY | ||
| ApigwDynamodbApikeyCdkStack.UserPoolId = us-east-1_XXXXXXXXX | ||
| ApigwDynamodbApikeyCdkStack.UserPoolClientId = XXXXXXXXXXXXXXXXXXXXXXXXXX | ||
| ``` | ||
|
|
||
| 1. Create a Cognito user with a tenantId: | ||
| ```bash | ||
| aws cognito-idp admin-create-user \ | ||
| --user-pool-id USER_POOL_ID \ | ||
| --username user@example.com \ | ||
| --user-attributes Name=email,Value=user@example.com Name=custom:tenantId,Value=sample-tenant \ | ||
| --temporary-password "TempPass1!" | ||
| ``` | ||
|
|
||
| 1. Set a permanent password for the user: | ||
| ```bash | ||
| aws cognito-idp admin-set-user-password \ | ||
| --user-pool-id USER_POOL_ID \ | ||
| --username user@example.com \ | ||
| --password "MySecurePass1!" \ | ||
| --permanent | ||
| ``` | ||
|
|
||
| 1. Insert a tenant mapping into the DynamoDB table: | ||
| ```bash | ||
| aws dynamodb put-item \ | ||
| --table-name TABLE_NAME \ | ||
| --item '{"tenantId": {"S": "sample-tenant"}, "apiKey": {"S": "my-api-key-123"}}' | ||
| ``` | ||
|
|
||
| 1. Get a token and call the API using the helper script: | ||
| ```bash | ||
| node get-token.js --user-pool-id USER_POOL_ID --client-id CLIENT_ID \ | ||
| --username user@example.com --password "MySecurePass1!" \ | ||
| --api-url https://REPLACE_WITH_API_URL/protected | ||
| ``` | ||
| If successful, you should receive a response like: | ||
| ```json | ||
| { "message": "Access granted" } | ||
| ``` | ||
|
|
||
| 1. Try with an invalid or missing token: | ||
| ```bash | ||
| curl https://REPLACE_WITH_API_URL/protected | ||
| ``` | ||
| You should receive an unauthorized error. | ||
|
|
||
| ## Cleanup | ||
|
|
||
| 1. Delete the stack: | ||
| ```bash | ||
| cdk destroy | ||
| ``` | ||
|
|
||
| ---- | ||
| Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
|
|
||
| SPDX-License-Identifier: MIT-0 |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,88 @@ | ||
| { | ||
| "app": "npx ts-node --prefer-ts-exts src/bin/apigw-dynamodb-apikey-cdk.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-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, | ||
| "@aws-cdk/aws-cloudwatch-actions:changeLambdaPermissionLogicalIdForLambdaAction": true, | ||
| "@aws-cdk/aws-codepipeline:crossAccountKeysDefaultValueToFalse": true, | ||
| "@aws-cdk/aws-codepipeline:defaultPipelineTypeToV2": true, | ||
| "@aws-cdk/aws-kms:reduceCrossAccountRegionPolicyScope": true, | ||
| "@aws-cdk/aws-eks:nodegroupNameAttribute": true, | ||
| "@aws-cdk/aws-ec2:ebsDefaultGp3Volume": true, | ||
| "@aws-cdk/aws-ecs:removeDefaultDeploymentAlarm": true, | ||
| "@aws-cdk/custom-resources:logApiResponseDataPropertyTrueDefault": false, | ||
| "@aws-cdk/aws-s3:keepNotificationInImportedBucket": false, | ||
| "@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature": false, | ||
| "@aws-cdk/aws-ecs:disableEcsImdsBlocking": true, | ||
| "@aws-cdk/aws-ecs:reduceEc2FargateCloudWatchPermissions": true, | ||
| "@aws-cdk/aws-dynamodb:resourcePolicyPerReplica": true, | ||
| "@aws-cdk/aws-ec2:ec2SumTImeoutEnabled": true, | ||
| "@aws-cdk/aws-appsync:appSyncGraphQLAPIScopeLambdaPermission": true, | ||
| "@aws-cdk/aws-rds:setCorrectValueForDatabaseInstanceReadReplicaInstanceResourceId": true, | ||
| "@aws-cdk/core:cfnIncludeRejectComplexResourceUpdateCreatePolicyIntrinsics": true, | ||
| "@aws-cdk/aws-lambda-nodejs:sdkV3ExcludeSmithyPackages": true, | ||
| "@aws-cdk/aws-stepfunctions-tasks:fixRunEcsTaskPolicy": true, | ||
| "@aws-cdk/aws-ec2:bastionHostUseAmazonLinux2023ByDefault": true, | ||
| "@aws-cdk/aws-route53-targets:userPoolDomainNameMethodWithoutCustomResource": true, | ||
| "@aws-cdk/aws-elasticloadbalancingV2:albDualstackWithoutPublicIpv4SecurityGroupRulesDefault": true, | ||
| "@aws-cdk/aws-iam:oidcRejectUnauthorizedConnections": true, | ||
| "@aws-cdk/core:enableAdditionalMetadataCollection": true, | ||
| "@aws-cdk/aws-lambda:createNewPoliciesWithAddToRolePolicy": true | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| #!/bin/bash | ||
| set -euo pipefail | ||
|
|
||
| APP="npx ts-node --prefer-ts-exts src/bin/apigw-dynamodb-apikey-cdk.ts" | ||
| STACK_NAME="ApigwDynamodbApikeyCdkStack" | ||
|
|
||
| npm install | ||
| cdk deploy "$STACK_NAME" --app "$APP" "$@" |
74 changes: 74 additions & 0 deletions
74
apigw-APIKey-tenantid-cdk/example-pattern-tenantbasedAPIkeyauthorization.json
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,74 @@ | ||
| { | ||
| "title": "Amazon API Gateway with Cognito, Lambda Authorizer & DynamoDB for Tenant API Key Authentication", | ||
| "description": "Implement a secure tenant-based API key authorization system using Amazon Cognito, Amazon API Gateway, AWS Lambda Authorizer, and Amazon DynamoDB. Cognito issues JWTs with a custom tenantId claim, and the Lambda authorizer maps tenants to API keys via DynamoDB.", | ||
|
|
||
| "language": "TypeScript", | ||
| "level": "200", | ||
| "framework": "AWS CDK", | ||
| "introBox": { | ||
| "headline": "How it works", | ||
| "text": [ | ||
| "This pattern demonstrates how to implement a secure tenant-based API key authorization system using Amazon Cognito, Amazon API Gateway, Lambda Authorizer, and Amazon DynamoDB.", | ||
| "Amazon Cognito authenticates users and issues JWTs (ID tokens) containing a custom tenantId claim.", | ||
| "The client sends the JWT in the Authorization header. API Gateway forwards the token to the Lambda authorizer, which decodes the JWT, extracts the custom:tenantId claim, and queries DynamoDB to retrieve the corresponding API key.", | ||
| "The authorizer returns a policy document with the usageIdentifierKey set to the API key, enabling API Gateway usage plan integration.", | ||
| "The API Gateway then allows or denies access to the protected endpoint based on the policy returned by the authorizer." | ||
| ] | ||
| }, | ||
| "gitHub": { | ||
| "template": { | ||
| "repoURL": "https://github.com/aws-samples/serverless-patterns/tree/main/apigw-APIKey-tenantid-cdk", | ||
| "templateURL": "serverless-patterns/apigw-APIKey-tenantid-cdk", | ||
| "projectFolder": "apigw-APIKey-tenantid-cdk", | ||
| "templateFile": "src/lib/apigw-dynamodb-apikey-stack.ts" | ||
| } | ||
| }, | ||
| "resources": { | ||
| "bullets": [ | ||
| { | ||
| "text": "Amazon Cognito Developer Guide", | ||
| "link": "https://docs.aws.amazon.com/cognito/latest/developerguide/what-is-amazon-cognito.html" | ||
| }, | ||
| { | ||
| "text": "Lambda Authorizers for Amazon API Gateway", | ||
| "link": "https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-use-lambda-authorizer.html" | ||
| }, | ||
| { | ||
| "text": "Amazon DynamoDB Developer Guide", | ||
| "link": "https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Introduction.html" | ||
| }, | ||
| { | ||
| "text": "Amazon API Gateway - REST APIs", | ||
| "link": "https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-rest-api.html" | ||
| }, | ||
| { | ||
| "text": "API Gateway Usage Plans", | ||
| "link": "https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-api-usage-plans.html" | ||
| } | ||
| ] | ||
| }, | ||
| "deploy": { | ||
| "text": ["npm install", "cdk deploy"] | ||
| }, | ||
| "testing": { | ||
| "text": [ | ||
| "Create a Cognito user: <code>aws cognito-idp admin-create-user --user-pool-id USER_POOL_ID --username user@example.com --user-attributes Name=email,Value=user@example.com Name=custom:tenantId,Value=sample-tenant --temporary-password \"TempPass1!\"</code>", | ||
| "Set a permanent password: <code>aws cognito-idp admin-set-user-password --user-pool-id USER_POOL_ID --username user@example.com --password \"MySecurePass1!\" --permanent</code>", | ||
| "Insert a tenant mapping into the DynamoDB table: <code>aws dynamodb put-item --table-name TABLE_NAME --item '{\"tenantId\": {\"S\": \"sample-tenant\"}, \"apiKey\": {\"S\": \"my-api-key-123\"}}'</code>", | ||
| "Get a token and call the API: <code>node get-token.js --user-pool-id USER_POOL_ID --client-id CLIENT_ID --username user@example.com --password \"MySecurePass1!\" --api-url https://REPLACE_WITH_API_URL/protected</code>", | ||
| "If successful, you should receive a response: <code>{ \"message\": \"Access granted\" }</code>" | ||
| ] | ||
| }, | ||
| "cleanup": { | ||
| "text": [ | ||
| "Delete the CDK stack: <code>cdk destroy</code>" | ||
| ] | ||
| }, | ||
| "authors": [ | ||
| { | ||
| "name": "Lavanya Tangutur", | ||
| "bio": "Lavanya Tangutur serves as a Senior Technical Account Manager at AWS ocused on helping customers build, deploy, and run secure, resilient, and cost-effective workloads on AWS.", | ||
| "linkedin": "www.linkedin.com/in/lavanyatangutur" | ||
| } | ||
| ] | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,71 @@ | ||
| #!/usr/bin/env node | ||
|
|
||
| // Usage: | ||
| // node get-token.js --user-pool-id <id> --client-id <id> --username <email> --password <pass> --api-url <url> | ||
| // | ||
| // Authenticates with Cognito, retrieves an ID token, and calls the API Gateway endpoint. | ||
|
|
||
| const { | ||
| CognitoIdentityProviderClient, | ||
| InitiateAuthCommand, | ||
| } = require("@aws-sdk/client-cognito-identity-provider"); | ||
| const https = require("https"); | ||
| const http = require("http"); | ||
|
|
||
| function parseArgs() { | ||
| const args = process.argv.slice(2); | ||
| const parsed = {}; | ||
| for (let i = 0; i < args.length; i += 2) { | ||
| parsed[args[i].replace(/^--/, "")] = args[i + 1]; | ||
| } | ||
| const required = ["user-pool-id", "client-id", "username", "password", "api-url"]; | ||
| for (const key of required) { | ||
| if (!parsed[key]) { | ||
| console.error(`Missing required argument: --${key}`); | ||
| process.exit(1); | ||
| } | ||
| } | ||
| return parsed; | ||
| } | ||
|
|
||
| async function getToken(clientId, username, password) { | ||
| const client = new CognitoIdentityProviderClient(); | ||
| const resp = await client.send( | ||
| new InitiateAuthCommand({ | ||
| AuthFlow: "USER_PASSWORD_AUTH", | ||
| ClientId: clientId, | ||
| AuthParameters: { USERNAME: username, PASSWORD: password }, | ||
| }) | ||
| ); | ||
| return resp.AuthenticationResult.IdToken; | ||
| } | ||
|
|
||
| function callApi(url, token) { | ||
| return new Promise((resolve, reject) => { | ||
| const mod = url.startsWith("https") ? https : http; | ||
| const req = mod.get(url, { headers: { Authorization: `Bearer ${token}` } }, (res) => { | ||
| let body = ""; | ||
| res.on("data", (chunk) => (body += chunk)); | ||
| res.on("end", () => { | ||
| console.log(`Status: ${res.statusCode}`); | ||
| try { console.log(JSON.stringify(JSON.parse(body), null, 2)); } | ||
| catch { console.log(body); } | ||
| resolve(); | ||
| }); | ||
| }); | ||
| req.on("error", reject); | ||
| }); | ||
| } | ||
|
|
||
| (async () => { | ||
| const args = parseArgs(); | ||
| try { | ||
| console.log("Authenticating with Cognito..."); | ||
| const token = await getToken(args["client-id"], args.username, args.password); | ||
| console.log("Token obtained. Calling API...\n"); | ||
| await callApi(args["api-url"], token); | ||
| } catch (err) { | ||
| console.error("Error:", err.message); | ||
| process.exit(1); | ||
| } | ||
| })(); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| { | ||
| "name": "apigw-dynamodb-apikey-cdk", | ||
| "version": "0.1.0", | ||
| "bin": { | ||
| "apigw-dynamodb-apikey-cdk": "bin/apigw-dynamodb-apikey-cdk.js" | ||
| }, | ||
| "scripts": { | ||
| "build": "tsc", | ||
| "watch": "tsc -w", | ||
| "cdk": "cdk" | ||
| }, | ||
| "devDependencies": { | ||
| "@types/node": "22.7.9", | ||
| "aws-cdk": "2.1003.0", | ||
| "esbuild": "^0.25.1", | ||
| "ts-node": "^10.9.2", | ||
| "typescript": "~5.6.3" | ||
| }, | ||
| "dependencies": { | ||
| "@aws-sdk/client-cognito-identity-provider": "^3.1034.0", | ||
| "aws-cdk-lib": "2.189.1", | ||
| "constructs": "^10.0.0" | ||
| } | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The script name implies it deploys DynamoDB, but it actually runs cdk deploy for the whole stack with a hardcoded --app override duplicating cdk.json. The README never references it, so it's an undocumented second deploy path that can drift from cdk.json. It also runs npm install redundantly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This script is not required. so removed it