用户池身份验证流程 - Amazon Cognito

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

用户池身份验证流程

Amazon Cognito 包含多种对用户进行身份验证的方法。所有用户群体(无论您是否具有域)都可以在用户群体 API 中对用户进行身份验证。如果您向用户群体添加域,则可以使用用户群体端点。用户群体 API 支持针对 API 请求的各种授权模型和请求流程。

为了验证用户的身份,除了密码之外,Amazon Cognito 还支持包含新质询类型的身份验证流程。Amazon Cognito 身份验证通常要求您按以下顺序实施两个 API 操作:

Public authentication

InitiateAuthRespondToAuthChallenge 是未经身份验证的 API,用于客户端公共应用程序客户端。

Server-side authentication

AdminInitiateAuthAdminRespondToAuthChallenge 需要 IAM 凭证,适用于服务器端机密应用程序客户端。

用户通过应答连续的质询进行身份验证,直到身份验证失败或 Amazon Cognito 向用户发放令牌。您可以在包含不同质询的流程中对 Amazon Cognito 重复这些步骤,以支持任何自定义身份验证流程。

通常,您的应用程序会生成一条提示,要求从用户收集信息,然后在 API 请求中将该信息提交给 Amazon Cognito。考虑使用用户池中的 InitiateAuth 流程,您已在其中为用户配置了多重身份验证 (MFA)。

  1. 应用程序会提示您的用户输入用户名和密码。

  2. 您可以将用户名和密码作为参数包含在 InitiateAuth 中。

  3. Amazon Cognito 会返回 SMS_MFA 质询和会话标识符。

  4. 应用程序会提示您的用户输入手机上收到的 MFA 代码。

  5. 您将该代码和会话标识符包含在 RespondToAuthChallenge 请求中。

根据用户池的特征,您最终可能会在您的应用程序从 Amazon Cognito 检索令牌之前,响应 InitiateAuth 的几个质询。Amazon Cognito 在对每个请求的响应中都包含一个会话字符串。要将您的 API 请求合并到身份验证流程中,请在每个后续请求中包含来自上一个请求的响应中的会话字符串。默认情况下,在会话字符串过期之前,您的用户有三分钟时间完成每项质询。要调整此时段,请更改您的应用程序客户端的 Authentication flow session duration(身份验证流程会话持续时间)。以下过程介绍如何在应用程序客户端配置中更改此设置。

注意

身份验证流程会话持续时间设置适用于使用 Amazon Cognito 用户群体 API 进行身份验证。Amazon Cognito 托管 UI 将多重身份验证的会话持续时间设置为 3 分钟,并将密码重置代码的会话持续时间设置为 8 分钟。

Amazon Cognito console
配置应用程序客户端身份验证流程会话持续时间 (AWS Management Console)
  1. 在您的用户群体中的 App integration(应用程序集成)选项卡上,从 App clients and analytics(应用程序客户端和分析)容器中选择您的应用程序客户端的名称。

  2. 应用程序客户端信息容器中选择编辑

  3. Authentication flow session duration(身份验证流程会话持续时间)的值更改为 SMS MFA 代码所需的有效期,以分钟为单位。这还会更改任何用户在您的应用程序客户端中必须完成任何身份验证质询的时间。

  4. 选择 ‬保存更改

Amazon Cognito API
配置应用程序客户端身份验证流程会话持续时间 (Amazon Cognito API)
  1. 使用 DescribeUserPoolClient 请求中您的现有用户群体设置准备 UpdateUserPoolClient 请求。您的 UpdateUserPoolClient 请求必须包含所有现有的应用程序客户端属性。

  2. AuthSessionValidity 的值更改为 SMS MFA 代码所需的有效期,以分钟为单位。这还会更改任何用户在您的应用程序客户端中必须完成任何身份验证质询的时间。

有关应用程序客户端的更多信息,请参阅用户池应用程序客户端

您可以使用 AWS Lambda 触发器来自定义用户身份验证的方式。作为身份验证流程的一部分,这些触发器将发布并验证自己的质询。

您还可以在安全后端服务器上对用户使用管理员身份验证流程。您可以使用用户迁移身份验证流来进行用户迁移,而无需用户重置其密码。

失败登录尝试的 Amazon Cognito 锁定行为

在使用密码进行五次未经身份验证或经 IAM 身份验证的登录尝试失败后,Amazon Cognito 会将您的用户锁定一秒钟。然后,每多一次失败的尝试,锁定持续时间将增加一倍,最长约为 15 分钟。在锁定期内进行的尝试会产生 Password attempts exceeded 异常,不会影响后续锁定期的持续时间。对于累计 n 次的失败登录尝试(不包括 Password attempts exceeded 异常),Amazon Cognito 会将您的用户锁定 2^(n-5) 秒。要将锁定重置为其 n=0 初始状态,用户必须在锁定期到期后才能成功登录,或者在锁定后连续 15 分钟的任何时间内都不得发起任何登录尝试。此行为随时可能会发生变化。此行为不适用于自定义质询,除非它们还执行基于密码的身份验证。

客户端身份验证流程

以下过程适用于您使用 AWS Amplify 或者 AWS SDK 创建的用户客户端应用程序:

  1. 用户将他们的用户名和密码输入到应用程序中。

  2. 应用程序使用用户的用户名和安全远程密码(SRP)详细信息调用 InitiateAuth 操作。

    此 API 操作返回身份验证参数。

    注意

    该应用程序使用 AWS 开发工具包内置的 Amazon Cognito SRP 特征生成 SRP 详细信息。

  3. 应用程序调用 RespondToAuthChallenge 操作。如果调用成功,则 Amazon Cognito 返回用户的令牌,并且身份验证流程完成。

    如果 Amazon Cognito 需要另一个质询,则对 RespondToAuthChallenge 的调用不返回任何令牌。相反,调用会返回一个会话。

  4. 如果 RespondToAuthChallenge 返回一个会话,应用程序将再次调用 RespondToAuthChallenge,这次使用会话和质询响应(例如,MFA 代码)。

服务器端身份验证流程

如果您没有用户应用程序,而是使用 Java、Ruby 或 Node.js 安全后端或服务器端应用程序,则可以对 Amazon Cognito 用户池使用经过身份验证的服务器端 API。

对于服务器端应用程序,用户池身份验证与客户端应用程序的身份验证类似,但以下情况除外:

  • 服务器端应用程序调用 AdminInitiateAuth API 操作(而不是 InitiateAuth)。此操作需要具有包含cognito-idp:AdminInitiateAuth和权限的 AWS 证书cognito-idp:AdminRespondToAuthChallenge。该操作返回必需的身份验证参数。

  • 服务器端应用程序获得身份验证参数后,它就会调用 AdminRespondToAuthChallenge API 操作(而不是 RespondToAuthChallenge)。只有在您提供 AWS 凭证时,AdminRespondToAuthChallengeAPI 操作才会成功。

有关使用 AWS 凭证签署 Amazon Cognito API 请求的更多信息,请参阅AWS 一般参考中的签名版本 4 签名流程

AdminInitiateAuthAdminRespondToAuthChallenge API 操作不能接受管理员登录的 username-and-password 用户凭据,除非您通过以下方式之一明确允许他们这样做:

  • 调用 CreateUserPoolClientUpdateUserPoolClient 时,在 ExplicitAuthFlow 参数中包含 ALLOW_ADMIN_USER_PASSWORD_AUTH(以前称为 ADMIN_NO_SRP_AUTH)。

  • ALLOW_ADMIN_USER_PASSWORD_AUTH 添加到应用程序客户端的身份验证流程列表中。在您的用户池中的 App integration(应用程序集成)选项卡上的 App clients and analytics(应用程序客户端和分析)下配置应用程序客户端。有关更多信息,请参阅用户池应用程序客户端

自定义身份验证流程

Amazon Cognito 用户池还允许使用自定义身份验证流程,这可以帮助您使用触发器创建基于质询/响应的身份验证模型。 AWS Lambda

注意

您不能使用高级安全功能来处理泄露的凭据,也不能使用自定义身份验证流程的自适应身份验证。有关更多信息,请参阅向用户池添加高级安全

自定义身份验证流程可以自定义质询和响应周期,以满足不同需求。该流程首先调用 InitiateAuth API 操作,该调用指示将使用的身份验证类型并提供了所有初始身份验证参数。Amazon Cognito 将使用以下类型的信息之一响应 InitiateAuth 调用:

  • 用户质询及会话和参数。

  • 错误(如果用户未能通过身份验证)

  • ID、访问和刷新令牌(如果 InitiateAuth 调用中提供的参数足以使用户登录)。(通常,用户或应用程序必须首先应答质询,但这必须由您的自定义代码决定。)

如果 Amazon Cognito 使用质询响应 InitiateAuth 调用,则应用程序将收集更多输入并调用 RespondToAuthChallenge 操作。此调用提供质询响应并将其传回会话。Amazon Cognito 对 RespondToAuthChallenge 的响应类似于对 InitiateAuth 调用的响应。如果用户已登录,Amazon Cognito 会提供令牌,如果用户未登录,则 Amazon Cognito 会提供另一个质询或错误。如果 Amazon Cognito 返回另一质询,则序列重复,应用程序调用 RespondToAuthChallenge 直到用户成功登录或返回错误。有关 InitiateAuthRespondToAuthChallenge API 操作的详细信息,请参阅 API 文档

内置身份验证流程和质询

Amazon Cognito 包含内置 AuthFlowChallengeName 值,以便标准身份验证流程可以通过安全远程密码(SRP)协议验证用户名和密码。这些 AWS 软件开发工具包内置了 Amazon Cognito 对这些流程的支持。

该流程通过将 USER_SRP_AUTH 作为 AuthFlow 发送到 InitiateAuth 开始。您还在 AuthParameters 中发送 USERNAMESRP_A 值。如果 InitiateAuth 调用成功,则响应将在质询参数中包括 PASSWORD_VERIFIER 作为 ChallengeNameSRP_B。然后,应用程序将使用 ChallengeResponses 中的 PASSWORD_VERIFIER ChallengeName 和必要参数调用 RespondToAuthChallenge。如果 RespondToAuthChallenge 调用成功并且用户登录,则 Amazon Cognito 将发布令牌。如果您为用户激活了多重验证 (MFA),Amazon Cognito 返回 SMS_MFAChallengeName。该应用程序可以通过对 RespondToAuthChallenge 的另一次调用来提供必要的代码。

自定义身份验证流程和质询

应用程序可以启动自定义身份验证流程,具体方法是:调用 InitiateAuth 并将 CUSTOM_AUTH 用作 Authflow。借助自定义身份验证流程,三个 Lambda 触发器控制响应的质询和验证。

  • DefineAuthChallenge Lambda 触发器将以前的质询和响应的会话数组作为输入。然后,它生成下一个质询名称和布尔值,指示用户是否通过身份验证并且应被授予令牌。此 Lambda 触发器是一个状态机,可通过质询控制用户的路径。

  • CreateAuthChallenge Lambda 触发器将质询名称作为输入并生成质询和参数以评估响应。当 DefineAuthChallenge 返回 CUSTOM_CHALLENGE 作为下一次质询时,身份验证流程调用 CreateAuthChallengeCreateAuthChallenge Lambda 触发器在质询元数据参数中传递下一个类型的质询。

  • VerifyAuthChallengeResponse Lambda 函数会评估响应并返回布尔值以表明响应是否有效。

自定义身份验证流程还可以使用内置质询的组合,例如 SRP 密码验证和通过短信进行的 MFA。它可以使用自定义质询,如验证码或秘密问题。

在自定义身份验证流程中使用 SRP 密码验证

如果您希望将 SRP 包含在自定义身份验证流程中,则您必须开始使用 SRP。

  • 要在自定义流程中启动 SRP 密码验证,应用程序将 CUSTOM_AUTH 作为 Authflow 来调用 InitiateAuth。在 AuthParameters 映射 中,来自应用程序的请求包括 SRP_A:(SRP A 值)和 CHALLENGE_NAME: SRP_A

  • CUSTOM_AUTH 流会使用 challengeName: SRP_AchallengeResult: true 的初始会话调用 DefineAuthChallenge Lambda 触发器。您的 Lambda 函数使用 challengeName: PASSWORD_VERIFIERissueTokens: falsefailAuthentication: false 作出响应。

  • 接下来,该应用程序必须使用 challengeName: PASSWORD_VERIFIERchallengeResponses 映射中 SRP 所需的其它参数调用 RespondToAuthChallenge

  • 如果 Amazon Cognito 验证了密码,RespondToAuthChallenge 使用 challengeName: PASSWORD_VERIFIERchallengeResult: true 的第二个会话调用 DefineAuthChallenge Lambda 触发器。此时,DefineAuthChallenge Lambda 触发器可以使用 challengeName: CUSTOM_CHALLENGE 响应来开启自定义质询。

  • 如果为用户启用了 MFA,则在 Amazon Cognito 验证密码后,您的用户将被要求设置 MFA 或使用 MFA 登录。

注意

Amazon Cognito 托管的登录网页无法激活 自定义身份验证质询 Lambda 触发器

有关 Lambda 触发器的更多信息,包括示例代码,请参阅使用 Lambda 触发器自定义用户池工作流

管理员身份验证流程

身份验证的最佳实践是使用 自定义身份验证流程 中所述的 API 操作,以使用 SRP 进行密码验证。S AWS DK 使用这种方法,这种方法可以帮助他们使用 SRP。但是,如果您希望避免 SRP 计算,还可以使用另一组专为在安全后端服务器上使用的管理员 API 操作。对于这些后端管理员实施,请使用 AdminInitiateAuth 代替 InitiateAuth。另外,请使用 AdminRespondToAuthChallenge 代替 RespondToAuthChallenge。由于您能够以明文形式提交密码,因此在使用这些操作时不必进行 SRP 计算。示例如下:

AdminInitiateAuth Request { "AuthFlow":"ADMIN_USER_PASSWORD_AUTH", "AuthParameters":{ "USERNAME":"<username>", "PASSWORD":"<password>" }, "ClientId":"<clientId>", "UserPoolId":"<userPoolId>" }

这些管理员身份验证操作要求提供开发人员凭证,并使用 AWS 签名版本 4 (SigV4) 签名过程。这些操作在 Node.js 等标准 AWS SDK 中可用,便于用于 Lambda 函数。要使用这些操作并让它们接受明文密码,您必须在控制台中为应用程序激活这些操作。或者,您可以在调用 CreateUserPoolClientUpdateUserPoolClient 时为 ExplicitAuthFlow 参数传递 ADMIN_USER_PASSWORD_AUTHInitiateAuthRespondToAuthChallenge 操作不接受 ADMIN_USER_PASSWORD_AUTH AuthFlow

AdminInitiateAuth 响应 ChallengeParameters 中,USER_ID_FOR_SRP 属性(如果存在)包含用户的实际用户名而不是别名(如电子邮件地址或电话号码)。在 AdminRespondToAuthChallenge 调用的 ChallengeResponses 中,您必须在 USERNAME 参数中传递此用户名。

注意

由于后端管理员实施使用管理员身份验证流程,因此流不支持设备跟踪。在您启用设备跟踪时,管理员身份验证成功,但任何对刷新访问令牌的调用均会失败。

用户迁移身份验证流程

用户迁移 Lambda 触发器可帮助您将用户从旧式用户管理系统迁移到您的用户池。如果选择 USER_PASSWORD_AUTH 身份验证流程,则用户在用户迁移过程中无需重置密码。此流程在身份验证期间通过加密的 SSL 连接向服务发送用户的密码。

所有用户均完成迁移后,请切换为更安全的 SRP 流程。SRP 流程不通过网络发送任何密码。

要了解有关 Lambda 触发器的更多信息,请参阅使用 Lambda 触发器自定义用户池工作流

有关使用 Lambda 触发器迁移用户的更多信息,请参阅利用用户迁移 Lambda 触发器将用户导入用户池