In this showcase were going to use the following:

  • Recently released, still in beta, HTTP API (ApiGatewayV2)
  • Auth0 to handle authentication for the routes
  • CloudFormation to create the resources and provide a template to build from

Setup Auth0

Setup your authentication service, I'm using Auth0, use any provider you like as long as they support JWT.

Auth0 website landing page
Auth0 website or use another provider that supports JWT

After creating an account at Auth0, navigate to APIs on the left. Then click "Create API"

Auth0 APIs dashboard
Auth0 "Create API"

Fill out the details in the popup that appears. After saving you should see the following. Take note of the "Identifier", that is your audience that will be used later.

Auth0 API Details
Auth0 API Details

Then view the details of the application that was created automatically for your API.

Auth0 Machine to Machine Test Application Details
Auth0 machine to machine application details

Take note of the "Domain", this is your Issuer URI that will be used later. For Auth0, this is https://<TENANT_ID>.auth0.com/.

The CloudFormation Stack

Now that your authentication provider is ready and you've noted the audience and issuer URI, you can launch the CloudFormation stack.

You will be asked to provide the Audience and Issuer URI that you should have from setting up the authentication provider above.

AWS CloudFormation Stack Parameters
CloudFormation template audience and issuer URI parameters
AWS CloudFormation Designer with API Gateway, Lambda and Custom Authorizer
CloudFormation diagram of API Gateway HTTP (beta) with custom authorizer using Auth0 and a test route with lambda integration

CloudFormation will create the following resources:

  • API Gateway V2 HTTP (beta)
  • $default deployment stage
  • Custom authorizer using your issuer and audience from Auth0
  • Testing route /test
  • Testing route integration using AWS Lambda
  • Testing AWS Lambda function
  • Testing function IAM Role to allow logging to CloudWatch
  • IAM Role to allow API Gateway to invoke the integration Lambda functions

There are 2 important items to note that cost me a lot of time debugging.

Pitfall #1: Ensure API Gateway has Proper Permissions

You must use an Invoke IAM Role on your route integration or add the appropriate Lambda resource permissions to allow API Gateway to invoke your Lambda function. Incorrect permissions will cause API Gateway to return 500 errors.

The template uses this method, I prefer the invoke IAM Role because it's easier to manage.

Amazon API Gateway Integration Invoke IAM Role
API Gateway integration invoke IAM Role

If not using an Invoke IAM Role, you must ensure the Lambda resource permissions allow your API Gateway to invoke the function. If you're creating the integration in the console, this is done automatically. Note, the template does not use this method.

API Gateway Integration Lambda Resource Permissions
API Gateway integration Lambda resource permissions

Pitfall #2: Ensure Proper Lambda Handler Response

If your API Gateway and Lambda permissions are correct but you're still getting 500s, ensure the Lambda function response is correct.

When using the nodejs Lambda runtime, take care to use either async or callback in the handler, see https://docs.aws.amazon.com/lambda/latest/dg/nodejs-prog-model-handler.html.

exports.handler = async function(event, context) {
  const response = {
    statusCode: 200,
    body: JSON.stringify('Hello from Lambda!')
  };
  return response;
}

Also ensure the response is JSON with a statusCode and string body (if applicable), see https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-create-api-as-simple-proxy-for-lambda.html#api-gateway-proxy-integration-create-lambda-backend.

Testing the API

Once the stack is complete, you can send a request to the test route /test. To get an access token, navigate to your Auth0 API and go to "Test". See the screenshot below, run the command and copy the access token.

Auth0 getting an access token for testing

With the access token, send a GET request to the test route and include the Authorization header but DO NOT include "Bearer" before the token.

Pitfall #3: Don't Include Bearer in the Authorization Header

When adding the authorization header, DO NOT include "Bearer" before the token string, see https://forums.aws.amazon.com/thread.jspa?threadID=240420. Your authorization header should look like this:

{
  "Authorization": "eja123..."
}

You will be sending a request to something like this URL:

https://tju42ljd6a.execute-api.us-west-2.amazonaws.com/test

AWS API Gateway with invoke URL

Wrapping Up

The CloudFormation stack you created is a good starting point to create more routes with Lambda integrations. Any changes you make should be done through the CloudFormation template to avoid drift and manual changes.

There is no passive cost for creating and running the stack. You pay for usage of API Gateway and Lambda.


About Me

I'm a software engineer and hold a Masters degree in Mechanical and Aerospace Engineering from the University of California, Irvine. My broad background helps me adapt and stay passionate about finding pragmatic solutions to complicated problems. Let's chat ackhatib@gmail.com.