Amazon Web Service platform’s Identity and Access Management offering consists of two major components — Cognito User Pool and Cognito Identity Pool. In this article we deep dive into Cognito User Pool and find out what it is, how to use it and when to use it.
Cognito User Pool
Cognito user pool — at its core — is a “user repository” with very rich user registration and authentication capabilities. This is where you can define a schema of the “USER” entity of your application / solution. When you are setting up a Cognito user pool and defining how users are going to identify themselves in you application, you have two main options to choose from as shown below:
Username — This allows user to set an alphanumeric string which they can then use as their identifier for the application that uses this Cognito user pool as its user repository. If you capture user’s email and mobile number during registration, Cognito provides an capability to verify these for you. Once verified and if you have set the options “Also allow sign in with verified email address” and “Also allow sign in with verified phone number” — users will also be able to use their verified email or phone number to identify themselves and login. The last options allows your users to change their user name.
Email address or phone number — This is allows users to either use a verified e-mail or phone number as their identifiers. As an implementer you can decide which one it will be or if you select the last option above (Allow both email addresses and phone numbers (users can choose one)) then you will let the user decide if they want to use email address or phone number as their identity.
One very important setting of the user pool is the case sensitivity of the identity. It is recommended that you make the user’s identifier case insensitive. Remember once the user pool is created — There is no way to change any of its core configurations like user’s identity, case sensitivity of user identity. So be careful about how you configure the user pool.
Since it is a user repository — obviously it offers capability to store user’s attributes. Out of the box following attributes can be stored.
You can decide which attributes are mandatory and which are optional. Based on this configuration, while registering user in Cognito user pool you will need to pass all attributes marked as “Required”. If you want to store any attribute other than the ones listed above — You have the capability to define custom attributes.
The custom attribute can either be “String” or “Number” type. You can also define the min / max length / value for such custom attribute and if the attribute is mutable or not.
Being a user repository, the most important aspect is management of user’s password. While setting up the user pool, you can define characteristics of user’s password. Following are the options you can select from to define the password strength.
If you are defining user pool for a consumer facing application, you should set the user pool to allow user’s to sign themselves up. On the other hand if you want a tighter control over creation of users then you can set it up such that only people with administrator level access to the user pool will be able to create users. So in order for a user to access your application — They first have to request an administrator to create an account for them and provide a temporary password. The user can then login using the temporary password and change it immediately after first login.
Cognito user pool offers multi factor authentication capability out of the box. One thing to note is that this does come at an additional cost of sending SMS text messages to deliver the security code. This means that all users must provide their phone numbers and the phone numbers must be verified during the user signup process. You can choose to not use MFA at all or make it mandatory so that all your users have to mandatorily opt for MFA. The third option is to make it optional and let the user decide if they want to use MFA or not.
One of the most annoying and time consuming support function is to help user’s recover their account after they have forgotten their password. With Cognito user pool, you can give the capability to recover accounts in the hands of your users. When a user forgets their password, they can have a code sent to their verified email or verified phone to recover their account. If you have MFA enabled then it is recommended not allowing phone to be used for both password resets and multi-factor authentication (MFA).
Integration with Simple Email Service
Cognito user pool can use simple email service to send out email messages to the users. These messages include MFA, email verification, welcome email for administrator configured users.
You require a verified email address. Note the syntax of the “FROM email address” field — “Hello from your company” will be the name that the user will see in their e-mail client and it will appear to be sent from “email@example.com” email address. When user replies to any of these e-mails, you can configure an email address which will receive the these replies. If you are expecting large number of users to signup and use your application it is recommended that you use SES for all your cognito related e-mail transactions.
You can also customise the verification and invitation email messages by adding custom HTML.
User Device Tracking
You can also configure if you want to remember devices that user is using to access your application. When turned on, all distinct devices of the users will be tracked and registered. You can also give an options to your end user if you want them to decide if their devices are remembered or not. By default this capability is turned off. This capability is useful when you want to restrict the number of devices the user can access your application / resources from.
Client Application Integration
Most of the user functions like login, registration and account recovery has to be integrated with a client application. Client applications can be native mobile clients or a web applications. In order to allow these client applications to access the Cognito user pool capabilities, you have to register these client applications with the Cognito user pool. The way you do that is by defining a client.
Giving an appropriate App client name is important as it helps to identify which client applications have access to the user pool. The client applications can use AWS Amplify (https://aws.amazon.com/amplify/) to integrate with Cognito user pool. Each application client you register is given an application client id and an optional application client secret. When you use AWS Amplify, you configure the ID and secret so that you can seamlessly access Cognito user pool capabilities within your application. Remember that for web clients, you have to leave the “Generate client secret” check-box unchecked.
AWS Amplify uses SRP (secure remote password) protocol so make sure that you enable the same for the application client.
You can also define if these application clients can read / write user attributes. This gives you the capability to restrict what the user can do in a mobile application v/s a web application. Any attributes that are marked as mandatory will always be writable by all app clients.
In any application / solution, many (or sometimes all) user registration / sign-in related events require some post processing e.g. sending a welcome e-mail after successful user signup, sending notification email to user that they accessed the application so that user can immediately be alerted if someone else is accessing the application using their credentials. This is where “triggers” of Cognito user pool help. Following are various events for which you can assign a Lambda functions.
Cognito service will invoke the Lambda function when a specific event happens. You can write your custom logic within the Lambda function to perform the requisite workflow. For example you can use the “Pre sign-up” trigger check if the user has entered a “disposable” email address or not. If you are migrating users from your own repository to Cognito then you can use the “User Migration” trigger to identify if the user signing in is a new user or an existing user. If the user is an existing user, you can perform the migration of user from old system to Cognito. If you want to restrict the number of devices user can access your application then you can utilise the “Pre authentication” trigger to query the number of distinct devices user is accessing the application from and then either allow of deny the request.
One important capability of the Cognito user pool is the capability to configure external identity providers so users can user their existing social accounts to identify them selves and register with your application.
One limitation of using the social login with Cognito user pool is that you have to user the “hosted UI” to allow users to login to your application. The hosted UI is a full blown OAuth server, backed by the Cognito API. The “hosted UI” offers very limited UI customisations and may not gel well with your overall user experience of the application (specially for mobile applications). The AWS Amplify SDK for web, iOS and Android does have support for hosted UI so integrating it within your application is easy. Once social logins are configured you can also define which application clients can allow which identity providers. You can also define mapping of user attributes received from identity providers with Cognito user attributes.
Uses of Cognito User Pool
If you are looking for a simple, scalable user management and authentication service Cognito user pool is a very good option. It provides wide range of capabilities from user sign up, user sign-in, password / account management etc. Once user establishes their identity (username, email or phone number), you can then use that identity within your application backend for authorisation purpose.
Remember Cognito user pool is an authentication service — It is not an authorisation service. So you will have to implement the authorisation management yourself.
Also if you want Cognito user pool users to access any of the AWS resources e.g. S3, RESTful services hosted on API gateway — then you will need to integrate the Cognito user pool with a Cognito Identity pool. The Cognito identity pool is capable of using Cognito user pool as an identity provider and issue an AWS IAM token using which Cognito user pool users can access AWS resources that are protected by AWS IAM policies. Expect more about this in the article on Cognito Identity Pool.
When should you use Cognito User Pool?
Use case 1: If you have a backend services (e.g. Spring boot based REST APIs hosted on EC2) that is already having authorisation support, you can use Cognito user pool as authentication provider.
User case 2: If you have a web application that requires user identity to personalise their experience.
Cognito User Pool & Server-less Architecture
If you are building a server less application on AWS ans want your end users to have seamless access to it — just having Cognito user pool is not enough. In a server-less application most resources that the user will need to access are protected by AWS IAM infrastructure such as RESTful services hosted on API Gateway, Files stored on S3. In order to access such resources, the users need an AWS IAM access token. Cognito user pool is not capable of issuing an AWS IAM access token. This is the job of the Cognito Identity Pool. You have to integrate Cognito user pool with Cognito identity pool for this purpose. For server less application use case, it is also recommended that you do not integrate social identity providers with your Cognito user pool. Instead integrate the social identity providers as additional identity providers along with Cognito user pool in the Cognito identity pool. This allows the users to user social or Cognito user pool credentials to sign-in and access your server less application. With such configuration, client applications integrating social login do not have to use the “hosted UI” for the sign-up / sign-in experience allowing much needed flexibility in sign-up / sign-in UX design.