Cognito Syncでデバイス間でデータ共有

目次

Cognito Syncでデバイス間でユーザーデータを共有する

AWS DVAの出題範囲の1つでもある、AWSサービスを使用した開発に関する内容です。
Cognito Syncを使って、デバイス間でユーザーデータを共有することができます。
今回はAWS SDK for JavaScript v3を使用して、Cognito Syncを操作します。

なおCognito Syncですが、現在は本機能に代わって、AWS AppSyncを使用することが推奨されています。

Amazon Cognito Sync を初めて使用する場合は、AWS AppSync を使用してください。AWS AppSync は、Amazon Cognito Sync と同様に、デバイス間のアプリケーションデータを同期するためのサービスです。

Amazon Cognito Sync

構築する環境

Diagram of share data across devices with Cognito Sync.

S3バケットを作成し、静的ウェブサイトホスティング機能を有効にします。
内部にHTMLファイルを設置して、コンテンツを用意します。

Cognito IDプールを使用し、正常にサインインしたユーザーに対して、Cognito Syncへのアクセスを許可します。
Cognito Syncの検証ですが、ブラウザの背景色に関する情報を保存・共有する機能を作成します。具体的には以下の手順で実施します。

  1. ブラウザを起動し、個人ページにサインインし、背景色を保存する。
  2. 別ブラウザを起動し、改めて個人ページにサインイン後、ブラウザで背景色を取得する。

環境構築用のCloudFormationテンプレートファイル

上記の構成をCloudFormationで構築します。
以下のURLに、CloudFormationテンプレートに加え、ブラウザスクリプト等を配置してます。

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

テンプレートファイルのポイント解説

今回の環境を構成するための、各テンプレートファイルのポイントを取り上げます。

Cognito Syncにアクセスするための一時的な権限を付与する

IDプール本体を確認します。
ポイントは認証ユーザーに付与する権限用のIAMロールです。

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)

サインインしたユーザーに対して、Cognito Syncへアクセスすることを許可するポリシーを作成します。ポリシーはAWS公式ページIAM ロールおよびロールの信頼とアクセス権限を参考にして作成します。

ブラウザスクリプト

JavaScriptを使用して、サインイン後のCognito機能を実装します。
AWS SDK for JavaScript v3を使用してブラウザスクリプトを作成する手順は、以下のページをご確認ください。

あわせて読みたい
ブラウザでAWS SDK for JavaScript v3を扱う 【ブラウザでAWS SDK for JavaScript v3を扱う】 AWSを使用してWebアプリを開発する場合、AWS SDK for JavaScriptの使用がベストプラクティスとなります。同SDKには2つ...

本ページでは、Cognito Syncを中心に取り上げます。

Cognito Syncを使って、デバイス間でデータ共有を行うためには、データセットに対して、データを保存・取得するという形を取ります。

Amazon Cognito では、キー/値ペアが含まれるデータセットにエンドユーザーデータを保存することができます。このデータは、ログインとデバイス全体でアクセスできるように Amazon Cognito ID と関連付けられます。

データの同期

今回は「preference」というデータセットを用意し、「background-color」というキー名で背景色データを管理し、背景色を登録・取得する機能を作成します。

IDトークン取得

今回の構成では、OAuthフローにImplicit Grant(暗黙の付与)を設定しています。
Implicit Grantですと、URLパラメータからIDトークンを取得することができます。

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

詳細は以下のページをご確認ください。

あわせて読みたい
Cognitoユーザープールの認証後にIDプールで権限を与える(Implicit Grant編) 【Cognitoユーザープールの認証後にIDプールで権限を与える】 CognitoユーザープールとIDプールを使用して、サインインユーザーにAWSリソースにアクセスするための権限...

Cognito Syncクライアント作成

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)

インストール済みのパッケージの中から、必要なクラスや関数をインポートします。
それらを使用して、Cognito Syncクライアントを作成します。

Cosnigo Syncデータセットに値を保存する

Cognito Syncへのアクセスを、値の保存と取得に大別します。
まずは保存方法を確認します。

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)

AWS SDK for JavaScript v3を使用して、Cognito Syncデータセットに値を保存するためには、以下の手順を実行する必要があります。

  1. ListRecordsCommandを実行して、データセット情報を取得し、SyncSessionTokenから、現在のSyncCountを確認する。
  2. UpdateRecordsCommandを実行して、最新のSyncCountを指定の上、「replace」を実行する

上記の2コマンドを実行するためには、Cognito IDが必要になりますので、GetIdCommandを実行して取得します。

ListRecordsCommandですが、これはSyncSessionTokenおよびSyncCountの値を取得するために実行します。
SyncCountですが、APIリファレンスでは、以下のように説明されています。

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

RecordPatch

つまりデータセットに値を保存するためには、初回時は0を、2回目以降は現在の値をインクリメントした値を指定する必要があります。

UpdateRecordsCommandを実行時に渡すパラメータの中で、RecordsPathesがポイントです。
本パラメータにて、保存する値や関連づけるキーに加え、実行する操作を指定します。操作はOpパラメータで指定します。

An operation, either replace or remove.

RecordPatch

今回は値を更新することが目的ですので、「replace」を指定することで、背景色情報を保存します。

作成した関数(setBackgroundColorToCognitoSyncDataset)をグローバルな関数をして設定します。
加えて保存用のボタンが押下された際に、本関数が実行されるように設定します。

Cognito Syncデータセットから値を取得する

続いて取得方法を確認します。

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)

AWS SDK for JavaScript v3を使用して、Cognito Syncデータセットの値を取得するためには、ListRecordsCommandを実行します。
取得したレコードの中から、キーをチェックして、背景色情報を取得します。

こちらの関数(getBackgroundColorFromCognitoSyncDataset)も、グローバルな関数をして設定します。
取得用のボタンが押下された際に、本関数が実行されるように設定します。

S3の静的ウェブサイトホスティング機能

静的ウェブサイトホスティング機能で、S3バケットに設置したHTMLファイルを公開します。
詳細は以下のページをご確認ください。

あわせて読みたい
S3静的ウェブサイトホスティング機能でサイトを公開する 【S3静的ウェブサイトホスティング機能でサイトを公開する構成】 S3の静的ウェブサイトホスティング機能を使って、ウェブサイトを公開する方法を確認します。 ウェブサ...

環境構築

CloudFormationを使用して、本環境を構築し、実際の挙動を確認します。

CloudFormationスタックを作成し、スタック内のリソースを確認する

CloudFormationスタックを作成します。

スタックの作成および各スタックの確認方法については、以下のページをご確認ください。

あわせて読みたい
CloudFormationのネストされたスタックで環境を構築する 【CloudFormationのネストされたスタックで環境を構築する方法】 CloudFormationにおけるネストされたスタックを検証します。 CloudFormationでは、スタックをネストす...

各スタックのリソースを確認した結果、今回作成された主要リソースの情報は以下の通りです。

  • S3バケットの名前:dva-03-001
  • CognitoユーザープールのID:ap-northeast-1_LCLoZND22
  • Cognitoユーザープール アプリクライアントのID:2al2uf1i5bs4g9rc6ruu702mbu
  • Cognitoユーザープール ドメインプレフィックス:dva-03-001
  • Cognito IDプールのID:ap-northeast-1:800ca6c3-73fb-4c6f-ae5e-e0a91e7fb994

S3バケットにHTMLを設置する

S3バケットにHTMLを設置し、サインイン/サインアウト後のコンテンツを用意します。

Put HTML for Cognito in S3 bucket

Cognito Syncにアクセスする:1台目のデバイス(ブラウザ)

準備が整いましたので、実際にホストされたUIにアクセスします。

まずブラウザ(Chrome)を起動し、以下のURLにアクセスします。このブラウザをデバイスと見立てて進めます。

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

するとルートページであるindex.htmlが表示されます。

Go to the Sign In page of Cognito UserPool.

「Sign In」を押下すると、サインインページが表示されます。初回に限り、サインアップ処理を必要です。サインアップ処理に関しては、Cognito ユーザープールでログインページを作成する – ホストされたUIにアクセスする:サインアップをご確認ください。今回は「awstut」というユーザー名を登録します。

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

サインイン後は以下のようなページが表示されます。

Set the background color to Cognito Sync.

background-colorの右枠に背景色を入力し、「set background-color」を押下します。

The background color will be reflected.

無事に背景色が変化しました。

JavaScriptによって、背景色を変更したことに加え、Cognito Syncのデータセットに「red」を保存しました。

Cognito Syncにアクセスする:2台目のデバイス(ブラウザ)

今度は別ブラウザ(Safari)を起動します。

サインイン後、上記ページにアクセスします。先ほど設定した背景色を取得するために、「get background-color」を押下します。

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

背景色が変化しました。

Cognito Syncのデータセットにアクセスしてデータを取得後、正常に背景色を変更することができました。

なお上記の操作によって、IDプールに新しいIdentity IDが登録されます。

Identity registered in the Cognito Id Pool

さらに詳細を見ると、preferenceというデータセットが作成されていることもわかります。

Dataset created in the Cognito Id Pool.

データセットのキーとして「background-color」、値として「red」が登録されています。

Store background color in the Dataset of Cognito Id Pool

このようにユーザープールとIDプールを連携させることによって、Cognito Syncを使用することができます。

まとめ

Cognito Syncのデータセットにアクセスすることで、デバイス間でデータを共有できることを確認しました。

目次