Amazon Cognito のユーザープールで記憶済みデバイスを使用するにはどうすればよいですか?
最終更新日: 2022 年 10 月 17 日
Amazon Cognito のユーザープールのユーザーがアプリのサインインに使用したデバイスを追跡したいと考えています。どうすればよいですか?
簡単な説明
Amazon Cognito は、ユーザープールのユーザーがサインインに使用するデバイスを追跡および記憶できます。デバイスの記憶をアクティブ化することで、サインインの制限を設定できます (例えば、ある 1 つのデバイスからのサインインを制限する)。または、ユーザーが同じデバイスから繰り返しサインインしなくてもよいようにすることができます。詳細については、「ユーザープールデバイス追跡設定の指定」を参照してください。
注: デバイストラッキング機能を使用するには、USER_SRP_AUTH 認証フローを使用する必要があります。記憶されたデバイスを使用して多要素認証 (MFA) を置き換えるには、ユーザープールの MFA もオンにする必要があります。
デバイスの記憶プロセスは、2 つの部分から構成されます。
- 新しいデバイスの確認。デバイスから認証を開始し、Amazon Cognito で確認して、一意のデバイス識別子を取得します。
- 確認済みデバイスの検証。確認済みデバイスから認証を開始し、それ以降のサインイン試行では MFA ステップをスキップします。
解決方法
注: 次の手順では、アプリクライアントのコードで実行する Amazon Cognito API コールについて説明します。AWS Mobile SDKs for Android または AWS Mobile SDKs for iOS などのクライアントサイド SDK を使用している場合は、実装の多くは SDK によって処理されます。
記憶済みデバイスのセットアップ
- Amazon Cognito コンソールで、[Manage user pools] (ユーザープールの管理) を選択し、次にユーザープールを選択します。
- 左のナビゲーションペインの [全般設定] で、[デバイス] を選択します。
- [Do you want to remember your user's devices] (ユーザーのデバイスを記憶しますか?) で、[Always] (常に) または [User Opt In] を選択します。詳細については、Amazon Cognito Your User Pools を使用したデバイスの追跡と記憶をご参照ください。
- [Do you want to use a remembered device to suppress the second factor during multi-factor authentication (MFA)] (記憶済みのデバイスを使用して、多要素認証 (MFA) 中に 2 つ目の要素を抑制しますか?) で、[Yes] (はい) または [No] (いいえ) を選択します。詳細については、「記憶済みデバイスを使用した多要素認証 (MFA、Multi-Factor Authentication) の停止」を参照してください。
注: これらのオプションが表示されない場合は、MFA はアクティブ化されていません。MFA を設定するには、左のナビゲーションペインで、[MFA and verifications] (MFA および検証) を選択します。 - [Save changes] (変更を保存) を選択します。
SetUserMFAPreference の呼び出し
アプリクライアントのコードで、SetUserMFAPreference API を呼び出して、使用している MFA メソッドの MFA 設定を [true] に設定します。
InitiateAuth の呼び出し
アプリクライアントのコードで、InitiateAuth API を呼び出してデバイスキーを取得します。この API リクエストには、必ず次のリクエストパラメータを含めてください。
- AuthFlow。USER_SRP_AUTH を使用します。
- AuthParameters。認証パラメータには、USERNAME、SRP_A、SECRET_HASH を含めます。
注意: SECRET_HASH は、アプリクライアントがクライアントシークレットを使用して設定されている場合のみ必要です。
次の式を使用して SRP_A を計算します。
SRP_A = ga (mod N)
- AWS Amplify (JavaScript) GitHub リポジトリの AuthenticationHelper.js で定義されているとおりに g を使用します。
- a = 128 ランダムバイトとします。
詳細については、「request syntax」(リクエスト構文) および選択した AWS SDK の API リファレンスを参照してください。
MFA チャレンジのために RespondToAuthChallenge を呼び出す
アプリクライアントが InitiateAuth API を呼び出すと、Amazon Cognito ユーザープールは、アクティブ化された MFA メソッドに基づいて MFA チャレンジのセットを返します。
アプリは、RespondToAuthChallenge API を使用するこれらのチャレンジに応答する必要があります。例えば、ユーザープールで SMS テキストメッセージの MFA をアクティブ化した場合は、パラメータ ChallengeName に SMS_MFA の値を含めます。詳細については、「request syntax」(リクエスト構文) および選択した AWS SDK の API リファレンスを参照してください。
デバイスキーの保存
すべての MFA チャレンジに応答すると、Amazon Cognito は NewDeviceMetadataType フィールドの DeviceGroupKey および一意の DeviceKey で応答します。
Android、iOS、JavaScript のいずれか向けの AWS Mobile SDK をブラウザで使用している場合は、これらのキーはアプリケーションによってデバイスのローカルストレージに自動的に移動されます。他の AWS SDK を使用している場合は、同様のキーストレージソリューションをアプリに設計するようにしてください。
ConfirmDevice を呼び出す
DeviceGroupKey および DeviceKey を使用して、Secure Remote Password (SRP) プロトコルでシークレットを作成します。SRP では、ソルトとパスワードの検証が生成されます。以下の リクエストパラメータを含む ConfirmDevice API 呼び出しで、これらを Amazon Cognito に渡します。
- AccessToken。ユーザーの有効なアクセストークンを使用します。
- DeviceKey。Amazon Cognito から返されたデバイスの一意のキーを使用します。
- DeviceName。デバイスに付ける名前を使用します。(AWS Mobile SDK はユーザーエージェントを使用します。)
- DeviceSecretVerifierConfig。Salt (16 ランダムバイト、base64 エンコード) および PasswordVerifier を含めます。
PasswordVerifier には、次の式を使用します。
PasswordVerifier = g( SHA256_HASH(salt + FULL_PASSWORD) ) (mod N)
- AWS Amplify (JavaScript) GitHub リポジトリの AuthenticationHelper.js で定義されているとおりに g を使用します。
- FULL_PASSWORD = SHA256_HASH(DeviceGroupKey + username + ":" + RANDOM_PASSWORD) とします。
- RANDOM_PASSWORD = 40 random bytes, base64-encoded とします。
- AWS Amplify (JavaScript) GitHub リポジトリの AuthenticationHelper.js で定義されているように N を使用します。
詳細については、「request syntax」(リクエスト構文) および選択した AWS SDK の API リファレンスを参照してください。
(オプション) UpdateDeviceStatus の呼び出し
ユーザープールに記憶されたデバイスをセットアップするときに、[Always] (常に) を選択すると、この手順を省略できます。[User Opt In] を選択した場合は、UpdateDeviceStatus API 呼び出しを含める必要があります。
注: Amazon Cognito Identity SDK for JavaScript を使用している場合は、代わりに setDeviceStatusRemembered または setDeviceStatusNotRemembered を呼び出す必要があります。詳細については、GitHub の SDK の README ファイルの Usage を参照してください。
アプリのユーザーにデバイスを記憶するオプションを付与する場合は、デバイスによってユーザープールで「記憶されていない」ものとして追跡されることを確認します。 デバイスを記憶させるかをユーザーに確認し、次に UpdateDeviceStatus API を使用して入力を送信する必要があります。
注意: オプトインが必要な場合は、ユーザーはオプトインしてからデバイスを記憶し、MFA チャレンジを抑制する必要があります。
デバイスキーによる InitiateAuth の呼び出し
アプリクライアントのコードで、InitiateAuth API を呼び出して、記憶済みデバイスを検証します。この呼び出しでは、次のようにリクエストパラメータにデバイスキーを含めます。
- AuthFlow。USER_SRP_AUTH を使用します。
- AuthParameters。認証パラメータ USERNAME、SRP_A、DEVICE_KEY を含めます。
詳細については、「request syntax」(リクエスト構文) および選択した AWS SDK の API リファレンスを参照してください。
DEVICE_SRP_AUTH のために RespondToAuthChallenge を呼び出す
アプリクライアントが有効なデバイスキーを使用して InitiateAuth API コールを実行すると、Amazon Cognito のユーザープールは PASSWORD_VERIFIER チャレンジを返します。チャレンジ応答に DEVICE_KEY を含める必要があります。その後、DEVICE_SRP_AUTH チャレンジを受け取ります。応答するには、RespondToAuthChallenge API を呼び出し、次のリクエストパラメータを含めます。
- ChallengeName。DEVICE_SRP_AUTH を使用します。
- ClientId。有効なアプリクライアント ID を使用します。
- ChallengeResponses。これらの応答には USERNAME、DEVICE_KEY、SRP_A を含めます。
注意: SRP_A の場合は、前述した式をこれらの手順で使用します。
この API を呼び出すと、Amazon Cognito はもう 1 つのチャレンジ DEVICE_PASSWORD_VERIFIER で応答します。この応答では、チャレンジへの応答に必要な ChallengeParameters の SECRET_BLOCK および SRP_B の値も取得します。
詳細については、「request syntax」(リクエスト構文) および選択した AWS SDK の API リファレンスを参照してください。
DEVICE_PASSWORD_VERIFIER に対する RespondToAuthChallenge の呼び出し
DEVICE_PASSWORD_VERIFIER チャレンジに応答するには、RespondToAuthChallenge API を呼び出し、次のリクエストパラメータを含めます。
- ChallengeName。DEVICE_PASSWORD_VERIFIERを使用します。
- ClientId。有効なアプリクライアント ID を使用します。
- ChallengeResponses。USERNAME、PASSWORD_CLAIM_SECRET_BLOCK、TIMESTAMP、PASSWORD_CLAIM_SIGNATURE、DEVICE_KEY を含めます。
チャレンジへの応答を次のように定義します。
- PASSWORD_CLAIM_SECRET_BLOCK では、SECRET_BLOCK の値を使用します。
- TIMESTAMP には、現在の時刻を含めます。(例: Tue Sep 25 00:09:40 UTC 2018)
- PASSWORD_CLAIM_SIGNATURE =SHA256_HMAC(K_USER, DeviceGroupKey+DeviceKey+PASSWORD_CLAIM_SECRET_BLOCK+TIMESTAMP), base64-encoded とします。
- K_USER = SHA256_HASH(S_USER) とします。
- Let S_USER = [ ( SRP_B - [ k * [ (gx) (mod N) ] ] )(a + ux) ](mod N) とします。
- x = SHA256_HASH(salt + FULL_PASSWORD) とします。
- u =SHA256_HASH(SRP_A+SRP_B) とします、
- k = SHA256_HASH(N + g) とします。
ユーザープールから JSON ウェブトークンの取得
最後のチャレンジに正常に応答すると、Amazon Cognito ユーザープールにより AuthenticationResult で JSON ウェブトークンが返されます。
{
"AuthenticationResult": {
"AccessToken": "...",
"ExpiresIn": 3600,
"IdToken": "...",
"RefreshToken": "...",
"TokenType": "Bearer"
},
"ChallengeParameters": {}
}