Building a Secure API Gateway using Amazon Cognito via Terraform!
Journey: 📊 Community Builder 📊
Subject matter: Building on AWS
Task: Building a Secure API Gateway using Amazon Cognito via Terraform!
Using the 6 Pillars of the AWS Well-Architected Framework, Operational Excellence, Security, and Reliability will be achieved in this build.
Last week, I used the AWS Management Console to build a secure REST API project.
This week, I used Terraform to build a similar environment!
When creating an API, you can use Amazon Cognito - specifically a User Pool - to control who has access to the API in the API Gateway.
To do this, you need to create a Cognito authoriser and then link your API method to the authoriser.
Once an authenticated user logs in, they obtain an ID token and are able to call the API using the token.
For this project, I am using Postman to call my API and will show the various responses you receive with and without an ID/Access token.
Resource credit: This IaC architecture was created using guidance from Mattia Mazzari on Medium Here.
I did have some problems with the build, which I will document and post about soon.
What did I use to build this environment?
- Visual Studio Code platform
- Terraform
- AWS CLI
- AWS Management Console
- Postman API Platform
- IAM and JSON
- CORS
What is built?
- An API Gateway [REST API]
- Cognito User Pool with Cognito Hosted UI
- Cognito Users
- Cognito Authoriser
- AWS Lambda function
- Amazon DynamoDB table
More information on Cognito Authorisers can be found here: https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-integrate-with-cognito.html
More information on CORS can be found here: https://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-cors.html
More information on CloudWatch logging for REST APIs can be found here: https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-logging.html#set-up-access-logging-permissions
In this task, I created a REST API Gateway, protected by Cognito, and hosted a Lambda function to perform CRUD operations on a DynamoDB table.
After receiving my API invoke URL, I was then able to call the publically accessible URL in the Postman API platform successfully.
I then enabled the Cognito User Pool as the method authoriser and redeployed the environment. This automatically created a new, verified user and updated my API method.
Calls to my invoke URL via Postman now failed as expected, I needed an authorised ID token!
I returned to my AWS CLI and requested an authentication token.
I tested the ID token issued against the Authoriser and confirmed a successful authentication “200 response”.
I then added the authorisation token to the Postman header, added some data to POST to my DynamoDB table, and issued the command… success! Calls to my API were now succeeding again with a 200 response and viewable content in the API platform!
When returning to view my DynamoDB table, the data I had POST to my Invoke URL via Postman now existed!
This was a great learning experience in API Gateway and how Cognito can be used to create reliable and secure environments!
Some of the highlights…
Terraform files:
Terraform apply:
S3 Bucket:
Lambda Function:
Lambda Trigger:
Lambda CW:
API Gateway config:
API Gateway Stages:
API Authoriser:
DynamoDB Table:
Cognito User Pool:
New user:
CloudWatch logs:
API token request:
API token test:
Recipe to add:
Postman API failing: [token not yet added to header]
Postman API successful: [token has been added to header]
DynamoDB Check:
Terraform destroy:
My interpretation of the architecture:
I hope you have enjoyed the article!