如何在 Amazon Cognito 用户池中使用记住的设备?

上次更新日期:2021 年 8 月 17 日

我想跟踪 Amazon Cognito 用户池中的用户用于登录我的应用程序的设备。该如何操作?

简短描述

Amazon Cognito 可以跟踪和记住用户池中的用户用于登录的设备。通过启用设备记忆功能,您可以设置登录限制(例如,限制从某个设备登录)。或者,您可以让用户跳过同一设备上的重复登录。有关更多信息,请参阅指定用户池设备跟踪设置

注意:记忆设备功能仅可用于 USER_SRP_AUTH 身份验证流程。此外,此功能需要为用户池启用多重身份验证 (MFA)

记住设备是一个两步过程:

  • 确认新的设备。从设备启动身份验证,然后使用 Amazon Cognito 进行确认以获取唯一的设备标识符。
  • 验证已确认的设备。从已确认的设备启动身份验证,以在随后的登录尝试中跳过 MFA 步骤。

解决方法

注意:以下说明概要描述了在应用程序客户端代码中进行的 Amazon Cognito API 调用。如果您使用的是客户端开发工具包,例如适用于 Android 或 iOS 的 AWS 移动开发工具包,则大部分实现都由开发工具包处理。

设置记住的设备

  1. Amazon Cognito 控制台中,选择 Manage user pools (管理用户池),然后选择您的用户池。
  2. 在左侧导航窗格中的一般设置下,选择设备
  3. 对于 Do you want to remember your user's devices (您是否想要记住您用户的设备),请选择 Always (始终)User Opt I (用户选择加入)。有关更多信息,请参阅使用 Amazon Cognito 跟踪和记住您用户池中的设备
  4. 对于 Do you want to use a remembered device to suppress the second factor during multi-factor authentication (MFA) (您是否想要在多重身份验证 (MFA) 期间使用记住的设备阻止第二因素),请选择 Yes (是)No (否)。有关更多信息,请参阅使用记住的设备来阻止多重身份验证 (MFA)
    注意:如果这些选项不出现,则 MFA 未启用。要设置 MFA,在左侧导航窗格中选择 MFA and verifications (MFA 和验证)
  5. 选择 Save changes (保存更改)。

有关更多信息,请参阅指定用户池设备跟踪设置

调用 SetUserMFAPreference

在您的应用程序客户端代码中,调用 SetUserMFAPreference API,为您要使用的 MFA 方法将 MFA 首选项设置为 true

调用 InitiateAuth

在您的应用程序客户端代码中,调用 InitiateAuth API 来获取设备密钥。在此 API 请求中,确保包含以下请求参数

  • AuthFlow。使用 USER_SRP_AUTH
  • AuthParameters。包含身份验证参数 USERNAMESRP_ASECRET_HASH
    注意:仅当您的应用程序客户端配置了客户端密钥时,才需要SECRET_HASH

使用以下公式计算 SRP_A

SRP_A = ga (mod N)

  • 使用 AWS Amplify (JavaScript) GitHub 存储库上 AuthenticationHelper.js 中定义的 g
  • a = 128 个随机字节

有关更多信息,请参阅请求语法您选择的 AWS 开发工具包的 API 参考

为 MFA 质询调用 RespondToAuthChallenge

应用程序客户端调用 InitiateAuth API 之后,您的 Amazon Cognito 用户池将根据您启用的 MFA 方法返回一系列 MFA 质询。

您的应用程序必须使用 RespondToAuthChallenge API 应答这些质询。例如,如果您在用户池中启用了 SMS 文本消息 MFA,则参数 ChallengeName 要包含值 SMS_MFA。有关更多信息,请参阅请求语法您选择的 AWS 开发工具包的 API 参考

存储设备密钥

应答所有 MFA 质询后,Amazon Cognito 会在 NewDeviceMetadataType 字段中以 DeviceGroupKey 和唯一的 DeviceKey 进行响应。

如果您在浏览器中使用适用于 Android、iOS 或 JavaScript 的 AWS 移动开发工具包,则这些密钥将由应用程序自动移至设备的本地存储中。如果您使用的是其他 AWS 开发工具包,请确保为您的应用程序设计类似的密钥存储解决方案。

调用 ConfirmDevice

对于 DeviceGroupKeyDeviceKey,使用安全远程密码 (SRP) 协议创建一个秘钥,该协议会生成一个 salt 和一个密码验证程序。通过包含以下请求参数ConfirmDevice API 调用将这些传递到 Amazon Cognito:

  • AccessToken。使用对于用户有效的访问令牌。
  • DeviceKey。用从 Amazon Cognito 返回的设备唯一密钥。
  • DeviceName。使用您给设备指定的名称。(AWS 移动软件开发工具包使用用户代理。)
  • DeviceSecretVerifierConfig。包括 Salt(16 个随机字节,以 base64 编码)和 PasswordVerifier

对于 PasswordVerifier:使用以下公式:

PasswordVerifier = g(salt + FULL_PASSWORD) (mod N)

  • 使用 AWS Amplify (JavaScript) GitHub 存储库上 AuthenticationHelper.js 中定义的 g
  • FULL_PASSWORD = SHA256_HASH(DeviceGroupKey + username + ":" + RANDOM_PASSWORD)
  • RANDOM_PASSWORD = 40 个随机字节,以 base64 编码
  • 使用 AWS Amplify (JavaScript) GitHub 存储库上 AuthenticationHelper.js 中定义的 N

有关更多信息,请参阅请求语法您选择的 AWS 开发工具包的 API 参考

(可选)调用 UpdateDeviceStatus

在设置记住用户池中的设备时,如果选择 Always(始终),则可以跳过此步骤。如果您选择 User Opt In(用户选择加入),则必须包含 UpdateDeviceStatus API 调用。

注意:如果您使用适用于 JavaScript 的 Amazon Cognito 身份开发工具包,则必须调用 setDeviceStatusRememberedsetDeviceStatusNotRemembered。有关更多信息,请参阅 GitHub 上开发工具包 README 文件中的 使用情况

当您为应用程序的用户提供记住其设备的选项时,请确认该设备在您的用户池中将作为“未记忆”来跟踪。 您必须询问用户是否要记住设备,然后使用 UpdateDeviceStatus API 发送其输入。

注意:当需要选择加入时,用户必须选择加入才能记住其设备并阻止 MFA 质询。

使用设备密钥调用 InitiateAuth

在您的应用程序客户端代码中,调用 InitiateAuth API 来验证记住的设备。在此调用中,在请求参数中包含设备密钥,如下所示:

  • AuthFlow。使用 USER_SRP_AUTH
  • AuthParameters。包含身份验证参数 USERNAMESRP_ADEVICE_KEY

有关更多信息,请参阅请求语法您选择的 AWS 开发工具包的 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。在这些响应中包含 USERNAMEDEVICE_KEYSRP_A
    注意:对于 SRP_A,使用说明中前面提到的公式。

调用此 API 后,Amazon Cognito 将以另一个质询响应:DEVICE_PASSWORD_VERIFIER。在响应中,您还将获得 ChallengeParameters SECRET_BLOCKSRP_B 的值,可供响应质询之用。

有关更多信息,请参阅请求语法您选择的 AWS 开发工具包的 API 参考

为 DEVICE_PASSWORD_VERIFIER 调用 RespondToAuthChallenge

要响应 DEVICE_PASSWORD_VERIFIER 质询,调用 RespondToAuthChallenge API 并包含以下请求参数

  • ChallengeName。使用 DEVICE_PASSWORD_VERIFIER
  • ClientId。使用有效的应用程序客户端 ID。
  • ChallengeResponses。包含 USERNAMEPASSWORD_CLAIM_SECRET_BLOCKTIMESTAMPPASSWORD_CLAIM_SIGNATUREDEVICE_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 编码
  • K_USER = SHA256_HASH(S_USER)
  • S_USER = (SRP_B - k * gx)(a + ux)
  • x = SHA256_HASH(salt + FULL_PASSWORD)
  • u = SHA256_HASH(SRP_A + SRP_B)
  • k = SHA256_HASH(N + g)

从您的用户池获取 JSON Web 令牌

成功响应上一个质询后,您的 Amazon Cognito 用户池在 AuthenticationResult 中返回 JSON Web 令牌:

{ 
    "AuthenticationResult": { 
        "AccessToken": "...", 
        "ExpiresIn": 3600, 
        "IdToken": "...", 
        "RefreshToken": "...", 
        "TokenType": "Bearer" 
    }, 
    "ChallengeParameters": {} 
}

用户池身份验证流程

用户池参考(AWS 管理控制台)

AuthenticationHelper.js(AWS Amplify GitHub 存储库)

CognitoUser.js(AWS Amplify GitHub 存储库)

这篇文章对您有帮助吗?


您是否需要账单或技术支持?