Skip to main content

How to create an AWS Cognito user pool using CloudFormation

Greetings!

In my previous article, I created a Cognito user pool using the AWS console. However, that is not a good practice in real projects as it involves a lot of manual work. That is why we need to leverage infrastructure as code. In this article, we create the same setup using CloudFormation.
It turned out that there is no proper example in the documentation and the documentation is also a little confusing. Had to do a little trial and error and dig the internet as well.

What we need

We need to create a user pool and register a client. After that, we need to retrieve an access token for the logged-in user.

Steps

We mainly need to configure;
  • UserPool
  • UserPoolClient
  • UserPoolDomain
Here is the complete CloudFormation template.
AWSTemplateFormatVersion: "2010-09-09"
Description: Cognito Stack

Resources:
  MyWebAppUserPool:
    Type: AWS::Cognito::UserPool
    Properties:
      UserPoolName: my-web-app-user-pool
      Policies:
        PasswordPolicy:
          MinimumLength: 6
      UsernameAttributes:
        - email
      VerificationMessageTemplate:
        DefaultEmailOption: CONFIRM_WITH_CODE
      AutoVerifiedAttributes:
        - email
      EmailConfiguration:
        EmailSendingAccount: COGNITO_DEFAULT
      Schema:
        - AttributeDataType: String
          Mutable: False
          Name: email
          Required: True
        - AttributeDataType: String
          Mutable: True
          Name: name
          Required: True

  MyWebAppUserPoolClient:
    Type: AWS::Cognito::UserPoolClient
    Properties:
      UserPoolId: !Ref MyWebAppUserPool
      ClientName: my-web-app
      GenerateSecret: True
      CallbackURLs:
        - http://localhost:8585
      AllowedOAuthFlows:
        - code
      AllowedOAuthFlowsUserPoolClient: True
      AllowedOAuthScopes:
        - openid
        - email
      SupportedIdentityProviders:
        - COGNITO

  MyWebAppUserPoolDomain:
    Type: AWS::Cognito::UserPoolDomain
    Properties:
      UserPoolId: !Ref MyWebAppUserPool
      Domain: my-web-app-aslkdjs2349slj

Domain

We need to have a domain to access Cognito provided user interface. Here I have hard-coded a value for this example. We need to attach the domain to our user pool via UserPoolId.

UserPoolClient

This is our client application properties (ex: single page application) that use the Cognito user pool. As the client app needs a password to access, I have enabled GenerateSecret by providing True.

The whole idea of this is to use the OAuth authorization code grant type. We need to provide multiple properties to achieve it. Make sure to provide OAuth scopes and supported identity providers as, without these, cognito-provided UI is not enabled.

UserPool

This includes the actual user pool details. Users can register themselves by providing their email, name, and password. A code will be sent for verification using Cognito provided email template. Password length should be a minimum of 6 characters in length.

Create the stack

We can create the stack by executing the below AWS command.
aws cloudformation deploy --template-file ./cognito-cloudformation.yml --stack-name my-web-app-congnito --region us-east-1

Delete the stack

We can delete everything by executing the below AWS command.
aws cloudformation delete-stack --stack-name my-web-app-congnito --region us-east-1

Obtain the token

Here we need to construct 2 URLs.
  • Obtain the code (login endpoint)
  • Exchange the code for the code (token endpoint)
I used postman to construct both endpoints.
Use a browser window for the GET endpoint as this is a redirect call.
GET https://my-web-app-aslkdjs2349slj.auth.us-east-1.amazoncognito.com/login?
client_id=7kbvc8fdt3q3s1obl1lrb85fe7
&response_type=code
&scope=email openid
&redirect_uri=http://localhost:8585
The above GET URL will give the code. Use that code to get an access token using the below URLs.
curl -X POST \
  https://my-web-app-aslkdjs2349slj.auth.us-east-1.amazoncognito.com/oauth2/token \
  -H 'cache-control: no-cache' \
  -H 'content-type: application/x-www-form-urlencoded' \
  -H 'postman-token: 28d19d50-e626-2379-a857-990aba678230' \
  -d 'Content-Type=application%2Fx-www-form-urlencoded
&client_id=7kbvc8fdt3q3s1obl1lrb85fe7
&client_secret=1cc638a7698placg96ua0tr2e4onrit43gphf9lrpirh5lpgpqne
&grant_type=authorization_code
&code=b8b2f44f-7ab2-4eca-b924-c06025c74ff1
&redirect_uri=http://localhost:8585'
That's it guys. Happy learning ☺

References














Comments