Front-End Web & Mobile

Amazon Cognito in your Node.js web app

Today’s post comes from Michael Garcia, Solutions Architect for AWS. Based in Paris, he helps our customers and partners gain proficiency with AWS services and solutions.

———————————————————————————————————

Recently, we published articles on how to use Amazon Cognito in different contexts such as Amazon Cognito Credentials providers for mobiles or Amazon Cognito for synchronizing data. If you haven’t already, you should read how to use Amazon Cognito in your website because today we are going to focus on an implementation of Amazon Cognito in a website using the Node.js SDK.

Imagine we are a video game editor and we want our end users to be able to play our game inside a browser as well as on their smart phones. To make the authentication of our users across different platforms and different devices very easy and secure, we decide to use Amazon Cognito. We will use Amazon as our identity provider (other identity providers are supported with Amazon Cognito such as Facebook and Google).

In this scenario, the mini-game we will develop is simple. A player has a gauge with a scale of 0 to 100 that represents his life’s points. He can then click on two buttons to add or subtract points.

We need a simple way to persist data between the mobile and web platforms so we will use the Amazon Cognito’s datastore for that purpose.

Our Node.js website will contain two parts:

  • Delegation of user authentication using Amazon.com as an identity provider.
  • A mini-game that will leverage Amazon Cognito’s datastore.

Let’s log into the Node.js web app and play the mini-game.

Login with Amazon

Amazon Cognito supports unauthenticated and authenticated users, but in this application, we will authorize only authenticated users. This means that we first have to login before being able to access the rest of the app.

Once the “Login with Amazon” button is hit, the user will have to authenticate using his Amazon credentials.

At this point, the user is redirected to the callback URL of the Node.js app. In the callback function, we retrieve multiple pieces of information on the user:

  • Name
  • Email address
  • Amazon token (token from the identity provider)

We now have to call Amazon Cognito in order to get a unique Cognito ID for our user. This Cognito ID will represent our identity.

//Params for making the API call
var params = {
    AccountId: AWS_ACCOUNT_ID, // AWS account Id
    RoleArn: IAM_ROLE_ARN, // IAM role that will be used by authentication
    IdentityPoolId: COGNITO_IDENTITY_POOL_ID, //ID of the identity pool
    Logins: {
        'www.amazon.com': AMAZON_TOKEN //Token given by Amazon
        }
};
    
//Initialize the Credentials object
AWS.config.credentials = new AWS.CognitoIdentityCredentials(params);

//Call to Amazon Cognito, get the credentials for our user
AWS.config.credentials.get(err,data){…}

 

The first time that the user connects, Amazon Cognito will create a new and unique Cognito ID for the user. This Cognito ID will be linked to the Amazon account thanks to the token given by the identity provider. As such, Amazon Cognito will be able to match the Amazon account to the same user and deliver the same Cognito ID at the next connection.

Retrieving data from Amazon’s Cognito datastore

Now that we have retrieved a Cognito ID for our user, we will list the records contained in the Amazon Cognito’s dataset used by the app; for that, we will need to instantiate the Amazon Cognito Sync client. The goal is to retrieve the current state of the mini-game.

By using the previous call to get a Cognito ID, it is now really easy to instantiate the Amazon Cognito Sync client:

// Other AWS SDKs will automatically use the Cognito Credentials provider
// configured in the JavaScript SDK.
cognitosync = new AWS.CognitoSync();

We will use this client to retrieve information on the dataset used by the app with the listRecords function. This functions either returns data if the dataset is not empty or creates an empty dataset if it does not exist. This will be useful when the user connects for the first time because no dataset will exist at this time.

 

//Call to the listRecords function of the Amazon Cognito’s API
cognitosync.listRecords({
    DatasetName: COGNITO_DATASET_NAME, //Name of the dataset 
    IdentityId: COGNITO_IDENTITY_ID, //Cognito ID of the user
    IdentityPoolId: COGNITO_IDENTITY_POOL_ID //Cognito identity pool ID
}, function(err, data) {
    if ( !err ) {
        //Store dataset metadata and SyncSessionToken in the user’s session 
        //for subsequent calls to the API where it is required.
        req.user.COGNITO_SYNC_TOKEN = data.SyncSessionToken;
        req.user.COGNITO_SYNC_COUNT = data.DatasetSyncCount;

        //Retrieve information on the dataset
        var dataRecords = JSON.stringify(data.Records);
    }
});

 

The website can now display information coming from Amazon on the user (name, email address) as well as information retrieved from Amazon Cognito’s dataset. The “Play !” section display is dynamic and only appears once the user is authenticated. In this screenshot, the user already has 25 points in the gauge.

Interacting with the data

Now it’s time to play with the three buttons that appear under the “Play !” section. The heart icon will add 25 points to the gauge, and the bomb icon will subtract 25 points from the gauge. The refresh icon can be used to synchronize the data if you are making modifications to the dataset at the same time on another platform—for example, if you are using the mobile sample app.

If a user clicks on the heart or the bomb icon, we will need to update the dataset with a new value so that the gauge can reflect that change. Before we can update the dataset, we must make a listRecords call as described above in order to retrieve the SyncSessionToken from the API. This token is required if you want to make an operation on the dataset (replace or delete). Once we have the SyncSessionToken in our possession (stored in the user’s session in our example), we will use the Amazon Cognito client once more to interact with the dataset.

This time we will call the updateRecords function:

//Parameters for updating the dataset
var params = {
    DatasetName: COGNITO_DATASET_NAME, //Dataset name
    IdentityId: req.user.COGNITO_IDENTITY_ID, //Cognito ID of the user
    IdentityPoolId: COGNITO_IDENTITY_POOL_ID, //Identity pool ID
    SyncSessionToken: req.user.COGNITO_SYNC_TOKEN, // SyncSessionToken
//retrieved from the previous API call to listRecords 
    RecordPatches: [{
        Key: COGNITO_KEY_NAME, //Name of the key to update
        Op: 'replace', //Replace operation to update the dataset
        SyncCount: req.user.COGNITO_SYNC_COUNT, 
        Value: req.user.CURRENT_LIFE //Value of the gauge to update
    }]
};

//Make the call to Amazon Cognito to update the dataset
cognitosync.updateRecords(params, function(err, data) {
    if ( !err ) {
        //Store dataset metadata and SyncSessionToken in the user’s session 
        //for subsequent calls to the API where it is required.
        req.user.COGNITO_SYNC_TOKEN = data.SyncSessionToken;
        req.user.COGNITO_SYNC_COUNT = data.DatasetSyncCount;

        //Retrieve information returned by the call
        var dataRecords = JSON.stringify(data.Records);
    }
});

As you can see on this screenshot, after clicking twice on the heart icon the gauge now contains 75 points. The data returned mentions the key that we changed in the dataset and the new value, reflected by the gauge.

What’s next?

We’ve seen how easy it is to integrate with Amazon Cognito and how a developer can benefit from its authentication and data synchronization features. Your users will benefit from those features as well, because they will get a smooth experience transitioning from one device or platform to another.

You can now implement these features in your websites as well as on your mobile apps using the AWS SDKs. You can also play around with the sample app to extend it. For example, you could authorize unauthenticated users to interact with it as well.