Terraform module to create an AWS API Gateway with Cognito authentication.
The module creates the following AWS resources.
- ACM Certificate
- Wildcard certificate for specified domain, e.g.
*.demo.yegorius.com
. - Created using AWS Certificate Manager (ACM) Terraform module.
- Wildcard certificate for specified domain, e.g.
- API Gateway
- API with Lambda integration.
- Custom domain name for the API.
- This creates a CloudFront distribution with the wildcard certificate referenced above.
- The custom domain name is
api.demo.yegorius.com
. This is the actual endpoint of the API.
- An API endpoint created to test the end-to-end setup.
- Lambda
- A function that API Gateway endpoint points to.
- Cognito
- Cognito User Pool.
- Only an App Client is created. This means that this Cognito setup is only able to perform
client_credentials
authentication flow. - This type of flow is used for granting an application access to the API Gateway API or for server-to-server communication.
- Requests to the API Gateway must contain a valid
access_token
. - The only reason we need the Cognito User Pool is to host the App Client. There are no actual users or groups involved.
- Only an App Client is created. This means that this Cognito setup is only able to perform
- App Client.
- This is where the
client_id
andclient_secret
are hosted, which are essentially equivalent to a username / password pair, which need to be specified when asking Cognito for anaccess_token
.
- This is where the
- Cognito Custom Domain.
- A user-friendly Cognito DNS name which clients query in order to obtain
access_token
, e.g. https://auth.demo.yegorius.com.
- A user-friendly Cognito DNS name which clients query in order to obtain
- Resource Server.
- The URL that points to the resource that needs to be authenticated, e.g. https://api.demo.yegorius.com. In order to perform API calls to this API, the client needs the
acess_token
from Cognito.
- The URL that points to the resource that needs to be authenticated, e.g. https://api.demo.yegorius.com. In order to perform API calls to this API, the client needs the
- Cognito User Pool.
- Route53
- DNS Zone, e.g.
demo.yegorius.com
- This zone manages DNS records inside the domain name.
- In my case, I have
yegorius.com
registered on GoDaddy. There, I created NS records to point to this DNS zone in AWS.
api.demo.yegorius.com
A
record alias pointing to API Gateway's CloudFront distribution.auth.demo.yegorius.com
A
record alias pointing to Cognito's CloudFront distribution.
- DNS Zone, e.g.
Replace aws_account_id
, domain_name
, and other variables are desired.
module "api_gateway_cognito" {
source = "git::https://github.com/yegorski/terraform-aws-api-gateway-cognito.git?ref=master"
aws_account_id = "YOUR_AWS_ACCOUNT_ID"
domain_name = "demo.yegorius.com" # Zone name, with DNS delegation from your DNS provider
name = "api"
region = "us-east-1"
tags = {
Owner = "yegorski"
Environment = "production"
}
}
After applying this module, check that the API is up and is indeed behind authentication.
- Verify that the API cannot be reached without an access token.
curl -X GET \
https://api.demo.yegorius.com/v1/hello_world \
-H 'Content-Type: application/json' \
&& echo ""
Response:
{"message":"Unauthorized"}
- Verify Cognito grants a valid access token.
curl -X POST \
'https://auth.demo.yegorius.com/oauth2/token?grant_type=client_credentials' \
-H 'Authorization: Basic base64(client_id:client_secret)' \
-H 'Content-Type: application/x-www-form-urlencoded' \
&& echo ""
Response:
{
"access_token": "<token>",
"expires_in": 3600,
"token_type": "Bearer"
}
- Verify that the API can be reached with a valid access token.
curl -X GET \
https://api.demo.yegorius.com/v1/hello_world \
-H 'Authorization: Bearer <token>' \
-H 'Content-Type: application/json' \
&& echo ""
Response:
"Hello World!"