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

上次更新日期:2022 年 10 月 17 日

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

简短描述

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

注意:必须使用 USER_SRP_AUTH 身份验证流程才能使用设备跟踪功能。要使用记住的设备替换多重身份验证(MFA),您还必须为用户群体启用 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( 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 个随机字节,以 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) (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 Web 令牌

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

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

这篇文章对您有帮助吗?


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