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 provides the following features:
Today we will discuss User Pools and Federated Identities in detail.
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.
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.
Please perform the following steps to create a User Pool from the console.
Now, we will explore an Amazon Cognito User Pool example to sign up and sign in the user.
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.
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);
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:
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:
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.
*/
}
};
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 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.
Please perform the following steps to create a new Identity Pool from the console:
Here Cognito has been selected for a valid Authentication provider by adding User Pool ID and App client id:
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.
Keep your serverless AWS applications secure [Tutorial]
Amazon Neptune, AWS’ cloud graph database, is now generally available
How to start using AWS