API Key Authentication with API Gateway using AWS CDK

API key authentication is a common method for securing APIs by controlling access to them. It’s important to note that API keys are great for authentication, but further development should be made to ensure proper authorization at the business level. A…


This content originally appeared on DEV Community and was authored by Thomas Taylor

API key authentication is a common method for securing APIs by controlling access to them. It's important to note that API keys are great for authentication, but further development should be made to ensure proper authorization at the business level. API keys do not ensure that the correct permissions are being enforced, only that the user has access to the API.

Regardless, let's get started! In this post, we're going to touch on a few services:

  1. API Gateway with Proxy Integration
  2. Lambda Authorizer
  3. AWS CDK

Get started

Conceptually, the flow of our application will look like this:

  1. Client makes a request to API Gateway with API key
  2. The lambda authorizer determines if the API key is valid
  3. If the API key is valid, the policy is generated and the request is allowed to pass through to the lambda function
  4. If the API key is invalid, the request is denied
  5. The lambda function is invoked and returns a response

Set up the CDK project

Firstly, let's create the CDK project. I will choose TypeScript as the language, but you can choose any language you prefer. Please refer to the AWS CDK hello world documentation for other supported languages.

cdk init --language typescript

Next, let's install the necessary dependencies:

npm i

In addition, install the @types/aws-lambda package:

npm i @types/aws-lambda

Let's start by finding the primary stack file which is located under the lib directory. In my case, it's lib/api-key-gateway-stack.ts.

Edit the CDK stack

Luckily, in a few lines of code, we can spin up a full-featured API Gateway with a lambda handler using the AWS CDK.

import { Duration, Stack, StackProps } from "aws-cdk-lib";
import { Construct } from "constructs";
import { Runtime } from "aws-cdk-lib/aws-lambda";
import {
  LambdaRestApi,
  TokenAuthorizer,
  AuthorizationType,
} from "aws-cdk-lib/aws-apigateway";
import { NodejsFunction } from "aws-cdk-lib/aws-lambda-nodejs";

export class ApiKeyGatewayStack extends Stack {
  constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props);
    const fn = new NodejsFunction(this, "server", {
      entry: "bin/server.ts",
      handler: "handler",
      runtime: Runtime.NODEJS_20_X,
      timeout: Duration.minutes(1),
    });
    const auth = new NodejsFunction(this, "auth", {
      entry: "bin/auth.ts",
      handler: "handler",
      runtime: Runtime.NODEJS_20_X,
      timeout: Duration.seconds(10),
    });
    const api = new LambdaRestApi(this, "api", {
      handler: fn,
      defaultMethodOptions: {
        authorizationType: AuthorizationType.CUSTOM,
        authorizer: new TokenAuthorizer(this, "authorizer", {
          handler: auth,
        }),
      },
    });
  }
}

Let's break down the code:

  1. The first construct, NodejsFunction, is a node lambda function that will serve as our primary handler.
  2. The second construct, another NodejsFunction, is a lambda authorizer that will be used to validate the API key.
  3. The third construct, LambdaRestApi, is the API Gateway that includes the first construct wired as the proxy integration and the second construct as the authorizer.

Create the lambda handler

Located at bin/server.ts, we will create a simplistic lambda function that returns Hello, World!.

import { APIGatewayProxyEvent, APIGatewayProxyResult } from "aws-lambda";

export const handler = async (
  event: APIGatewayProxyEvent,
): Promise<APIGatewayProxyResult> => {
  return {
    statusCode: 200,
    body: JSON.stringify({ message: "Hello, World!" }),
  };
};

Create the lambda authorizer

Next, let's create the lambda authorizer located at bin/auth.ts. This lambda function will be responsible for validating the API key.

To keep it simple, we will hardcode the API key to Bearer abc123.

import { APIGatewayTokenAuthorizerEvent, Handler } from "aws-lambda";

export const handler: Handler = async (
  event: APIGatewayTokenAuthorizerEvent,
) => {
  const effect = event.authorizationToken == "Bearer abc123" ? "Allow" : "Deny";
  return {
    principalId: "abc123",
    policyDocument: {
      Version: "2012-10-17",
      Statement: [
        {
          Action: "execute-api:Invoke",
          Effect: effect,
          Resource: [event.methodArn],
        },
      ],
    },
  };
};

Deploy the stack

Now that we have our stack and lambda handlers setup, let's deploy the stack!

npx cdk deploy

Once the deployment is complete, you should see the API Gateway endpoint as an output.

Do you wish to deploy these changes (y/n)? y
ApiKeyGatewayStack: deploying... [1/1]
ApiKeyGatewayStack: creating CloudFormation changeset...

 ✅  ApiKeyGatewayStack

✨  Deployment time: 45.34s

Outputs:
ApiKeyGatewayStack.apiEndpoint9349E63C = https://x2s65m7xyd.execute-api.us-east-1.amazonaws.com/prod/
Stack ARN:
arn:aws:cloudformation:us-east-1:123456789012:stack/ApiKeyGatewayStack/0ca225a0-3727-11ef-ae64-0affd17461c9
✨  Total time: 117.33s

Test the API

Let's use curl to test the API without the API key.

curl https://<id>.execute-api.us-east-1.amazonaws.com/prod/

Output:

{"message":"Unauthorized"}

As expected, we received an unauthorized response. Now, let's test the API with the API key.

curl https://x2s65m7xyd.execute-api.us-east-1.amazonaws.com/prod/ \
    -H "Authorization: Bearer abc123"

Output:

{"message":"Hello, World!"}

Great! We have successfully created an API Gateway with a lambda authorizer using the AWS CDK. At this point, you may choose to extend the Lambda Authorizer to query another data source like DynamoDB that stores API keys.

Clean up

Lastly, let's clean up our AWS resources by destroying the stack:

npx cdk destroy

That's it! You successfully created an API Gateway with a lambda authorizer using the AWS CDK.


This content originally appeared on DEV Community and was authored by Thomas Taylor


Print Share Comment Cite Upload Translate Updates
APA

Thomas Taylor | Sciencx (2024-06-30T21:43:52+00:00) API Key Authentication with API Gateway using AWS CDK. Retrieved from https://www.scien.cx/2024/06/30/api-key-authentication-with-api-gateway-using-aws-cdk/

MLA
" » API Key Authentication with API Gateway using AWS CDK." Thomas Taylor | Sciencx - Sunday June 30, 2024, https://www.scien.cx/2024/06/30/api-key-authentication-with-api-gateway-using-aws-cdk/
HARVARD
Thomas Taylor | Sciencx Sunday June 30, 2024 » API Key Authentication with API Gateway using AWS CDK., viewed ,<https://www.scien.cx/2024/06/30/api-key-authentication-with-api-gateway-using-aws-cdk/>
VANCOUVER
Thomas Taylor | Sciencx - » API Key Authentication with API Gateway using AWS CDK. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2024/06/30/api-key-authentication-with-api-gateway-using-aws-cdk/
CHICAGO
" » API Key Authentication with API Gateway using AWS CDK." Thomas Taylor | Sciencx - Accessed . https://www.scien.cx/2024/06/30/api-key-authentication-with-api-gateway-using-aws-cdk/
IEEE
" » API Key Authentication with API Gateway using AWS CDK." Thomas Taylor | Sciencx [Online]. Available: https://www.scien.cx/2024/06/30/api-key-authentication-with-api-gateway-using-aws-cdk/. [Accessed: ]
rf:citation
» API Key Authentication with API Gateway using AWS CDK | Thomas Taylor | Sciencx | https://www.scien.cx/2024/06/30/api-key-authentication-with-api-gateway-using-aws-cdk/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.