Share data across devices with Cognito Sync

TOC

Configure Cognito Sync to share user data between devices

This is the scope of the AWS DVA, which is about development using AWS services.
Cognito Sync can be used to share user data between devices.
This time, we will use AWS SDK for JavaScript v3 to operate Cognito Sync.

We will be using Cognito Sync, but it is currently recommended to use AWS AppSync instead of this feature.

If you’re new to Amazon Cognito Sync, use AWS AppSync. Like Amazon Cognito Sync, AWS AppSync is a service for synchronizing application data across devices.

Amazon Cognito Sync

Environment

Diagram of share data across devices with Cognito Sync.

Create an S3 bucket and enable the static website hosting feature.
Prepare content by placing HTML files inside.

Use the Cognito ID pool to grant access to Cognito Sync to users who have successfully signed in.
To validate Cognito Sync, we will create a function to store and share data about the background color of the browser. Specifically, we will perform the following steps:

  1. launch a browser, sign in to your personal page, and save the background color.
  2. launch another browser, sign in to your personal page again, and retrieve the background color in your browser.

CloudFormation template files

We will build the above configuration using CloudFormation.
In addition to the CloudFormation template, browser scripts, etc. are placed at the following URLs.

https://github.com/awstut-an-r/awstut-dva/tree/main/03/001

Template file points

We will cover the key points of each template file to configure this environment.

Grant temporary permissions to access Cognito Sync

Let’s check the identity pool itself.
The point is the IAM role for the privileges to be granted to the authenticated user.

Resources:
  IdentityPoolAuthenticatedRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Action: sts:AssumeRoleWithWebIdentity
            Principal:
              Federated: cognito-identity.amazonaws.com
            Condition:
              StringEquals:
                cognito-identity.amazonaws.com:aud: !Ref IdentityPool
              ForAnyValue:StringLike:
                cognito-identity.amazonaws.com:amr: authenticated
      Policies:
        - PolicyName: IdentityPoolAuthenticatedPolicy
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Effect: Allow
                Action:
                  - cognito-sync:*
                Resource:
                  - !Sub
                    - "arn:aws:cognito-sync:${AWS::Region}:${AWS::AccountId}:identitypool/${CognitoAud}/identity/${CognitoSub}/*"
                    - CognitoAud: ${cognito-identity.amazonaws.com:aud}
                      CognitoSub: ${cognito-identity.amazonaws.com:sub}
Code language: YAML (yaml)

Create a policy that allows the signed-in user to access Cognito Sync. You can create the policy by referring to the AWS official page IAM Roles and Role Trust and Access Permissions.

Browser Script

Use JavaScript to implement Cognito functionality after sign-in.
For instructions on how to create a browser script using AWS SDK for JavaScript v3, please see the following page.

あわせて読みたい
Using AWS SDK for JavaScript v3 in Browser 【Using AWS SDK for JavaScript v3 in Browser】 When developing Web applications using AWS, the best practice is to use the AWS SDK for JavaScript.The SDK is ...

This page focuses on Cognito Sync.

Using Cognito Sync to share data between devices takes the form of storing and retrieving data against a data set.

Amazon Cognito lets you save end user data in datasets containing key-value pairs. This data is associated with an Amazon Cognito identity, so that it can be accessed across logins and devices.

Synchronizing data

In this case, we will prepare a dataset called “preference”, manage background color data with the key name “background-color”, and create a function to register and retrieve background color.

ID token acquisition

In this configuration, the OAuth flow is set to Implicit Grant.
With Implicit Grant, an ID token can be obtained from URL parameters.

const params = new URLSearchParams(location.hash.slice(1));
const idToken = params.get("id_token");
Code language: JavaScript (javascript)

For more details, please check the following page

あわせて読みたい
Authorization by Cognito ID Pool after Authentication by User Pool – Implicit Grant Ver 【Authorization by Cognito ID Pool after Authentication by User Pool - Implicit Grant Ver】 Use the Cognito user pool and identity pool to grant signed-in us...

Create Cognito Sync Client

Create a client object to access Cognito Sync.

import {
  CognitoIdentityClient,
  GetIdCommand
} from "@aws-sdk/client-cognito-identity";

import {
  fromCognitoIdentityPool
} from "@aws-sdk/credential-provider-cognito-identity";

import {
  CognitoSyncClient,
  ListRecordsCommand,
  UpdateRecordsCommand
} from "@aws-sdk/client-cognito-sync";

const cognitoIdentityClient = new CognitoIdentityClient({ region: REGION });
const cognitoSyncClient = new CognitoSyncClient({
  region: REGION,
  credentials: fromCognitoIdentityPool({
    client: cognitoIdentityClient,
    identityPoolId: IDENTITY_POOL_ID,
    logins: {
      [`cognito-idp.${REGION}.amazonaws.com/${USER_POOL_ID}`]: idToken
    }
  })
});
Code language: JavaScript (javascript)

Import the required classes and functions from the installed package.
Use them to create a Cognito Sync client.

Store values in Cosnigo Sync dataset

Access to Cognito Sync is broadly divided into storing and retrieving values.
First, let’s check the storage method.

const identityId = response.IdentityId;
const setBackgroundColorToCognitoSyncDataset = async (color) => {
  const listRecordsResponse = await cognitoSyncClient.send(
    new ListRecordsCommand({
      DatasetName: DATASET,
      IdentityId: identityId,
      IdentityPoolId: IDENTITY_POOL_ID
    })
  );
  const syncSessionToken = listRecordsResponse.SyncSessionToken;
  const syncCount = (() => {
    for (let record of listRecordsResponse.Records) {
      if (record.Key == DATASET_KEY) {
        return record.SyncCount + 1;
      }
    }
    return 0;
  })();

  const response = await cognitoSyncClient.send(
    new UpdateRecordsCommand({
      DatasetName: DATASET,
      IdentityId: identityId,
      IdentityPoolId: IDENTITY_POOL_ID,
      RecordPatches: [{
        Key: DATASET_KEY,
        Op: "replace",
        SyncCount: syncCount,
        Value: color
      }],
      SyncSessionToken: syncSessionToken
    })
  );
  document.body.style.background = color;
};

window.setBackgroundColorToCognitoSyncDataset = setBackgroundColorToCognitoSyncDataset;

document.getElementById("button-set").addEventListener("click", function(event) {
  var color = document.getElementById("background-color").value;
  setBackgroundColorToCognitoSyncDataset(color);
});
Code language: JavaScript (javascript)

To store values in the Cognito Sync dataset using the AWS SDK for JavaScript v3, the following steps must be performed

  1. run ListRecordsCommand to get the dataset information and check the current SyncCount from the SyncSessionToken.
  2. execute UpdateRecordsCommand, specify the latest SyncCount, and then execute “replace”

To execute the above two commands, the Cognito ID is required, which is obtained by executing GetIdCommand.

ListRecordsCommand, which is executed to obtain the values of SyncSessionToken and SyncCount.
SyncCount is described in the API reference as follows

Last known server sync count for this record. Set to 0 if unknown.

RecordPatch

In other words, to store a value in the data set, it must be set to 0 the first time and incremented by the current value the second and subsequent times.

Among the parameters passed when executing UpdateRecordsCommand, RecordsPathes is the key point.
This parameter specifies the operation to be performed in addition to the value to be stored and the associated key. The operation is specified by the Op parameter.

An operation, either replace or remove.

RecordPatch

In this case, the objective is to update the value, so “replace” is specified to save the background color information.

The created function (setBackgroundColorToCognitoSyncDataset) is set as a global function.
In addition, set this function to be executed when the button for saving is pressed.

Retrieving values from Cognito Sync dataset

Then check the acquisition method.

const getBackgroundColorFromCognitoSyncDataset = async () => {
  const listRecordsResponse = await cognitoSyncClient.send(
    new ListRecordsCommand({
      DatasetName: DATASET,
      IdentityId: identityId,
      IdentityPoolId: IDENTITY_POOL_ID
    })
  );

  for (let record of listRecordsResponse.Records) {
    if (record.Key == DATASET_KEY) {
      document.body.style.background = record.Value;
      break;
    }
  }
};

window.getBackgroundColorFromCognitoSyncDataset = getBackgroundColorFromCognitoSyncDataset;

document.getElementById('button-get').addEventListener('click', function(event) {
  getBackgroundColorFromCognitoSyncDataset();
});
Code language: JavaScript (javascript)

To retrieve values from the Cognito Sync dataset using AWS SDK for JavaScript v3, execute the ListRecordsCommand.
From the retrieved records, check the keys and get the background color information.

This function (getBackgroundColorFromCognitoSyncDataset) is also set up as a global function.
This function is set to be executed when the button for acquisition is pressed.

S3 Static Website Hosting

The static website hosting feature publishes HTML files placed in S3 buckets.
Please see the following page for details.

あわせて読みたい
Publish your site with S3 static website hosting 【Configure the S3 static website hosting to publish your site】 Find out how to use the S3 static website hosting to publish a website. If your website cons...

Architecture

We will use CloudFormation to build this environment and check its actual behavior.

Create CloudFormation stacks and check resources in stacks

Create a CloudFormation stack.

For more information on how to create stacks and check each stack, please refer to the following page.

あわせて読みたい
CloudFormation’s nested stack 【How to build an environment with a nested CloudFormation stack】 Examine nested stacks in CloudFormation. CloudFormation allows you to nest stacks. Nested ...

After checking the resources for each stack, the following is the information for the main resources created this time.

  • Name of the S3 bucket: dva-03-001
  • Cognito user pool ID: ap-northeast-1_LCLoZND22
  • Cognito user pool app client ID: 2al2uf1i5bs4g9rc6ruu702mbu
  • Cognito user pool domain prefix: dva-03-001
  • Cognito ID pool ID: ap-northeast-1:800ca6c3-73fb-4c6f-ae5e-e0a91e7fb994

Place HTMLs in S3 bucket

Place the HTML in the S3 bucket and prepare the contents after sign-in/sign-out.

Put HTML for Cognito in S3 bucket

Access Cognito Sync: 1st device (browser)

Now that we are ready, let’s actually access the hosted UI.

First, launch your browser (Chrome) and access the following URL.

https://s3-ap-northeast-1.amazonaws.com/dva-03-001/index.html

Go to the Sign In page of Cognito UserPool.

Click “Sign In” to go to the sign-in page.

The sign-up process is required only for the first time. For more information about the signup process, please refer to Create sign-in page in the Cognito user pool – Accessing the hosted UI: Sign up. This time, we will register a user name of “awstut”.

User created in Cognito Userpool.
Details of the user created in the Cognito Userpool.

After signing in, you will see a page like the one below.

Set the background color to Cognito Sync.

Enter a background color in the right frame of background-color and press “set background-color”.

The background color will be reflected.

The background color has been changed successfully.

In addition to changing the background color, JavaScript saved “red” to the Cognito Sync data set.

Access Cognito Sync: 2nd device (browser)

Now, launch a different browser (Safari).

After signing in, access the above page.

Press “get background-color” to get the background color you have just set.

You can use Cognito Sync to get the background color on another device.

The background color has changed.

After accessing the Cognito Sync dataset and retrieving the data, I was able to change the background color successfully.

The above operation will register a new Identity ID in the ID pool.

Identity registered in the Cognito Id Pool

Looking at more details, we can also see that a data set called preference has been created.

Dataset created in the Cognito Id Pool.

The dataset is registered with “background-color” as the key and “red” as the value.

Store background color in the Dataset of Cognito Id Pool

By linking the user pool and identity pool in this way, Cognito Sync can be used.

Summary

We have confirmed that we can share data between devices by accessing the Cognito Sync dataset.

TOC