Amazon Cognito: Managing Mobile Account Data

Amazon Cognito allows secure authentication in a world where mobile apps are regularly being accessed by individuals using multiple smart devices

Amazon Cognito is an Amazon Web Service that offers mobile identity management and data synchronization across devices. We’ll first take some time to make sure we’re clear about exactly what Cognito does, then we’ll dive right in with a simple Java application.

First though, just what are data synchronization and identity management?

With the explosion in mobile applications being accessed by individuals using multiple smart devices, keeping accounts consistent and updated has been a challenge. The trick is to effectively manage user data like settings, preferences, and application state. Launching a simple app can now require the infrastructure to managing details like data sync, network state and storage.

Amazon Cognito addresses these challenges and allows developers to concentrate more on application development.

In the days before Amazon Cognito, Identity Management naturally required authentication before gaining application access to any AWS resources. An application would need to pass in a valid AWS account ID and its credentials (both Secret Key and Access Key). Securing AWS credentials dynamically was always a concern: One cannot hard code the credentials within applications, as that breaks best practices. Storing credentials on an encrypted file system doesn’t sound like a perfect solution either.

Amazon Cognito offers a reliable and secure way to access AWS resources without having to produce credentials upfront (although AWS account details are still required). The system gives your users unique identifiers and ensures that they remain consistent across devices.

How does this work? Amazon Cognito has users authenticate via public login Providers (like Google and Facebook). With Cognito now in the driver’s seat, your app’s permissions are carefully respected while it gains access to precisely the AWS resources it needs. Your users will enjoy their smooth experience, while you can remain confident that your credentials aren’t dangerously exposed.

This illustrates the authentication flow when an app tries to access AWS services via public login providers:
Amazon Cognito authentication system via public login providers

Developer authentication system

For various reasons, mobile app users sometimes choose not to use the account of a public login provider, but rather prefer the authentication mechanism provided by the application itself. Amazon Cognito is flexible enough to allow application developers their own authentication systems.

This diagram shows the authentication workflow for an app trying to access AWS services via a developer authentication system:
Amazon Cognito developer authentication system

Getting Started with Amazon Cognito

Now let’s see how the authentication actually works. We’ll try writing some application code to get a feel for making API calls like GetId, GetOpenIdToken, AssumeRoleWithWebIdentity, and most importantly, the AWS Security Token Service (STS).

In this example, we’ll use Amazon Cognito with an application that doesn’t have required AWS credentials, but can still access the AWS S3 service to upload a file from local file system:

1. Create an identity pool in the Amazon Cognito console. The pool will look like the image below. The identity pool will let you create a new IAM role (or use the existing one) for your app user. Once you have an IAM role, it will give you access to the necessary AWS resources using temporary credentials. We’ll see how identity pool details will be used in application code in just a moment.
Create an identity pool in the Amazon Cognito console
As you can see, by checking “Enable access to unauthenticated identities”, we are allowing unauthorized users. But because we are doing so, we have to be very careful assigning privileges to this user. This can be controlled by attaching an appropriate policy for the corresponding role.

For our example, the policy for the Cognito_testcognitoidentityUnauth_Role should be:
Amazon Cognito policy role
2. Make a note of the ARN, as we will use it while writing the application. Click “Show ARN” to get the details, as below:
Amazon Cognito ARN 3. Now, if you have Eclipse running, create a simple java project with a class called TestAWSCognitoIdentityProvider, using this content for the class:

import java.io.File;
import java.util.Date;
import com.amazonaws.auth.AWSSessionCredentials;
import com.amazonaws.auth.AnonymousAWSCredentials;
import com.amazonaws.auth.BasicSessionCredentials;
import com.amazonaws.services.cognitoidentity.AmazonCognitoIdentity;
import com.amazonaws.services.cognitoidentity.AmazonCognitoIdentityClient;
import com.amazonaws.services.securitytoken.model.Credentials;
import com.amazonaws.services.cognitoidentity.model.GetIdRequest;
import com.amazonaws.services.cognitoidentity.model.GetIdResult;
import com.amazonaws.services.cognitoidentity.model.GetOpenIdTokenRequest;
import com.amazonaws.services.cognitoidentity.model.GetOpenIdTokenResult;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.model.PutObjectRequest;
import com.amazonaws.services.securitytoken.AWSSecurityTokenService;
import com.amazonaws.services.securitytoken.AWSSecurityTokenServiceClient;
import com.amazonaws.services.securitytoken.model.AssumeRoleWithWebIdentityRequest;
import com.amazonaws.services.securitytoken.model.AssumeRoleWithWebIdentityResult;
public class TestAWSCognitoIdentityProvider {
  /**
  As far a
  * @param args
  */
  public static void main(String[] args) {
    // initialize the Cognito identity client with a set
    // of anonymous AWS credentials
    AmazonCognitoIdentity identityClient = new AmazonCognitoIdentityClient(new AnonymousAWSCredentials());
    identityClient.setEndpoint(“<<set endpoint for AWS cognito>>”);
    GetIdRequest idRequest = new GetIdRequest();
    idRequest.setAccountId(“<<Here you should give your aws accound number>>“);
    idRequest.setIdentityPoolId(“<<Provide endpoint for identitypool>>“);
    GetIdResult idResp = identityClient.getId(idRequest);
    String identityId = idResp.getIdentityId();
    GetOpenIdTokenRequest tokenRequest = new GetOpenIdTokenRequest();
    tokenRequest.setIdentityId(identityId);
    GetOpenIdTokenResult tokenResp = identityClient.getOpenIdToken(tokenRequest);
    String openIdToken = tokenResp.getToken();
    AWSSecurityTokenService stsClient = new AWSSecurityTokenServiceClient(new AnonymousAWSCredentials());
    AssumeRoleWithWebIdentityRequest stsReq = new AssumeRoleWithWebIdentityRequest();
    stsReq.setRoleArn(“<<Provde the ARN that was noted down in step 2>>“);
    stsReq.setWebIdentityToken(openIdToken);
    stsReq.setRoleSessionName(“AppTestSession”);
    AssumeRoleWithWebIdentityResult stsResp = stsClient.assumeRoleWithWebIdentity(stsReq);
    Credentials stsCredentials = stsResp.getCredentials();
    AWSSessionCredentials sessionCredentials = new BasicSessionCredentials(
      stsCredentials.getAccessKeyId(),
      stsCredentials.getSecretAccessKey(),
      stsCredentials.getSessionToken()
    );
    Date sessionCredentialsExpiration = stsCredentials.getExpiration();
    System.out.println(sessionCredentials.getAWSAccessKeyId());
    String bucketName = “<<Existing bucket name>>”;
    String keyName = “cognitokey”;
    String uploadFileName = “<<File name with path>>”;
    AmazonS3 s3client = new AmazonS3Client(sessionCredentials);
    s3client.setEndpoint(“<<Provide S3 endpoint>>”);
    File file = new File(uploadFileName);
    s3client.putObject(new PutObjectRequest(bucketName, keyName, file));
  }
}

Now let’s try to understand the code. Once you’ve created the identity pool, you need to call the GetId API, providing your AWS account and identity pool details in order to retrieve a unique identifier (also known as a Cognito ID) for your end user.Amazon Cognito ID request
Now, use the Cognito ID to get an OpenID token. By exchanging your OpenID token with STS (Security token service), you can get temporary, limited-privilege AWS credentials.Amazon Cognito - Get open ID token
AssumeRolewithWebIdentity returns a set of temporary security credentials for users who have been authenticated in a mobile or web application through an OpenID Connect-compatible web identity provider. Besides AssumeRolewithWebIdentity, STS supports other actions. This explains how we used the AWS S3 client with temporary credentials to upload files, instead of having to present a user’s permanent secret key and access key.

Note: To avoid any compilation/runtime errors, make sure you have these jars available in the build path. Or if you are using Maven, make sure you’ve taken care of all dependencies.
Amazon Cognito - Java build path
4. Once you are all set, you can run this Java program and then verify in S3 whether the file was uploaded or not.

Summary: Amazon Cognito facts

  • Amazon Cognito can be used with Amazon, Facebook, Twitter, Digits, Google, and any other OpenID Connect-compatible identity provider.
  • Amazon Cognito supports unauthenticated guest users (i.e., users who do not authenticate with your own identity system or with one of the supported Identity Providers).
  • Cognito events can be integrated with Amazon Lambda.
  • Data is encrypted at rest in the Amazon Cognito sync store, and all identity data is transmitted over HTTPS.
  • Charges for Amazon Cognito are based on the total amount of app data stored in the Amazon Cognito sync store and the number of sync operations performed. With the AWS Free Tier, you receive 10GB of sync store and 1,000,000 sync operations per month for up to 12 months. After that, it will cost $0.15 per GB of sync store per month and $0.15 for each 10,000 sync operations.
  • AWS Cognito is currently available in the US East (N. Virginia), EU (Ireland), and Asia Pacific (Tokyo) regions.
  • AWS Cognito streams allow streaming user identity data from AWS Cognito to Amazon Kinesis.

Get a hands-on training experience and learn how to manage authentication with Amazon Cognito with Cloud Academy’s lab.

Please add your experiences or thoughts to the comments below.

 

Cloud Academy