Front-End Web & Mobile

Using Android SDK with Amazon Cognito Your User Pools

Introduction

Last month AWS launched the beta version of  Amazon Cognito User Pools. With this feature, you can easily add sign-up and sign-in functionality to your mobile and web applications. You get a simple to use, fully managed service for creating and maintaining a user directory which can scale to hundreds of millions of users. You also benefit from the security and privacy best practices of AWS.

AWS Mobile SDKs for Android, JavaScript, and iOS are available with this beta launch. You can use these SDKs in your apps to interact with your user pools. In this blog we will show how to get started with the Mobile SDK for Android. For guidance on iOS or JavaScript see the Amazon Cognito Developer Guide. For a walk-through on getting started with iOS, please visit this blog.

 

Creating your user pools

Before you can use the SDK, you must create a user pool.  

1) Start by signing in to the Amazon Cognito console and choosing Manage your User Pools. This opens the page where you can see all of your Cognito user pools and also create new pools.

2) Provide a name for your pool and choose Step through settings to start customizing the pool. You can choose Review defaults to create the pool with default settings.

3) Choose the required attributes for users in your pool. The attributes you select as “Required” are must-have values for users to sign-up in the pool. Some attributes can be used as aliases, which means that users can sign in with the aliases instead of their username, if these attributes are verified. Let’s choose email, given name and phone number as required parameters and email and phone number as aliases. If a user in this pool has verified his or her email address, then this user can use that email address to sign in. The user will still be able to sign in with his or her username.

4) The next step is to set the password requirements; we will use default password settings.

5) In the next step you can enable multi-factor authentication (MFA) for users in this pool. We will leave MFA turned off for users in this pool.

6) Next, you can customize the messages that are sent to users in your pool to deliver various verification codes.

7) The next step is to create a client ID for your app. A client ID is required to allow your app to interact with your user pool. Click Add an app and provide your the name of your app. This can be any string that helps you identify how this client-id is used, e.g., “my social network Android app”.

You can also generate a client secret along with the client ID, but it’s not required. If you chose to generate a client secret for your client ID you must use the generated client secret whenever you use the client ID in your apps.

8) The next step allows you to customize workflows through Lambda triggers. For this walkthrough we will not set up customization through Lambda.

9) Review the settings and choose “Create pool” to create your user pool.

You now have a user pool and users can sign up in this pool.

 

Using Amazon Cognito User Pools in your Android app

Start by creating a CognitoUserPool object. This will be the entry point for all interactions with your Cognito user pool from your app. To create this object, you will need the poolId, clientId and clientSecret (if generated for the clientId).

// setup AWS service configuration. Choosing default configuration
ClientConfiguration clientConfiguration = new ClientConfiguration();	

// Create a CognitoUserPool object to refer to your user pool
CognitoUserPool userPool = new CognitoUserPool(context, poolId, clientId, clientSecret, clientConfiguration);

Using this pool instance, you can sign up new users to the pool. To sign up a user, you will need to provide the following information from the user:

1.     user-id: This will be used by the user to login and must be unique with-in the pool.

2.     password: This will be the users’ password.

3.     User attributes: These are other user details. They must include the required attributes set for your pool. We had earlier set email, given name, and phone number as required attributes.

After you collect these details from your user, you can use the pool instance to sign up the user.

// Create a CognitoUserAttributes object and add user attributes 
CognitoUserAttributes userAttributes = new CognitoUserAttributes(); 

// Add the user attributes. Attributes are added as key-value pairs 
// Adding user's given name. 
// Note that the key is "given_name" which is the OIDC claim for given name 
userAttributes.addAttribute("given_name", userGivenName); 

// Adding user's phone number 
userAttributes.addAttribute("phone_number", phoneNumber); 

// Adding user's email address 
userAttributes.addAttribute("email", emailAddress);

Create a callback handler for sign up. The onSuccess method is called when the sign-up is successful. 

SignUpHandler signupCallback = new SignUpHandler() {

    @Override
    public void onSuccess(CognitoUser cognitoUser, boolean userConfirmed, CognitoUserCodeDeliveryDetails cognitoUserCodeDeliveryDetails) {
        // Sign-up was successful
        
        // Check if this user (cognitoUser) has to be confirmed
        if(!userConfirmed) {
            // This user has to be confirmed and a confirmation code was sent to the user
	    // cognitoUserCodeDeliveryDetails will indicate where the confirmation code was sent
	    // Get the confirmation code from user
        }
	else {
            // The user has already been confirmed
        }
    }
 
    @Override
    public void onFailure(Exception exception) {
        // Sign-up failed, check exception for the cause
    }
};

Call sign-up API 

// Sign up this user
userPool.signUpInBackground(userId, password, userAttributes, null, signupCallback);

Users may have to be confirmed after they sign up, before they can sign in. Users can confirm through email or phone number. After a successful sign-up, if the user has to be confirmed, a confirmation code will be sent to the user’s email or phone number. It is also possible to automatically confirm a user after sign-up through Lambda triggers.

If a user provides an email address or phone number during sign-up, and you have selected automatic verification for your user pool, a confirmation code will be sent to the user’s phone number as a text message or to the user’s email address. The cognitoUserCodeDeliveryDetails object, which was delivered to the callback handler on successful sign-up, will indicate where this confirmation code was sent. You can use this to let the user known where to expect the confirmation code.

Create a callback handler to confirm the user. This callback handler is used by the SDK to  communicate the results of the confirmation API call.

// Call back handler for confirmSignUp API 
GenericHandler confirmationCallback = new GenericHandler() { 
    
    @Override 
    public void onSuccess() { 
        // User was successfully confirmed
    } 

    @Override
    public void onFailure(Exception exception) { 
        // User confirmation failed. Check exception for the cause.
    } 
};

When a new user is confirmed, the user’s attribute through which the confirmation code was sent (email or phone number) will be marked as verified. If this attribute is also set to be used as an alias, then the user will be able to sign-in with that attribute (email or phone number) instead of the username.

Alias values must be unique in a pool, and you have choices to resolve the situation if the same email or phone number is already being used as an alias for an existing user in the pool.

You can allow the user confirmation to fail if such conflicts are found, you can do this by setting the forcedAliasCreation parameter to false. The attribute will then remain verified for the existing user, and will continue to be an alias for the existing user. The new user will remain un-confirmed. 

Setting this parameter to true will resolve the conflict by marking the attribute (iemail or phone number) as verified for the new user, and consequently marking it as not-verified for the existing user. This attribute is no longer an alias for the existing user.

// This will cause confirmation to fail if the user attribute has been verified for another user in the same pool  
boolean forcedAliasCreation = false; 

// Call API to confirm this user 
cognitoUser.confirmSignUpInBackground(confirmationCode, forcedAliasCreation, confirmationCallback);

All confirmed users can sign-in. On successful sign-in, access and iID tokens are returned. These tokens are encapsulated in a CognitoUserSession object.

To sign in, start by creating an callback handler for authentication. During the sign-in process the SDK will interact with your app through this callback handler.

// Callback handler for the sign-in process 
AuthenticationHandler authenticationHandler = new AuthenticationHandler() { 
    
    @Override 
    public void onSuccess(CognitoUserSession cognitoUserSession) { 
        // Sign-in was successful, cognitoUserSession will contain tokens for the user   
    }
    
    @Override
    public void getAuthenticationDetails(AuthenticationContinuation authenticationContinuation, String userId) { 
        // The API needs user sign-in credentials to continue
        AuthenticationDetails authenticationDetails = new AuthenticationDetails(userId, password, null);

        // Pass the user sign-in credentials to the continuation
        authenticationContinuation.setAuthenticationDetails(authenticationDetails);

        // Allow the sign-in to continue
        authenticationContinuation.continueTask();
    }

    @Override
    public void getMFACode(MultiFactorAuthenticationContinuation multiFactorAuthenticationContinuation) { 
        // Multi-factor authentication is required, get the verification code from user
        multiFactorAuthenticationContinuation.setMfaCode(mfaVerificationCode);
        // Allow the sign-in process to continue
        multiFactorAuthenticationContinuation.continueTask();
    }

    @Override
    public void onFailure(Exception exception) {
        // Sign-in failed, check exception for the cause
    } 
};

// Sign-in the user 
cognitoUser.getSessionInBackground(authenticationHandler);

After authenticating a user, you can perform other operations on this user, such as getting user details

// Implement callback handler for get details call
GetDetailsHandler getDetailsHandler = new GetDetailsHandler() {
    @Override
    public void onSuccess(CognitoUserDetails cognitoUserDetails) {
        // The user detail are in cognitoUserDetails
    }
        
    @Override
    public void onFailure(Exception exception) { 
        // Fetch user details failed, check exception for the cause
    }
};

// Fetch the user details 
cognitoUser.getDetailsInBackground(getDetailsHandler);

To obtain AWS credentials to access AWS resources for your user, first associate your user pool with an identity pool using the AWS Management Console.  If you haven’t already created an identity pool, do that using the Amazon Cognito Console.  In the Authentication providers choose the Cognito tab, and then specify your User Pool ID and App Client ID.

Now add the ID tokens, received after successful authentication, to your credentials provider.

// Get id token from CognitoUserSession.
String idToken = cognitoUserSession.getIdToken().getJWTToken(); 

// Create a credentials provider, or use the existing provider.
CognitoCachingCredentialsProvider credentialsProvider = new CognitoCachingCredentialsProvider(context, IDENTITY_POOL_ID, REGION);

// Set up as a credentials provider.
Map<String, String> logins = new HashMap<String, String>(); 
logins.put("cognito-idp.us-east-1.amazonaws.com/us-east-1_123456678", cognitoUserSession.getIdToken().getJWTToken()); 
credentialsProvider.setLogins(logins);

For further details on integrating Cognito User Pools with Cognito Federated Identity pools see AWS Cognito User Pools documentation.

This was a quick walk-through to get you started with using Amazon Cognito User Pools in your app. You can find further details about the AWS Mobile SDK for Android in the API reference. The sample app is in this GitHub repository.

We would like to hear your comments about this feature. You can reach out to us by posting on the Amazon Cognito forum or the GitHub repository.