AWS Cognito Basics – User Pools

Introduction

Amazon Cognito is a robust user directory service that handles user registration, authentication, account recovery & other operations for easy and fast web/mobile application development.

This service helps you manage your authentication, authorization and user management functions so that you can focus on your application management rather than managing users and authentication.

AWS Cognito provides two kinds of solutions based on the nature of the authentication:

  • User Pools
    • User pools are user directories that provide sign-up and sign-in options for your app users.
    • They are used for managing account and permissions for our applications.
  • Identity Pools
    • Identity pools enable you to grant your users access to other AWS services.
    • They are used for managing permissions for AWS services (e.g. S3 storage, EC2 instances etc.)

AWS Cognito is very flexible and can be used for different use cases and application types, so we will take a step by step approach to see how to handle various use cases and this way it will be easier to manage complexity.

In this post, we will be covering some basics of AWS Cognito. We’ll be starting with User Pools and learn some basic terminologies.

Following are few of the tasks, we will be performing in this post:

  • Create a User Pool
  • Configure a Client App and Authorization Flows
  • User Pools Auth-API Endpoints
  • Demo Hosted UI to create and manage users/groups

Next, we’ll create a user pool, add and configure client application’s settings and some other basics.

User Pool

User Pools are a multi-tenant LDAP-like user repository combined with an OAuth2 and OpenID Connect interface. User Pools also provide federation services using SAML, OpenID Connect, Facebook, Google+, and Amazon. More options are being added dynamically.

AWS Cognito uses JSON Web Tokens (JWTs) for the OAuth2 Access Tokens, OIDC ID Tokens, and OIDC Refresh Tokens.

Cognito User pools provides workflow triggers for use with AWS Lambda. So if you want to have a function execute whenever a new user sign-up etc. you can do that easily.

AWS Cognito is also integrated with AWS Lambda functions service (The catch is that lambdas are being triggered from the AWS API Gateway, which is the most common case).

User pools provide:

  • Sign-up and sign-in services.
  • A built-in, customizable web UI to sign in users.
  • Social sign-in with Facebook, Google, Login with Amazon, and Sign in with Apple, and through SAML and OIDC identity providers from your user pool.
  • User directory management and user profiles.
  • Security features such as multi-factor authentication (MFA), checks for compromised credentials, account takeover protection, and phone and email verification.
  • Customized workflows and user migration through AWS Lambda triggers.

Creating a User Pool using AWS Cognito

Lets start by creating a User Pool AWS Cognito Web Console.

AWS Console will start a wizard which you can configure as per your requirements. There are good descriptions to various steps available.

We have the options to choose how the users will login, which attributes are required, password strength etc. Note that you can not change attributes and some settings, once pool is created.

These configurations are very basic. Here in this setting, only email is required attributed. MFA is optional with (OTP) and User signups are allowed.

These configurations are simple and you can adjust those as per your requirements. I will not go into those details and here will show you just the created user pool:

App Clients

After you create a user pool, you can create an app to use the built-in webpages for signing up and signing in your users.

App clients are what Cognito uses to determine which application the user coming from and whether they are allowed to access it or not.

You can add a client using cognito console. Following picture shows configurations for a web client:

(Note, I unchecked the Generate client secret option, as this option is not applicable for public client type of application.

As you can see that different Auth Flows configurations are possible. Now those depends on your particular use cases. you can select the ones which suite better to your application.

Following is some detail about Auth Flows Configurations:

  • ALLOW_ADMIN_USER_PASSWORD_AUTH
    • Used for server-to-server authentication, when we want our server to access some resources to cognito and we would do it by providing a username and password without have to get a token via the UI, so there is no user interaction.
  • ALLOW_CUSTOM_AUTH
    • Enable us using lambda triggers for custom authentication. use to intercept user request to authenticate and send the custom challenges.
  • ALLOW_USER_PASSWORD_AUTH
    • We send a username/password as a request to Cognito. This flow is not very secure.
  • ALLOW_USER_SRP_AUTH
    • This is the one we are going to use.
  • ENABLE REFRESH_TOKEN_AUTH
    • We are going to use this flow as well.

Don’t worry, if these are seems cryptic. These will become familiar once you start using these.

Here is our app client is created:

Attribute Read/Write Permissions

We also need to set attribute read/write permissions. Click the Show Details button shown above and then select which attributes, this client will be allowed to read/write (In most cases, you would want to select them all)

So far, we have a User Pool and We also have created an App Client and configure it with auth flows. Next, we will configure App Integration section.

App Client Settings

App Client Settings is available under App Integration section on the web console. In this section, we start by defining which Identity Provider this app can use and some other settings:

Here is some information about Allowed OAuth Flows:

Authorization code grant

This redirects to IDP. User login at IDP level then redirect to Callback URL where we can use a code return to exchange it for a token. A custom application is required on the backend to exchange the authorization code for user pool tokens.

Implicit Grant

Allows us to call Cognito and obtain an Access-Token directly without having to redirect to cognito. You can use this flow when there’s no backend available to exchange an authorization code for tokens. It’s also helpful for debugging tokens.

Client Credentials

Used for machine-to-machine authentication where our API can request an access token using the client’s credentials.

Allowed OAuth Scopes

Choose what scopes our clients have permissions to access. Unless you specifically want to exclude one, select the check boxes for all of the Allowed OAuth scopes.

phone and email are self explanatory.

openid: return all user attributes in the ID-Token that we recieved when we login.

auth.congnito.signin.user.admin: grants the user access to update and verifying user attributes.

profile: grant access to user attributes that are readable by the client.

Click Save Changes once you are done with the selections.

Hosted UI and Domain Name

We’ll cover Hosted UI a little bit later. But to enable it, we first need to choose a domain name:

We can choose a domain name as shown below:

With this, if we go back to App Client setting and will notice that hosted UI is now available. You can click the link to launch it and see how it looks.

There are options for UI customization and Hosted UI is a good option in the start, as it allows you to focus on more important functionality and if Hosted UI is not fulfilling your requirements, then you can write your own UI for those purposes (we will do this in a later post).

Amazon Cognito user pools Auth API

Once a domain has been configured for your user pool, Amazon Cognito hosts an authentication server where you can add sign-up and sign-in webpages to your app.

Along with that certain endpoints are also setup:

  • AUTHORIZATION endpoint
  • TOKEN endpoint
  • USERINFO endpoint
  • LOGIN endpoint
  • LOGOUT endpoint
  • REVOCATION endpoint

We will learn more about these in upcoming post. You will notice that the hostname follows a general pattern of:

https://USER-POOL-NAME.REGION.amazonaws.com

More information about User Pool endpoints are available here.

There are also OIDC Discovery Endpoints:

Discovery endpoints structure:


https://cognito-idp.REGION.amazonaws.com/USER-POOL-ID

OIDC Discovery Endpoint

https://cognito-idp.eu-central-1.amazonaws.com/eu-central-1_BGOou5Rwx/.well-known/openid-configuration

JWKS Endpoint

https://cognito-idp.eu-central-1.amazonaws.com/eu-central-1_BGOou5Rwx/.well-known/jwks.json

We will use these endpoints in later posts. For now, if you like, you can visit these endpoints to see what kind of information is being returned.

Adding a User/Group using Console

We have ability to add users/groups from the console. Lets add a new user/group and add user to group:

Here is the add user dialog:

Similar way, add a group:

and then from user details area, added user to this group:

and from group details page, we can see that user is now added to the admin group:

As I created this User, Following is the email received from AWS Congnito:

Sign-In using Hosted UI

Just to verify the configurations. I then opened up the Hosted UI page and entered the credentials:

When clicked the Sign in button, the following change password UI shows up:

I’ve entered the new password and click the Send button and was redirected to following page:

and this is the same Callback URL, we setup earlier during User Pool Configurations:

We will now end this post at this point and in later post pick-up from here. We will later cover, how to integrate AWS Cognito in our client-applications, how to use it with API Gateway, how to protect our resources and the user management and permissions.

Summary

AWS Cognito lets you add user sign-up, sign-in and access control to your web and mobile applications quickly and easily.

In this post, we got a basic overview of AWS Cognito. We setup a User Pools, configure Client App and Authorization flows. We also created a user, group and added user to group using Hosted UI feature directly from AWS Console.

We have now a base setup and in later posts, we will build on top of this learning.

Let me know if you have some comments or questions. Till next time, Happy Coding.