使用 Amazon Cognito 用户池进行身份验证 - Amazon Cognito
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅 中国的 Amazon Web Services 服务入门 (PDF)

使用 Amazon Cognito 用户池进行身份验证

Amazon Cognito 包含多种对用户进行身份验证的方法。用户可以使用密码和 WebAuthn 通行密钥登录。Amazon Cognito 可以通过电子邮件或短信向他们发送一次性密码。您可以实现 Lambda 函数,以编排您自己的质询与响应序列。这些是身份验证流程。在身份验证流程中,用户提交一个密钥,Amazon Cognito 验证该密钥后,会颁发 JSON Web 令牌(JWT),供应用程序使用 OIDC 库进行处理。本章将介绍如何在不同的应用程序环境中,为您的用户池和应用程序客户端配置各种身份验证流程。您将了解使用托管登录的托管登录页面的选项,以及如何在 Amazon SDK 中构建您自己的逻辑和前端。

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

为了验证用户的身份,Amazon Cognito 支持多种身份验证流程,这些流程除了密码之外,还结合了其他类型的质询,例如电子邮件和短信一次性密码以及通行密钥。

实现身份验证流程

无论您是使用托管登录,还是通过 Amazon SDK 定制的应用程序前端来进行身份验证,都必须为应用程序客户端配置您希望实现的身份验证类型。以下信息介绍了如何在应用程序客户端和应用程序中设置身份验证流程。

App client supported flows

您可以在 Amazon Cognito 控制台中,或通过 Amazon SDK 中的 API,为应用程序客户端配置所支持的身份验证流程。在完成应用程序客户端的配置以支持这些流程后,即可在您的应用程序中部署它们。

以下过程展示了如何使用 Amazon Cognito 控制台为应用程序客户端配置可用的身份验证流程。

为应用程序客户端配置身份验证流程(使用控制台)
  1. 登录到 Amazon,导航到 Amazon Cognito 用户池控制台。选择一个用户池或新建一个。

  2. 在您的用户池配置中,选择应用程序客户端菜单。选择一个应用程序客户端或新建一个。

  3. 应用程序客户端信息下,选择编辑

  4. 应用程序客户端流程下,选择要支持的身份验证流程。

为应用程序客户端配置身份验证流程(使用 API/SDK)

要使用 Amazon Cognito API 为应用程序客户端配置可用的身份验证流程,请在 CreateUserPoolClientUpdateUserPoolClient 请求中设置 ExplicitAuthFlows 的值。以下是为客户端预置安全远程密码(SRP)和基于选择的身份验证的示例。

"ExplicitAuthFlows": [ "ALLOW_USER_AUTH", "ALLOW_USER_SRP_AUTH ]

配置应用程序客户端支持的流程时,您可以指定以下选项和 API 值。

应用程序客户端流程支持
身份验证流程 兼容性 控制台 API
基于选择的身份验证 服务器端、客户端 登录时选择身份验证类型 ALLOW_USER_AUTH
使用永久密码登录 客户端 使用用户名和密码登录 ALLOW_USER_PASSWORD_AUTH
使用永久密码和安全有效载荷登录 服务器端、客户端 使用安全远程密码(SRP)登录 ALLOW_USER_SRP_AUTH
刷新令牌 服务器端、客户端 从现有的经过身份验证的会话中获取新的用户令牌 ALLOW_REFRESH_TOKEN_AUTH
服务器端身份验证 服务器端 使用服务器端管理凭证登录 ALLOW_ADMIN_USER_PASSWORD_AUTH
自定义身份验证 服务器端和客户端定制应用程序。与托管登录不兼容。 通过 Lambda 触发器使用自定义身份验证流程登录 ALLOW_CUSTOM_AUTH
Implement flows in your application

托管登录会自动将您配置的身份验证选项显示在登录页面中。在定制的应用程序中,需通过声明初始身份验证流程来启动身份验证。

在为用户登录时,您的 InitiateAuthAdminInitiateAuth 请求正文必须包含一个 AuthFlow 参数。

基于选择的身份验证:

"AuthFlow": "USER_AUTH"

使用 SRP 的基于客户端的身份验证:

"AuthFlow": "USER_SRP_AUTH"

有关用户池身份验证的需知信息

在使用 Amazon Cognito 用户池设计身份验证模型时,请考虑以下信息。

托管登录与托管 UI 中的身份验证流程

托管登录提供的身份验证选项比经典托管 UI 更多。例如,无密码身份验证和通行密钥身份验证仅在托管登录中可用。

仅在 Amazon SDK 身份验证中可用的自定义身份验证流程

您无法在托管登录或经典托管 UI 中执行自定义身份验证流程,也无法使用 Lambda 触发器进行自定义身份验证。自定义身份验证仅支持使用 Amazon SDK 进行身份验证时使用。

通过外部身份提供者(IdP)登录的托管登录

您无法在使用 Amazon SDK 进行身份验证时通过第三方 IdP 登录用户。必须实现托管登录或经典托管 UI,将用户重定向到 IdP,然后在应用程序中使用 OIDC 库处理返回的身份验证对象。有关托管登录的更多信息,请参阅用户池托管登录

无密码身份验证对其他用户功能的影响

在用户池和应用程序客户端中激活使用一次性密码通行密钥的无密码登录,会影响用户的创建和迁移。当无密码登录启用时:

  1. 管理员无需密码即可创建用户。默认的邀请消息模板将不再包含 {###} 密码占位符。有关更多信息,请参阅以管理员身份创建用户账户

  2. 对于基于 SDK 的 SignUp 操作,用户在注册时无需提供密码。而在托管登录和托管 UI 中,即使允许无密码身份验证,在注册页面中仍会要求用户输入密码。有关更多信息,请参阅注册并确认用户账户

  3. 从 CSV 文件导入的用户,只要其属性中包含可用于无密码登录选项的电子邮件地址或电话号码,即可立即使用无密码方式登录,而无需重置密码。有关更多信息,请参阅通过 CSV 文件将用户导入用户池中

  4. 无密码身份验证不会调用用户迁移 Lambda 触发器

  5. 使用无密码方式作为第一重身份验证因素登录的用户,无法在其会话中添加多重身份验证(MFA)因素。仅基于密码的身份验证流支持 MFA。

通行密钥的依赖方 URL 不能位于公共后缀列表中

您可以使用自己拥有的域名(例如 www.example.com)作为通行密钥配置中的依赖方(RP)ID。此配置旨在支持运行在您自有域上的定制应用程序。公共后缀列表(PSL)包含受保护的高层级域。当您尝试将 RP URL 设置为 PSL 中的域时,Amazon Cognito 会返回错误。

身份验证会话流程持续时间

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

注意

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

Amazon Cognito console
配置应用程序客户端身份验证流程会话持续时间(Amazon Web Services 管理控制台)
  1. 在您的用户池中的应用程序集成选项卡上,从应用程序客户端和分析容器中选择您的应用程序客户端的名称。

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

  3. 身份验证流程会话持续时间的值更改为短信和电子邮件 MFA 验证码所需的有效期,以分钟为单位。这还会更改任何用户在您的应用程序客户端中必须完成任何身份验证质询的时间。

  4. 选择保存更改

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

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

有关应用程序客户端的更多信息,请参阅特定于应用程序的应用程序客户端设置

失败登录尝试的锁定行为

当用户连续五次输入错误密码尝试登录时(无论这些请求是通过未经身份验证的 API 操作还是通过 IAM 授权的 API 操作发起的),Amazon Cognito 会将该用户锁定一秒钟。然后,每多一次失败的尝试,锁定持续时间将增加一倍,最长约为 15 分钟。

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

身份验证会话示例

下图和分步指南展示了一个典型场景:用户登录应用程序。示例应用程序向用户提供多种登录选项。用户通过输入凭证选择其中一种,随后提供额外的身份验证因素,最终完成登录。

一个流程图,展示了一个应用程序如何提示用户输入并使用 Amazon SDK 来登录。

设想一个应用程序,其登录页面允许用户通过用户名和密码登录、请求通过电子邮件发送的一次性验证码,或选择指纹验证选项。

  1. 登录提示:您的应用程序显示一个主页,其中包含一个登录按钮。

  2. 请求登录:用户选择登录。您的应用程序从 Cookie 或缓存中检索其用户名,或提示其输入用户名。

  3. 请求选项:您的应用程序请求用户的登录选项,方法是使用 USER_AUTH 流程发起 InitiateAuth API 请求,获取用户的可用登录方式。

  4. 发送登录选项:Amazon Cognito 返回 PASSWORDEMAIL_OTPWEB_AUTHN。该响应包含一个会话标识符,供您在下一个响应中回传。

  5. 显示选项:您的应用程序显示 UI 元素,供用户选择输入用户名和密码、获取一次性验证码,或扫描指纹。

  6. 选择选项/输入凭证:用户输入其用户名和密码。

  7. 发起身份验证:您的应用程序通过 RespondToAuthChallenge API 请求提交用户的登录信息,确认使用用户名密码进行登录,并提供相应的用户名和密码。

  8. 验证凭证:Amazon Cognito 确认用户提供的凭证。

  9. 额外质询:该用户已配置使用于身份验证器应用程序进行多重身份验证。Amazon Cognito 返回 SOFTWARE_TOKEN_MFA 质询。

  10. 质询提示:您的应用程序显示一个表单,请求用户输入其身份验证器应用程序生成的基于时间的一次性密码(TOTP)。

  11. 回答质询:用户提交该 TOTP。

  12. 响应质询:您的应用程序在另一个 RespondToAuthChallenge 请求中提供用户的 TOTP。

  13. 验证质询响应:Amazon Cognito 确认用户提交的验证码,并确定您的用户池未针对当前用户配置额外的质询。

  14. 颁发令牌:Amazon Cognito 返回 ID、访问和刷新 JSON Web 令牌(JWT)。用户的初始身份验证完成。

  15. 存储令牌:您的应用程序缓存用户的令牌,以便后续引用用户数据、授权资源访问,并在令牌过期时进行更新。

  16. 呈现授权内容:您的应用程序根据用户的身份和角色判断其资源访问权限,并提供相应的应用程序内容。

  17. 访问内容:用户已登录并开始使用该应用程序。

  18. 使用过期令牌请求内容:稍后,用户请求一个需要授权的资源。但用户缓存的令牌已过期。

  19. 刷新令牌:您的应用程序使用用户保存的刷新令牌发起 InitiateAuth 请求。

  20. 颁发令牌:Amazon Cognito 返回新的 ID 和访问 JWT。用户的会话在无需再次输入凭证的情况下安全地完成刷新。

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

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