API Gateway API Keys using the Serverless Framework
API Gateway API Keys with the Serverless Framework
tl;dr
We can create API Keys specifically for our API Gateway endpoints that enforce a usage policy. We can enforce service-to-service authorization with this method, but this is a great way to monetize our APIs! Normally we would have a bearer token or a JWT token that we would use to authenticate our requests. However, API Keys are a great way to enforce authentication to our API outside of the context that someone is signed in to our application.
Code for this example can be found on GitHub here
Setup
We'll be using the Serverless Framework to deploy our API Gateway and to create our API Keys. If you don't have your AWS environment setup, you can follow the guide here at the Serverless Framework docs.
Initialize Project with Serverless Framework
Let's use npx so we don't have to install the serverless framework globally
$ npx serverless
And answer the prompts to create a new project.
? What do you want to make? AWS - Node.js - Starter
? What do you want to call this project? api-key
✔ Project successfully created in api-key folder
? What org do you want to add this service to? [Skip]
? Do you want to deploy now? No
Installing Serverless Framework as a Dev Dependency
We will be using npx to run the serverless framework commands in this guide.
In a production app, it is wise to install the serverless framework as a dev dependency,
and use npm run or yarn to run serverless commands.
Modify the serverless.yml
Running the npx serverless command created a simple serverless.yml file for us that should
look like this.
service: api-key
frameworkVersion: '3'
provider:
name: aws
runtime: nodejs14.x # possibly a newer version
functions:
hello:
handler: handler.hello
All we need to do for this example is to add a few lines. Let's add them.
Http Event
We have to add an http event to our hello function so that we can create an API Gateway endpoint.
This cannot be a new httpApi event since that will use the newer
HTTP API Gateway
and we need to use classic REST API Gateway
to use API Keys. See the difference between the two here
functions:
hello:
handler: handler.hello
events:
- http: # not httpApi
path: hello
method: get
private: true
API Keys
The quickest way to create an API Key is to add the apiKeys property to the provider object in our serverless.yml.
provider:
name: aws
runtime: nodejs14.x
apiKeys:
- tyler-tutorial-api-key
Deploy
Now we can deploy our API from our command line by running the following.
$ npx serverless deploy
Then we wait... Once the deployment is done, we will get an output to our console with the API Gateway endpoint and our api keys.
api keys: tyler-tutorial-api-key: Ai9VYOx...
endpoint: GET - https://3jkljz8892.execute-api.us-east-1.amazonaws.com/dev/hello
Testing our API
Please feel free to use a client like Postman or Insomnia to test our API.
But for this example, we will use curl like a command line hero.
$ curl https://3jkljz8892.execute-api.us-east-1.amazonaws.com/dev/hello
We get back the message
{"message":"Forbidden"}%
Hooray! It doesn't work! We need to add our API Key as a x-api-key header to the request.
$ curl https://3jkljz8892.execute-api.us-east-1.amazonaws.com/dev/hello \
-H "x-api-key: Ai9VYOx..."
Now we get back the JSON we expect from our hello function.
{
"message": "Go Serverless v3.0! Your function executed successfully!",
"input": {
"resource": "/hello",
"path": "/hello",
"httpMethod": "GET",
"headers": {
"Accept": "*/*",
...
"x-api-key": "Ai9VYOx...",
...
Conclusion
We went through a little example of how to lock down our API endpoints by creating API Keys.
While this is a great way to make a single (or several) API Gateway API Keys for a service-to-service authorization, it's not a great way to make hundreds or thousands of API Keys for an API we would like to monetize.
To do that we need to programatically create API Keys and assign them to our API Gateway endpoints. Ideally with a Usage Plan to rate limit and enforce a quota limit. We will cover that in a future article.
Resources
Full serverless.yml file
service: api-key
frameworkVersion: '3'
provider:
name: aws
runtime: nodejs14.x
apiGateway:
apiKeys:
- tyler-tutorial-api-key
# extra not included in the tutorial
usagePlan:
quota:
limit: 50
offset: 2
period: MONTH
throttle:
burstLimit: 20
rateLimit: 10
functions:
hello:
handler: handler.hello
events:
- http:
path: hello
method: get
private: true