AWS API Gateway 101: Create an API with Python, Cognito, and Serverless

Jean-Gaël Choppe
Dec 2, 2019 · 13 min read

The goal of this tutorial is to return a “Hello World” if you connect and authenticate successfully to our 100% serverless application. You will discover in this article how to take advantage of AWS Cognito, deploy an API Gateway and a few lambda functions through the serverless.com framework.

Installation

The first step is to install Serverless, Python3 & Boto3 (to allow use of Cognito with Python), Postman, and AWS CLI.

NPM

NPM (Node Package Manager) needs to be installed before installing Serverless. NPM is installed with Node.js. The following tutorial guides you through the installation: https://www.ostechnix.com/install-node-js-linux/

Serverless

Serverless is used to deploy the API Gateway and other resources such as Cognito and the lambdas that are created using Python3. The tutorial on how to install Serverless can be found here: https://serverless.com/framework/docs/getting-started/

Python3

We have used Python3 in this example to create lambda functions. Other languages such as Javascript or Golang can be used for this as well. The following guide walks you through the installation and setup of Python3: https://realpython.com/installing-python/

You’ll have to execute a command line that works for the OS being used. For example, on Arch Linux we have to execute the following:

Once Python3 has been installed, you can use the following command to check whether Python has been successfully downloaded:

Boto3

Boto3 is a Software Development Kit (SDK) that enables Python developers to create, configure, and manage AWS services such as EC2 and S3. For Boto3, you’ll need a PIP (which is generally installed with Python). You can use the following command to check if the PIP exists:

If an error is returned, you will have to install it. Here is a guide that walks you through this process: https://pip.pypa.io/en/stable/installing/

Once you have installed the PIP, execute the following command:

Postman

Postman is an easy-to-use software that helps build, test, and modify APIs. Postman has the ability to make various types of HTTP requests to an API. Here is a link to Postman’s website where the platform can be downloaded: https://www.getpostman.com/

AWS CLI

AWS CLI (Command Line Interface) must also be installed to manage your AWS services and to receive Cognito tokens. The following tutorial details how to install it: https://docs.aws.amazon.com/cli/latest/userguide/install-linux-al2017.html

Serverless — Simple Configuration

Begin by configuring Serverless. Serverless is a tool that can be used with AWS to deploy resources and APIs. If you want to investigate serverless in more detail here is the documentation: https://serverless.com/framework/docs/providers/aws/

Create a Serverless project

The following command (in Python) creates a Serverless project:

Based on what we’ve entered, a folder called ‘trackit’ (name of the project) is created. This newly created ‘trackit’ folder should have a Python file (which you can remove for now) and a file called serverless.yaml; this is your Serverless configuration file.

Simple configuration

Once the project is created, the serverless.yaml file needs to be configured. Here is a simple example of a Serverless configuration:

As you can see in the code above, the name entered after service: will be the name of your API Gateway.

You must also set up the name of your provider. In this example, we’re using AWS with Serverless so the name of the provider is AWS. We’re using Python 3.7 as our runtime (our lambdas will use Python 3.7).

You also have to choose your region; the following guide by AWS on Regions and Availability zones will provide you with some guidance: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html)

In this example, we’re looking to deploy in Oregon so the region we’ve selected is us-west-2 and we set a timeout of 60 seconds (you might want more or less based on your requirements).

We then create a simple function called endpoint_test which will be located in the test.py file. We have decided to call this lambda test_trackit. We put under functions: the lambda function test_trackit with the handler test.endpoint_test (test is the name of the file and endpoint_test the name of the function in the file). We designed this function to use an http event; the path to execute the lambda will be /test and the request method will be get.

Lambdas in Python

Next, we create the lambda functions in Python which will serve as endpoints of the API Gateway.

To test if the API Gateway is working correctly, we start by creating a test function. To do this, we begin by creating a file called test with a function called endpoint_test which is going to be our handler. If the set up is done correctly the endpoint will return the appropriate JSON file.

As you can see in the code, endpoint_test receives two arguments:

  • event
  • context

We are not going to use the specific arguments in this function since they are not within the scope of this tutorial. However, these arguments are very important if you intend to more fully utilize the endpoint functions.

Deployment with Serverless

Once all the previous steps have been completed, you can deploy your first lambda function and API Gateway with Serverless on AWS. This deployment will create an API Gateway with the service name that you’ve chosen (trackit, in this example) and a lambda function in the following format: [service name]-…-[lambda name]

To deploy your configuration, you can execute the following command in the Serverless config directory:

Once this is done, the next step is to check if the API Gateway works on AWS. The AWS API Gateway Dashboard provides us with the link to the API.

AWS Tools

You need to be connected to your AWS Console for the following steps.

AWS API Gateway Dashboard

To access the API Gateway Dashboard in AWS:

API Gateway → Your API Gateway NAME → Dashboard.

In the API Gateway Dashboard, you will find the link in a blue section at the top that says ‘Invoke this API at [Link]

Logs with Cloudwatch

You can also access Cloudwatch to see the logs of your lambda functions and the logs of the API Gateway as well. You can search for “/aws/lambda/” or “/aws/api-gateway/”. This is an easy way to find your lambda functions and your API Gateway, especially if you have many logs.

Lambda in AWS

You can find your lambdas in the AWS Lambda service in the AWS Console.

Test endpoints with Postman

Postman allows you to check whether your endpoints work. Once you open Postman, you will have something that looks like this:

For this deployment, we have selected GET as the request method. The request URL is in the link that we’ve acquired from the API Gateway Dashboard.

Once you click on the send button Postman will make a request to your API Gateway and execute the lambda function (endpoint). If everything has been set up correctly you will receive a response to the request. (See screenshot below)

Amazon Cognito

Amazon Cognito is a service that provides authentication, authorization, and user management for web and mobile applications.

Cognito with Serverless

We can set up Cognito on AWS directly, but it is simpler to create it from the Serverless deployment because we won’t need to get all the Amazon Resource Names (ARNs) for the configuration.

Create a Cognito UserPool with serverless

For this step, open your serverless config file again. First, you need to create a user pool. Under the provider module, create a resources module which contains Resources and a CognitoUserPool

The name we’ve chosen for the user pool in this example is trackittest1 but it’s up to you to choose a name for your user pool. You can also enter and modify additional details like the PasswordPolicy. For instance, if you want the password to have a minimum length of 8 characters, you can change the MinimumLength argument’s value to 8.

Create a Cognito UserPoolClient with serverless

A user pool client is used to connect to the UserPool. Directly below your CognitoUserPool configuration (always under resources), include your CognitoUserPoolClient configuration:

In Properties, you can choose the name of the client and you can link the client to a user pool. Here, we link the client to CognitoUserPool which is the user pool we created in the previous step.

Create an authorization to the API Gateway

Now that we have created our user pool and user pool client, we need to configure the authorization for the API Gateway because certain functions will need an authorized token to be executed.

Under CognitoUserPoolClient you will have to write something like this:

DependsOn relates to the API the authorization will depend on. We enter ApiGatewayRestApi here which is the API automatically created by Serverless when we deploy our Resources. We add IdentitySource: method.request.header.Authorization because in the Headers section in Postman the value of the Authorization key needs to be the authorization token. (See screenshot below)

Your first endpoint function with authorization

Now you just need to create an endpoint that will require an authorized token. But first, let’s create a user in Cognito.

Create a user in Cognito

You need to deploy Cognito with Serverless with the chosen configuration. This will create a User Pool and a User Pool Client.

In the AWS Console, go to the Cognito service and click on User Pools. Select the user pool that you have deployed (trackittest1 in this example). Click on ‘Users and groups’ which you will find in the menu on the left.

Click on Create user to create a user. (Don’t forget the parameters you’ve selected in the Serverless console such as minimum password length.)

Click on Create user when you are done.

We now have to initiate the user and change the password. Go to your terminal and create a file called auth.json (create it in another folder than the one you are deploying with Serverless):

Note that you will have to replace $username and $password variables under AuthParameters based on the user profile you’ve created. In order to find the UserPoolId: in the AWS console go to Cognito → Manage User Pools → Your User Pool Name.

To get the App Client Id, click on App Clients in the menu on the left.

You also need to click on Show Details and click on the checkbox: Enable sign-in API for server-based authentication (ADMIN_NO_SRP_AUTH):

(If you don’t click the checkbox you won’t be able to make any API requests with a token).

You can now execute this command in your terminal (where the auth.json file is located):

You will have an output like this:

$session” is the key for which you will need to change the password. To change the password, copy “$session” and replace $session with it. (See screenshot below)

Once you’ve done that use this user to test your request to the API. This request will need authorization and you’ll have to execute the following command to get an IdToken:

Note: Don’t forget to update your password in the auth.json file! If you don’t you will receive an error.

You will have something like this:

Whenever you need to generate an IdToken, you need to execute the previous command. Note that the IdToken is available only for a short period of time.

Create an endpoint which needs authorization with Serverless

Create the function in Python

For this example, we have decided to create our new function in the same file that we’ve used for the other endpoint. Cognito simplifies the process of creating a function that needs an authorized token. All you need to do is create a normal function and edit the Serverless config to deploy the function.

In Python:

As you can see, we have created a new function (endpoint_test_auth) that returns a response with the status 200 along with the text “Hello world”. Now we have to edit the serverless config and add the new endpoint:

The process is quite similar to what we did with the other endpoint. The only new thing here is we need to add an authorizer so the API Gateway knows that there’s an authorized token.

The authorizerId is in ApiGatewayAuthorizer:

You can now deploy with:

Go to the API Gateway in your AWS Console and you’ll find both the functions you created in the Resources section:

Test your endpoint which needs authorization with Postman

On Postman, as we did before, you’ll have to put your request URL using the correct request method as seen in the screenshot below:

Under ‘Key’, assign a name (‘Authorization’, for instance) to your key and under ‘Value’, enter your new IdToken which you generated with auth.json. Then click on send.

The successful output will be the following:

Note: You should attempt it without the authorization values in the headers and make a request. If the authorization has been set up correctly, the response to the request will be an error:

How much does it cost?

With this specific API Gateway, the cost for 1,000,000 “Hello world”s is $3.50. It’s important to note that it was not an easy task to exceed the free AWS plan to end up with this cost!

An Indispensable, Easy-To-Deploy, and Cost-Effective Solution

API Gateways are not only practically universal in terms of their applicability to different infrastructure workflows but also quite hard to do without. API Gateways apply to anyone who wants to create a modern software stack that’s built to seamlessly accommodate future modifications and integrations.

One of the primary appeals of API Gateways is the ease with which one can deploy them. The creation of the API presented in this article should take no more than an hour. Most of the heavy lifting is done by AWS and the only coding knowledge necessary is that required for the creation of relatively simple lambda functions.

In order to reproduce the features of an API in the absence of an API Gateway like the one we’ve presented in this article, one would have to set up an EC2 instance and create an API in Python with a common framework like Flask. If you think this a daunting task, wait till you reach the point where you have to come up with an alternative for Cognito!

Even for a quick project like this one, it would take at least a few hours to set up Flask. Despite such efforts the overall cost of the solution would become an issue due to the maintenance costs and SysOps efforts that go hand in hand with EC2 instances. Deploying an API Gateway like the one we’ve discussed in this article is not just simple and efficient, but also cost-effective. The reason for this is twofold: first, with AWS you only pay for what you use; and second, you practically eliminate all human costs by implementing an API Gateway using the steps outlined in this article.

About TrackIt

TrackIt is an Amazon Web Services Advanced Consulting Partner specializing in cloud management, consulting and software development solutions based in Venice, CA.

We specialize in Modern Software Development; DevOps, Infrastructure-As-Code, Serverless, CI/CD and Containerization with specialized expertise in Media & Entertainment workflows, High-Performance Computing environments and data storage.

Here is the GitHub repository of the tutorial: https://github.com/trackit/aws-api-gateway-cognito

TrackIt

TrackIt AWS DevOps Engineering Blog

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store