API Gateway Custom Authorization with Lambda, DynamoDB and CloudFormation
API Gateway provides an HTTP API endpoint that is fully configurable. You define the HTTP resources (like
/user), the HTTP methods on that resources (like
DELETE, …) and the integration (e.g. Lambda function) that should be called to process the request. A Lambda function can then run whatever logic is needed to answer the request. The Lambda function returns its result to the API Gateway. The API Gateway responds to the caller. The following figure demonstrates this flow.
You could include the authentication and authorization logic into the Lambda function that handles the request. But you can also separate concerns, make use of API Gateway caching mechanism, and go for Custom Authorization. API Gateway will invoke another Lambda function (Auth Lambda Function) for the first request and caches that result for a configurable duration. Caching will reduce the overhead (latency and DynamoDB charges) for authentication and authorization to a minimum.
You can use whatever logic you like to decide if a request is allowed or not. In this blog post, I will implement an API token mechanism. All HTTP requests from clients must pass an
Authorization: xyz header. The Auth Lambda Function will take this token to query a DynamoDB table. The request is allowed or denied depending on if the query matches.
As usual in this blog, I will use CloudFormation to setup all the needed resources.
The first thing you need is an API Gateway.
With the logical group in place, you can continue to add all the necessary parts to your API.
The code for the Auth Lambda Function is responsible for looking up the token. The
API Gateway expects that we respond in the following way:
A simple implementation looks like this:
var AWS = require('aws-sdk');
Let’s turn this into a CloudFormation template, including the DynamoDB table for the tokens and the IAM Role with permissions to talk to DynamoDB.
Now we have our
Auth Lambda Function. It’s time to integrate with our API Gateway.
The resource that we need is called an Authorizer. The Authorizer defines:
- The Lambda function to execute
- The header field that is passed to the Lambda function including a RegEx to validate the input value
- The TTL of the result
See how this translates to CloudFormation:
Now we need to define an HTTP Resource with an HTTP method protected by our Custom Authorization.
We will describe a
PUT /user endpoint that takes JSON as input in the following form:
To make all this work we need to setup a Lambda function with the permission to be invoked by our API Gateway. We also need a model for our user JSON structure, the
/user resource itself and the
Now you can use a Lambda function to protect your REST API built with API Gateway.
With API Gateway you can configure a RESTful API. Authorizers can be used to implement Custom Authorization with a Lambda function. The API Gateway will invoke the Auth Lambda Function to check if an HTTP request is allowed. You can use DynamoDB or other databases to store the necessary auth information. As long as the logic can run inside a Lambda function, you can do whatever you want.