Securing API with Cognito User Pool

SUJANSUJAN
9 min read

Hello Everyone,

In this blog, we’ll explore Amazon Cognito, a powerful AWS service for managing user authentication and access control in applications. We’ll also demonstrate how to use Amazon Cognito to secure APIs, ensuring that only authorized users can access our resources.


In this demo, we will secure an API deployed through API Gateway. By default, API Gateway does not provide authorization or security, which means anyone can access our endpoint.

We’ll use a Cognito Identity Pool to create users and configure an API that triggers a Lambda function. After successful sign-in, users will receive a token. API Gateway will validate this token to grant access to the request.

Additionally, we’ll use Postman to test our API. Postman allows us to send requests, configure details like headers, and view responses. It helps ensure that our API is properly secured and functioning as expected.


Task 1: Creating Lambda function

First, let's set up our backend server, lambda.

Search for lambda in the search box.

Click on Create a function.

Provide name for your function and select Python as runtime.

Keeping all other configurations as is, click on Create function.

We are just returning a simple hello message from lambda.

Click on Deploy.

Now, click on Test. To test our function, we have to provide a test event, for now, just provide the name for test event and click on Save.

Now, click on Test to see if the function is working as expected. We are getting the hello message.

Alright, that's the first job done.


Task 2: Creating an API

We will be creating a simple REST GET API.

Search for API Gateway in the search box.

Scroll down to REST API.

Click on Build.

Provide a name for your API and click on Create API.

Now we are at the root (/) level.

Let's create a method. Click on Create Method.

Configure Method type as GET, Integration type as Lambda function and select your created lambda function.

Click on Create method.

Click on Deploy API.

Choose New stage and provide a suitable Stage name.

Select the GET method and copy the invoke URL from your stage section.

Let's head over to the Postman.

Icon for package postman

Select GET method in Postman, paste the copied URL and click on Send.

We get the response from our lambda function.

"Hello from Lambda"


Task 3: Creating User Pool

Now, let's create a User Pool.

A User Pool is a user directory in Amazon Cognito that helps manage and authenticate users. When users sign up or sign in to your application, they interact with the user pool.

Search for Amazon Cognito in the search box.

Click on Create user pool.

For sign-in options, select Email, then click on Next.

For password policy, we can go with defaults, but I made some changes to make easier requirements for password in the Custom mode.

We decided to go for No MFA this time.

Leave the Self-service account recovery option as default.

This option configures how users will recover their account when they forget their password.

Click on Next.

Keep the Self-registration option as is. This allows new users to register for an account themselves.

Scroll down to bottom, leaving all other configurations as default.

We can choose the attributes that are required when a new user is created.

I added name as additional required attributes. You can select other attributes to add as you like.

Click on Next.

Select the Send email with Cognito option. The FROM email address shows who sent the email, while the REPLY-TO address indicates where replies will be sent, which can be different from the FROM address.

Click on Next.

Provide a suitable name for your User pool.

Tick the Use the Cognito Hosted UI box. This allows us to use Amazon Cognito's built-in user interface for authentication and sign-up, simplifying the process of integrating user sign-in and sign-up into your application.

Select the Cognito domain. We can use our custom domain, which involves configuring a custom domain name for the Cognito Hosted UI.

Essentially, this is the domain through which users will access the authentication interface for signing in or signing up.

Provide a suitable App client name. An initial app client in Amazon Cognito is essentially an identity for your application to interact with a user pool.

App Client
An app client in Amazon Cognito represents a specific application's configuration for interacting with a user pool, including settings like OAuth flows, callback URLs, and authentication methods. The term "client" reflects the application's role in consuming the authentication service. Multiple app clients can be linked to the same user pool, each tailored for different applications, allowing them to use the same user credentials while maintaining distinct configurations.

The client secret helps ensure that the client making requests to the Cognito service is indeed the one that was registered.

We are not generating for now.

We are using example.com as our callback URL for demo purpose.

Callback URLs are the addresses where users are sent after they log in or complete an authentication process. They direct users back to your app with the authentication details.

In the Advanced client app settings, we can customize the values as required.

Scroll down to the OAuth 2.0 grant types section.

OAuth 2.0 grant types are methods for obtaining access tokens to access protected resources.

Let's explore the workflows briefly.

Authorization Code Grant

  • The user logs in via the chosen authorization server (e.g., Amazon Cognito, Google Identity, or another OAuth 2.0 provider).

  • Authorization Server redirects back with an authorization code.

  • Your backend exchanges the code for tokens.

  • Use the tokens to access protected resources

Implicit Grant

  1. User logs in via the chosen authorization server.

  2. Authorization server redirects back with tokens in the URL.

  3. Use the tokens directly to access resources.

We are using Implicit Grant to obtain an access token directly from the authorization server.

Keeping all other configurations as default, click on Next.

Review your selections and click on Create user pool.

Our User pool has been created. Click on your created user pool.

Let's create a user in the Users section.

Provide email address and set password, then click on Create user.

A user has been created.


Task 4: Creating & testing API Gateway Authorizer

It's time to add Authorizers in API Gateway that will authenticate and authorize requests to our API. This ensures that only users with valid credentials can access our API resources.

Let's go to the API Gateway.

In the left panel, in Authorizers, click on Create an authorizer.

Provide a suitable name, select Cognito as Authorizer type, select your user pool and provide the header as Authorization in the Token source.

Click on Create authorizer.


Task 5: Signing in and Testing API Gateway Authorizer

To test the authorizer, we need a token value, which is obtained after a successful sign-in. Therefore, let's proceed with the sign-in process.

To view the sign-in page, we have two approaches: a direct link and a customized URL method. The direct link is simpler for basic use cases, while the customized URL method offers flexibility and customization for more complex scenarios and specific needs.

Click to get the URL

Let's implement the customized URL approach first.

There are two different URLs given, one for authorization code grant and another for implicit code grant.

We are using the second URL.


https://your_domain/login?response_type=token&client_id=your_app_client_id&redirect_uri=your_callback_url

We need to replace your_domain, your_app_client_id & your_callback_url fields with the original values.

In the App integration tab, you'll find your domain link in the Domain section.

Copy and replace it with your_domain in the URL.

In the same section, scroll to the bottom, and we'll find our App client list. Click on your App client.

Copy your Client ID and replace with your_app_client_id in the URL.

Scroll down a bit, and you'll find your allowed callback URLs that we had provided earlier.

Copy that and paste it into the above URL in your_callback_URL.

#My final URL
https://demodomain1.auth.ap-south-1.amazoncognito.com/login?response_type=token&client_id=6pv54rin409v9ngddqb932lade&redirect_uri=https://example.com

Copy and paste the complete URL into a new browser tab to access the sign-in page.

Alternatively, we can use a direct link for a more straightforward approach.

In your App client, in Hosted UI section, in the top right corner, we can see View Hosted UI.

Click on that button.

Sign in with your configured email & password.

We can also create new users using the Sign up link, as we have enabled Self-service sign-up option.

Since this is my first time signing in, I need to set up a new password. Additionally, because I set the name as a required attribute, it also appears on this page.

Click on Send.

Our sign-in was a success, and we're directed to the callback URL that we had set up.

Notice in the URL, there's a token provided by Cognito. We'll copy this token to test our Authorizer.

Copy the token and paste it into your text editor.

Only copy the #id_token value from the URL.

Paste the copied token in the Token value section and click on Test authorizer.

We got this output, and this is what's known as the decoded JWT claims, or just JWT claims. It's the data returned by the API Gateway authorizer during testing, representing various details about the user contained within the token used for authorization.

We can pass an invalid token value to observe the response we receive.


Task 6: Adding Authorizer to GET Method

Now in our GET method, we have to add the authorization in the method request.

Click on Method request & scroll a bit to see the body section.

Click on Edit.

Select your authorizer and click on Save.

After making the change, redeploy the API by clicking on Deploy API.

After deploying the API, copy the URL and open Postman to test the GET request.

Paste the URL then click on Send.

This time, we see an “Unauthorized” error.

In API Gateway, the authorizer is configured to expect the token in a header field called Authorization.

Let's copy our token again.

In the Headers section, add Authorization as the key and paste the token as the value. Then, click on Send.

Now that we have provided the token, the authorizer has validated it and granted access to the backend.

Note that if your token is not working, it may have expired. In this case, you will need to sign in again to obtain a new token.


Task 7: Conclusion

In this blog, we secured an API with Amazon Cognito and API Gateway. We set up a Lambda function, deployed a REST API, configured a Cognito User Pool, and used API Gateway Authorizers. Finally, we tested the setup with Postman.


Task 8: Clean Up

  1. Deleting API.

    Select your API and click on Delete to delete your API.

  2. Deleting Lambda function.

    Select your lambda function and in the Actions drop-down menu, click on Delete.

  3. Deleting User Pool.

    Select your User pool and click on Delete.


Alright, that sums up our today's work.

See you later in the next one!

0
Subscribe to my newsletter

Read articles from SUJAN directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

SUJAN
SUJAN

Hello people. I am here to document my learnings. See yah!!