12 min read

Amazon Cognito is a user authentication service that enables user sign-up and sign-in, and access control for mobile and web applications, easily, quickly, and securely. In Amazon Cognito, you can create your user directory, which allows the application to work when the devices are not online.

Amazon Cognito supports, to scale, millions of users and authenticates users from social identity providers such as Facebook, Google, Twitter, Amazon, or enterprise identity providers, such as Microsoft Active Directory through SAML, or your own identity provider system.

Today, we will discuss the AWS Cognito service for simple and secure user authentication for mobile and web applications.

With Amazon Cognito, you can concentrate on developing great application experiences for the user, instead of worrying about developing secure and scalable application solutions for handling the access control permissions of users and synchronization across the devices.

Let’s explore topics that fall under AWS Cognito and see how it can be used for user authentication from AWS.

This article is an excerpt from a book ‘Expert AWS Development’ written by Atul V. Mistry.

Amazon Cognito benefits

  • Amazon Cognito is a fully managed service and it provides User Pools for a secure user directory to scale millions of users; these User Pools are easy to set up.
  • Amazon Cognito User Pools are standards-based identity providers, Amazon Cognito supports many identity and access management standards such as OAuth 2.0, SAML 2.0, OAuth 2.0 and OpenID Connect.
  • Amazon Cognito supports the encryption of data in transit or at rest and multi-factor authentication.
  • With Amazon Cognito, you can control access to the backend resource from the application. You can control the users by defining roles and map different roles for the application, so they can access the application resource for which they are authorized.
  • Amazon Cognito can integrate easily with the sign-up and sign-in for the app because it provides a built-in UI and configuration for different federating identity providers. It provides the facility to customize the UI, as per company branding, in front and center for user interactions.
  • Amazon Cognito is eligible for HIPAA-BAA and is compliant with PCI DSS, SOC 1-3, and ISO 27001.

Amazon Cognito features

Amazon Cognito provides the following features:

  • Amazon Cognito Identity
    • User Pools
    • Federated Identities
  • Amazon Cognito Sync
  • Data synchronization

Today we will discuss User Pools and Federated Identities in detail.

Amazon Cognito User Pools

Amazon Cognito User Pools helps to create and maintain a directory for users and adds sign-up/sign-in to mobile or web applications. Users can sign in to a User Pool through social or SAML-based identity providers.

Enhanced security features such as multi-factor authentication and email/phone number verification can be implemented for your application. With AWS Lambda, you can customize your workflows for Amazon Cognito User Pools such as adding application specific logins for user validation and registration for fraud detection.

Getting started with Amazon Cognito User Pools

You can create Amazon Cognito User Pools through Amazon Cognito Console, AWS Command Line Interface (CLI), or Amazon Cognito Application Programming Interface (API). Now let’s understand all these different ways of creating User Pools.

Amazon Cognito User Pool creation from the console

Please perform the following steps to create a User Pool from the console.

  1. Log in to the AWS Management console and select the Amazon Cognito service.
  2. It will show you two options, such as Manage your User Pools and Manage Federated Identities, as shown:
Amazon Cognito
  1. Select Manage Your User Pools. It will take you to the Create a user pool screen. You can add the Pool name and create the User Pool. You can create this user pool in two different ways, by selecting:
    • Review defaults: It comes with default settings and if required, you can customize it
    • Step through settings: Step by step, you can customize each setting:
  1. When you select Review defaults, you will be taken to the review User Pool configuration screen and then select Create pool.
  2. When you will select Step through settings, you will be taken to the Attributes screen to customize it. Let’s understand all the screens in brief:
    • Attributes: This gives the option for users to sign in with a username, email address, or phone number. You can select standard attributes for user profiles as well create custom attributes.
    • Policies: You can set the password strength, allow users to sign in themselves, and stipulate days until expire for the newly created account.
    • MFA and verifications: This allows you to enable Multi-Factor Authentication, and configure require verification for emails and phone numbers. You create a new IAM role to set permissions for Amazon Cognito that allows you to send SMS message to users on your behalf.
    • Message customizations: You can customize messages to verify an email address by providing a verification code or link. You can customize user invitation messages for SMS and email but you must include the username and a temporary password. You can customize email addresses from SES-verified identities.
    • Tags: You can add tags for this User Pool by providing tag keys and their values.
    • Devices: This provides settings to remember a user’s device. It provides options such as Always, User Opt In, and No.
    • App clients: You can add app clients by giving unique IDs and an optional secret key to access this User Pool.
    • Triggers: You can customize workflows and user experiences by triggering AWS Lambda functions for different events.
    • Reviews: This shows you all the attributes for review.
  1. You can edit any attribute on the Reviews screen and then click on Create pool. It will create the User Pool.
  2. After creating a new User Pool, navigate to the App clients screen. Enter the App client name as CognitoDemo and click on Create app client:
  1. Once this Client App is generated, you can click on the show details to see App client secret:
  1. Pool Id, App client id, and App client secret are required to connect any application to Amazon Cognito.

Now, we will explore an Amazon Cognito User Pool example to sign up and sign in the user.

Amazon Cognito example for Android with mobile SDK

In this example, we will perform some tasks such as create a new user, request confirmation code for a new user through email, confirm user, user login, and so on.

  • Create a Cognito User Pool:

To create a User Pool with the default configuration, you have to pass parameters to the CognitoUserPool constructor, such as application context, userPoolId, clientId, clientSecret, and cognitoRegion (optional):

CognitoUserPool userPool = new CognitoUserPool(context, userPoolId, clientId, clientSecret, cognitoRegion);
  • New user sign-up:

Please perform the following steps to sign up new users:

Collect information from users such as username, password, given name, phone number, and email address. Now, create the CognitoUserAttributes object and add the user value in a key-value pair to sign up for the user:

CognitoUserAttributes userAttributes = new CognitoUserAttributes(); 
 
String usernameInput = username.getText().toString(); 
String userpasswordInput = password.getText().toString(); 
userAttributes.addAttribute("Name", name.getText().toString()); 
userAttributes.addAttribute("Email", email.getText().toString()); 
userAttributes.addAttribute("Phone", phone.getText().toString()); 
 
userPool.signUpInBackground(usernameInput, userpasswordInput, userAttributes, null, signUpHandler);

To register or sign up a new user, you have to call SignUpHandler. It contains two methods: onSuccess and onFailure.

For onSuccess, it will call when it successfully registers a new user. The user needs to confirm the code required to activate the account. You have to pass parameters such as Cognito user, confirm the state of the user, medium and destination of the confirmation code, such as email or phone, and the value for that:

SignUpHandler signUpHandler = new SignUpHandler() {
     @Override
     public void onSuccess(CognitoUser user, boolean signUpConfirmationState, CognitoUserCodeDeliveryDetails cognitoUserCodeDeliveryDetails) {
         // Check if the user is already confirmed
         if (signUpConfirmationState) {
             showDialogMessage("New User Sign up successful!","Your Username is : "+usernameInput, true);
         }    }
@Override
public void onFailure(Exception exception) {
showDialogMessage("New User Sign up failed.",AppHelper.formatException(exception),false);
}
};

You can see on the User Pool console that the user has been successfully signed up but not confirmed yet:

  • Confirmation code request:

After successfully signing up, the user needs to confirm the code for sign-in. The confirmation code will be sent to the user’s email or phone. Sometimes it may automatically confirm the user by triggering a Lambda function. If you selected automatic verification when you created the User Pool, it will send the confirmation code to your email or phone. You can let the user know where they will get the confirmation code from the cognitoUserCodeDeliveryDetails object. It will indicate where you will send the confirmation code:

VerificationHandler resendConfCodeHandler = new VerificationHandler() {
     @Override
     public void onSuccess(CognitoUserCodeDeliveryDetails details) {
         showDialogMessage("Confirmation code sent.","Code sent to "+details.getDestination()+" via "+details.getDeliveryMedium()+".", false);
     }
@Override
public void onFailure(Exception exception) {
showDialogMessage("Confirmation code request has failed", AppHelper.formatException(exception), false);
}
};

In this case, the user will receive an email with the confirmation code:

The user can complete the sign-up process after entering the valid confirmation code. To confirm the user, you need to call the GenericHandler. AWS SDK uses this GenericHandler to communicate the result of the confirmation API:

GenericHandler confHandler = new GenericHandler() {
     @Override
     public void onSuccess() {
       showDialogMessage("Success!",userName+" has been confirmed!", true);
     }
@Override
public void onFailure(Exception exception) {
showDialogMessage("Confirmation failed", exception, false);
}
};

Once the user confirms, it will be updated in the Amazon Cognito console:

  • Sign in user to the app:

You must create an authentication callback handler for the user to sign in to your application. The following code will show you how the interaction happens from your app and SDK:

// call Authentication Handler for User sign-in process.
 AuthenticationHandler authHandler = new AuthenticationHandler() {
     @Override
     public void onSuccess(CognitoUserSession cognitoUserSession) {
         launchUser();
 // call Authentication Handler for User sign-in process.
 AuthenticationHandler authHandler = new AuthenticationHandler() {
     @Override
     public void onSuccess(CognitoUserSession cognitoUserSession) {
         launchUser();
     }
@Override
public void getAuthenticationDetails(AuthenticationContinuation continuation, String username) {
// Get user sign-in credential information from API. AuthenticationDetails authDetails = new AuthenticationDetails(username, password, null);
// Send this user sign-in information for continuation continuation.setAuthenticationDetails(authDetails);
// Allow user sign-in process to continue continuation.continueTask();
}
@Override
public void getMFACode(MultiFactorAuthenticationContinuation mfaContinuation) {
// Get Multi-factor authentication code from user to sign-in mfaContinuation.setMfaCode(mfaVerificationCode); // Allow user sign-in process to continue mfaContinuation.continueTask(); }
@Override
public void onFailure(Exception e) { // User Sign-in failed. Please check the exception
showDialogMessage("Sign-in failed", e);
}
@Override
public void authenticationChallenge(ChallengeContinuation continuation) {
/** You can implement Custom authentication challenge logic 
* here. Pass the user's responses to the continuation.
*/
}
};
  • Access AWS resources from application user:

A user can access AWS resource from the application by creating an AWS Cognito Federated Identity Pool and associating an existing User Pool with that Identity Pool, by specifying User Pool ID and App client id. Please see the next section (Step 5) to create the Federated Identity Pool with Cognito.

Let’s continue with the same application; after the user is authenticated, add the user’s identity token to the logins map in the credential provider. The provider name depends on the Amazon Cognito User Pool ID and it should have the following structure:

cognito-idp.<USER_POOL_REGION>.amazonaws.com/<USER_POOL_ID>

For this example, it will be: cognito-idp.us-east-1.amazonaws.com/us-east-1_XUGRPHAWA.

Now, in your credential provider, pass the ID token that you get after successful authentication:

// After successful authentication get id token from  
// CognitoUserSession 
    String idToken = cognitoUserSession.getIdToken().getJWTToken();  
 
 // Use an existing credential provider or create new 
    CognitoCachingCredentialsProvider credentialsProvider = new CognitoCachingCredentialsProvider(context, IDENTITY_POOL_ID, REGION); 
 
 // Credentials provider setup 
    Map<String, String> logins = new HashMap<String, String>();  
    logins.put("cognito-idp.us-east-1.amazonaws.com/us-east-1_ XUGRPHAWA", idToken);  
    credentialsProvider.setLogins(logins);

You can use this credential provider to access AWS services, such as Amazon DynamoDB, as follows:

AmazonDynamoDBClient dynamoDBClient = new AmazonDynamoDBClient(credentialsProvider)

You have to provide the specific IAM permission to access AWS services, such as DynamoDB. You can add this permission to the Federated Identities, as mentioned in the following Step 6, by editing the View Policy Document. Once you have attached the appropriate policy, for example, AmazonDynamoDBFullAccess, for this application, you can perform the operations such as create, read, update, and delete operations in DynamoDB.

Now, we will look at how to create the Amazon Cognito Federated Identities.

Amazon Cognito Federated Identities

Amazon Cognito Federated Identities enables you to create unique identities for the user and, authenticate with Federated Identity Providers.

With this identity, the user will get temporary, limited-privilege AWS credentials. With these credentials, the user can synchronize their data with Amazon Cognito Sync or securely access other AWS services such as Amazon S3, Amazon DynamoDB, and Amazon API Gateway.

It supports Federated Identity providers such as Twitter, Amazon, Facebook, Google, OpenID Connect providers, or SAML identity providers, unauthenticated identities. It also supports developer-authenticated identities from which you can register and authenticate the users through your own backend authentication systems.

You need to create an Identity Pool to use Amazon Cognito Federated Identities in your application. This Identity Pool is specific for your account to store user identity data.

Creating a new Identity Pool from the console

Please perform the following steps to create a new Identity Pool from the console:

  1. Log in to the AWS Management console and select the Amazon Cognito Service.
  2. It will show you two options: Manage your User Pools and Manage Federated Identities.
  3. Select Manage Federated Identities. It will navigate you to the Create new identity pool screen. Enter a unique name for the Identity pool name:
  1. You can enable unauthenticated identities by selecting Enable access to unauthenticated identities from the collapsible section:
  1. Under Authentication providers, you can allow your users to authenticate using any of the authentication methods. Click on Create pool.
You must select at least one identity from Authentication providers to create a valid Identity Pool.

Here Cognito has been selected for a valid Authentication provider by adding User Pool ID and App client id:

  1. It will navigate to the next screen to create a new IAM role by default, to provide limited permission to end users. These permissions are for Cognito Sync and Mobile Analytics but you can edit policy documents to add/update permissions for more services. It will create two IAM roles. One for authenticated users that are supported by identity providers and another for unauthenticated users, known as guest users. Click Allow to generate the Identity Pool:
  1. Once the Identity Pool is generated, it will navigate to the Getting started with Amazon Cognito screen for that Identity Pool. Here, it will provide you with downloadable AWS SDK for different platforms such as Android, iOS – Objective C, iOS – Swift, JavaScript, Unity, Xamarin, and .NET. It also provides sample code for Get AWS Credentials and Store User Data:
Amazon Cognito Federated Identities

You have created Amazon Cognito Federated Identities.

We looked at how user authentication process in AWS Cognito works with User Pools and Federated Identities.

If you found this post useful, check out the book ‘Expert AWS Development’ to learn other concepts such as Amazon Cognito sync, traditional web hosting etc, in AWS development.

Read Next

Keep your serverless AWS applications secure [Tutorial]

Amazon Neptune, AWS’ cloud graph database, is now generally available

How to start using AWS

Tech writer at the Packt Hub. Dreamer, book nerd, lover of scented candles, karaoke, and Gilmore Girls.

3 COMMENTS

  1. Thx for the documentation 🙂 The docu seems to be not complete at section “Confirmation code request”. I share the necessary async task code, if you want to complete the docu… Best Regads

    //confirm signup code
    private void confirmCode(String strLoginName, String strConfirmationCode) {

    class MyTaskParams {
    CognitoUser user;
    String confirmationCode;

    MyTaskParams(CognitoUser user, String confirmationCode) {
    this.user = user;
    this.confirmationCode = confirmationCode;
    }
    }

    class MyTask extends AsyncTask {

    protected String doInBackground(MyTaskParams… params) {
    try {
    // create a callback handler for confirm
    GenericHandler handler = new GenericHandler() {
    @Override
    public void onSuccess() {
    Toast.makeText(getContext(), “User was successfully confirmed!”, Toast.LENGTH_LONG).show();
    }
    @Override
    public void onFailure(Exception exception) {
    Toast.makeText(getContext(), “Failure. Confirmation failed, probe exception for details” + exception.getMessage(), Toast.LENGTH_LONG).show();
    }
    };

    String confirmationCode = params[0].confirmationCode;
    CognitoUser user = params[0].user;
    user.confirmSignUp(confirmationCode, true, handler);

    return “confirm sign up successful”;

    } catch (Exception e) {
    return “Exception: ” + e.getMessage();
    }
    }
    protected void onPostExecute (String strResult){
    // TODO: check if successful
    }
    }

    CognitoUser user = mUserPool.getUser(strLoginName);
    MyTaskParams params = new MyTaskParams(user, strConfirmationCode);
    MyTask myTask = new MyTask();
    myTask.execute(params);

    }

  2. … I found out, that there are methods *InBackground, so no Async tysk is necessary …

    //confirm signup code
    private void confirmCode(String strLoginName, String strConfirmationCode) {

    CognitoUser user = mUserPool.getUser(strLoginName);

    // create a callback handler for confirm
    GenericHandler handler = new GenericHandler() {
    @Override
    public void onSuccess() {
    Toast.makeText(getContext(), “User was successfully confirmed!”, Toast.LENGTH_LONG).show();
    }

    @Override
    public void onFailure(Exception exception) {
    Toast.makeText(getContext(), “Failure. Confirmation failed, probe exception for details” + exception.getMessage(), Toast.LENGTH_LONG).show();
    }
    };
    user.confirmSignUpInBackground(strConfirmationCode, false, handler);

    }

  3. Hi, I have done exactly what you have mentioned above, I am able to connect to dentity pool using my facebook, google and Cognito user logins.

    The problem I am facing is regarding how to store email and name of users who signup using facebook and google. I expected to have some kind of two way binding between Cognito user pool and Identity pools to do that.

    The other way that I tried to achieve my goal was by adding identity providers into Cognito and mapping attributes, but the problem is that in android sdk cognitoUserPool.signUpInBackground() method needs to have password, which is fine with normal signup but when I signup using facebook or google, using this method does not make sense as when user logs in again, they would need to have same password which is not possible.

    am I doing anything wrong, how am I supposed to get user data in identity pool, could you please help me?

    thanks in advance.

LEAVE A REPLY

Please enter your comment!
Please enter your name here