In this module, you configure Amazon Cognito for use as the authentication provider in your application. Amazon Cognito is a fully managed authentication provider that allows for user sign-up, verification, login, and more.

Amazon Cognito has two different components: user pools and identity pools. User pools are standard user directories where users sign in through Amazon Cognito or through a third-party identity, such as Google or GitHub. After successful authentication, users receive tokens, such as access tokens or ID tokens, that can be used to access resources in the backend.

In contrast, identity pools provide a way for users to receive temporary AWS credentials for accessing AWS resources. This could be used to provide limited, direct access to an AWS Lambda function, an Amazon DynamoDB table, or other resources.

In this tutorial, you use Amazon Cognito user pools. You allow users to register via your application. After they’ve registered, they can login via a client to receive an ID token. This ID token can be passed as a header to your application to authenticate the user.

In the following steps below, you create an Amazon Cognito user pool. Then you create a client to access the user pool. Finally, you look at some example code to interact with the user pool.

Time to Complete Module: 20 Minutes


  • Step 1. Create an Amazon Cognito user pool

    A user pool is a user directory -- all user and group management happens in your pool. When creating a user pool, you need to specify rules for your user pool, including your password policy and the required attributes.

    In the scripts/ directory, there is a file called create-user-pool.sh. The contents are as follows:

    USER_POOL_ID=$(aws cognito-idp create-user-pool \
      --pool-name inventory-users \
      --policies '
          {
          "PasswordPolicy": {
            "MinimumLength": 8,
            "RequireUppercase": true,
            "RequireLowercase": true,
            "RequireNumbers": true,
            "RequireSymbols": false
          }
        }' \
      --query 'UserPool.Id' \
      --output text)
    
    echo "User Pool created with id ${USER_POOL_ID}"
    echo "export USER_POOL_ID=${USER_POOL_ID}" >> env.sh

    This script uses the AWS Command Line Interface (AWS CLI) to create a user pool. You give your user pool a name -- inventory-users -- and specify your password policies. For the password, this script requires a minimum length of eight characters, and the password must include an uppercase letter, a lowercase letter, and a number.

    You can create your user pool by executing the script with the following command:

    bash scripts/create-user-pool.sh

    You should see the following output:

    User Pool created with id <user-pool-id>

    In the next step, you create a client to access the user pool.

  • Step 2. Create a user pool client

    Now that you have a user pool configured, you need to make a user pool client. A user pool client is used to call unauthenticated methods on the user pool, such as register and sign in.

    The user pool client is used by your backend Node.js application. To register or sign in, a user makes an HTTP POST request to your application containing the relevant properties. Your application uses the user pool client and forwards these properties to your Amazon Cognito user pool. Then, your application returns the proper data or error message.

    There is a file in the scripts/ directory called create-user-pool-client.sh for creating a user pool client. The contents of the file are as follows:

    source env.sh
    
    CLIENT_ID=$(aws cognito-idp create-user-pool-client \
      --user-pool-id ${USER_POOL_ID} \
      --client-name inventory-backend \
      --no-generate-secret \
      --explicit-auth-flows ADMIN_NO_SRP_AUTH \
      --query 'UserPoolClient.ClientId' \
      --output text)
    
    echo "User Pool Client created with id ${CLIENT_ID}"
    echo "export COGNITO_CLIENT_ID=${CLIENT_ID}" >> env.sh

    The script creates a user pool client for your newly-created user pool. It uses the ADMIN_NO_SRP_AUTH flow, which is a flow that can be used in a server-side application. Because you’re doing a server-side flow, you don’t need a client secret used in a client-side flow, such as on a mobile device or in a single-page application.

    Run the script to create the user pool client with the following command:

    bash scripts/create-user-pool-client.sh

    You should see the following output:

    User Pool Client created with id <client-id>

    In the last step of this module, you learn about the authentication code that is used in your application.

  • Step 3. Review authentication code

    Now that you have created a user pool and a client to access the pool, let’s see how you use Amazon Cognito in your application.

    In the application/ directory of your project, there is a file called auth.js. This file contains a few authentication helpers for your application. There are three core functions to that file. Let’s review them in turn.

    The first function is createCognitoUser and is used when registering a new user in Amazon Cognito. The function looks as follows:

    const createCognitoUser = async (username, password, email) => {
      const signUpParams = {
        ClientId: process.env.COGNITO_CLIENT_ID,
        Username: username,
        Password: password,
        UserAttributes: [
          {
            Name: 'email',
            Value: email
          }
        ]
      }
      await cognitoidentityserviceprovider.signUp(signUpParams).promise()
      const confirmParams = {
        UserPoolId: process.env.USER_POOL_ID,
        Username: username
      }
      await cognitoidentityserviceprovider.adminConfirmSignUp(confirmParams).promise()
      return {
        username,
        email
      }
    }

    It uses the Amazon Cognito client ID that you set in the previous step, as well as the username, password, and email given by the user, to create a new user. Additionally, you immediately confirm the user so that the user can sign in. Usually, you opt for a confirmation process that verified the user’s email and/or mobile phone number so that you have a contact method for them. That’s out of scope for this tutorial, so you can just automatically confirm new users.

    The second core method is the login function that is used when registered users are authenticating. The code is as shown below:

    const login = async (username, password) => {
      const params = {
        ClientId: process.env.COGNITO_CLIENT_ID,
        UserPoolId: process.env.USER_POOL_ID,
        AuthFlow: 'ADMIN_NO_SRP_AUTH',
        AuthParameters: {
          USERNAME: username,
          PASSWORD: password
        }
      }
      const { AuthenticationResult: { IdToken: idToken } }= await cognitoidentityserviceprovider.adminInitiateAuth(params).promise()
      return idToken
    }

    Like in the createCognitoUser function, you use the Client Id and the given parameters to make a call to Amazon Cognito. The adminInitiateAuth method for Amazon Cognito authenticates the user and return tokens if the authentication method passes. You use ID tokens for authentication, so that is what you return for successful user logins.

    Finally, there is a verifyToken function. The contents of this function are as follows:

    const verifyToken = async (idToken) => {
      function getKey(header, callback){
        client.getSigningKey(header.kid, function(err, key) {
          var signingKey = key.publicKey || key.rsaPublicKey;
          callback(null, signingKey);
        });
      }
    
      return new Promise((res, rej) => {
        jwt.verify(idToken, getKey, {}, function(err, decoded) {
          if (err) { rej(err) }
          res(decoded)
        })
      })
    }

    This function verifies an ID token that has been passed up with a request. The ID token given by Amazon Cognito is a JSON Web Token, and the verifyToken function confirms that the token was signed by your trusted source and to identify the user. This function is used in endpoints that require authentication to ensure that the requesting user has access.

    In subsequent modules, you use these three authentication functions in your backend application.


In this module, you created and configured an Amazon Cognito user pool and a client for the user pool. You also saw your utility functions that interact with your Amazon Cognito user pool for user registration, login, and verification.

In the next module, you deploy your backend application using serverless technologies like AWS Lambda and Amazon API Gateway.