管理用户存在错误响应
Amazon Cognito 支持自定义由用户池返回的错误响应。自定义错误响应可用于用户创建和身份验证、密码恢复和确认操作。
使用用户池应用程序客户端的 PreventUserExistenceErrors 设置,以启用或禁用用户存在相关错误。当您使用 Amazon Cognito 用户池 API 创建新的应用程序时,默认情况下 PreventUserExistenceErrors 为 LEGACY 或禁用。在 Amazon Cognito 控制台中,默认选定防止用户已存在错误选项(PreventUserExistenceErrors 设置为 ENABLED)。要更新 PreventUserExistenceErrors 配置,请执行以下操作之一:
-
在 UpdateUserPoolClient API 请求中将
PreventUserExistenceErrors的值更改为ENABLED和LEGACY。 -
在 Amazon Cognito 控制台中编辑应用程序客户端,并将防止用户已存在错误的状态更改为选定(
ENABLED)和已取消选择(LEGACY)。
当此属性的值为 LEGACY 时,当用户尝试使用您的用户池中不存在的用户名登录时,应用程序客户端会返回 UserNotFoundException 错误响应。
当此属性的值为 ENABLED 时,应用程序客户端不会通过 UserNotFoundException 错误来透露您的用户池中不存在某个用户账户。当 PreventUserExistenceErrors 配置为 ENABLED 时,如果您提交一个不存在的用户名请求,会产生以下效果:
-
Amazon Cognito 会使用非特定信息响应 API 请求,否则其响应可能会泄露存在有效的用户。
-
Amazon Cognito 会向密码重置请求以及使用除 基于选择的身份验证(
USER_AUTH)之外的身份验证流程(例如USER_SRP_AUTH或CUSTOM_AUTH)的身份验证请求,返回通用的身份验证失败响应。错误响应告知您用户名或密码不正确。 -
对于基于选择的身份验证请求,Amazon Cognito 会从用户池允许的质询类型中随机选择一种进行响应。您的用户池可能会返回通行密钥、一次性密码或密码质询。
-
Amazon Cognito 账户确认和密码恢复 API 的行为会在以下两种响应之间交替:一种是返回指示验证码已发送到模拟传送渠道的响应,另一种是返回
InvalidParameterException错误。
以下信息详细说明了 PreventUserExistenceErrors 设置为 ENABLED 时用户池操作的行为。
身份验证和用户创建操作
您可以在用户名密码和安全远程密码(SRP)身份验证中配置错误响应。您还可以对使用自定义身份验证返回的错误进行自定义。基于选择的身份验证不受您的 PreventUserExistenceErrors 配置的影响。
身份验证流程中的用户存在性披露细节
- 基于选择的身份验证
-
在
USER_AUTH基于选择的身份验证流程中,Amazon Cognito 会根据用户池配置和用户的属性,从可用的主身份验证因素中返回一个质询。该身份验证流程可能返回密码、安全远程密码(SRP)、WebAuthn(通行密钥)、短信一次性密码(OTP)或电子邮件 OTP 质询。当PreventUserExistenceErrors启用时,Amazon Cognito 会向不存在的用户发出质询,要求他们完成一种或多种可用的身份验证形式。当PreventUserExistenceErrors禁用时,Amazon Cognito 会返回UserNotFound异常。 - 用户名和密码身份验证
-
当
PreventUserExistenceErrors启用时,身份验证流程ADMIN_USER_PASSWORD_AUTH、USER_PASSWORD_AUTH以及USER_AUTH的PASSWORD流程会返回NotAuthorizedException,附带Incorrect username or password消息。当PreventUserExistenceErrors禁用时,这些流会返回UserNotFoundException。 - 基于安全远程密码(SRP)的身份验证
-
作为最佳实践,应仅在没有配置电子邮件地址、电话号码或首选用户名别名属性的用户池中,对
USER_SRP_AUTH或USER_AUTH中的PASSWORD_SRP流程实现PreventUserExistenceErrors。在 SRP 身份验证流程中,具有别名属性的用户可能不会受到用户存在性隐藏的影响。用户名密码身份验证流程(ADMIN_USER_PASSWORD_AUTH、USER_PASSWORD_AUTH和USER_AUTHPASSWORD质询)能够完全隐藏来自别名属性的用户存在性信息。当有人使用应用程序客户端未知的用户名尝试 SRP 登录时,Amazon Cognito 会在第一步返回一个模拟响应,如 RFC 5054
所述。Amazon Cognito 始终针对相同的用户名和用户池组合返回相同的盐值以及 UUID 格式的内部用户 ID。当您发送带有密码证明的 RespondToAuthChallengeAPI 时,Amazon Cognito 在用户名或密码不正确时返回一个通用NotAuthorizedException错误。有关实施 SRP 身份验证的更多信息,请参阅使用永久密码和安全有效载荷登录。注意
如果您使用基于验证的别名属性,并且不可改变的用户名格式不是 UUID,则可以模拟使用用户名和密码身份验证的通用响应。
- 自定义身份验证质询 Lambda 触发器
-
当用户尝试使用
CUSTOM_AUTH身份验证流程登录但其用户名未找到时,Amazon Cognito 会调用自定义身份验证质询 Lambda 触发器。输入事件中包含一个名为UserNotFound的布尔值参数,对于任何不存在的用户,该参数值为true。此参数会出现在用户池发送给创建、定义和验证身份验证质询 Lambda 函数的请求事件中,这些函数构成自定义身份验证架构。在 Lambda 函数逻辑中检查该标识后,您可以为不存在的用户模拟自定义身份验证质询。 - 身份验证前 Lambda 触发器
-
当用户尝试登录但其用户名未找到时,Amazon Cognito 会调用身份验证前触发器。输入事件中包含一个
UserNotFound参数,对于任何不存在的用户,该参数值为true。
以下列表描述了 PreventUserExistenceErrors 对用户账户创建的影响。
用户创建流程中的用户存在性披露细节
- SignUp
-
当已使用用户名时,
SignUp操作始终返回UsernameExistsException。如果在您的应用程序中注册用户时,您不希望 Amazon Cognito 为电子邮件地址和电话号码返回UsernameExistsException错误,请使用基于验证的别名属性。有关别名的更多信息,请参阅自定义登录属性。有关 Amazon Cognito 如何阻止使用
SignUpAPI 请求来发现用户池中用户的示例,请参阅 在注册时防止出现电子邮件地址和电话号码的 UsernameExistsException 错误。 - 导入的用户
-
如果
PreventUserExistenceErrors已启用,则在对导入的用户进行身份验证期间,将返回通用NotAuthorizedException错误,指示用户名或密码不正确,而不是返回PasswordResetRequiredException。请参阅要求导入的用户重置密码了解更多信息。 - 迁移用户 Lambda 触发器
-
当 Lambda 触发器在原始事件上下文中设置了空响应时,Amazon Cognito 将为不存在的用户返回模拟响应。有关更多信息,请参阅利用用户迁移 Lambda 触发器导入用户。
在注册时防止出现电子邮件地址和电话号码的 UsernameExistsException 错误
以下示例演示了在用户池中配置别名属性时,如何在对 SignUp API 请求的响应中,防止重复的电子邮件地址和电话号码生成 UsernameExistsException 错误。您必须在创建用户池时使用电子邮件地址或电话号码作为别名属性。有关更多信息,请参阅用户池属性的自定义登录属性 部分。
-
Jie 注册了一个新的用户名,还提供了电子邮件地址
jie@example.com。Amazon Cognito 将向其电子邮件地址发送一个代码。示例 Amazon CLI 命令
aws cognito-idp sign-up --client-id 1234567890abcdef0 --username jie --password PASSWORD --user-attributes Name="email",Value="jie@example.com"示例响应:
{ "UserConfirmed": false, "UserSub": "<subId>", "CodeDeliveryDetails": { "AttributeName": "email", "Destination": "j****@e****", "DeliveryMedium": "EMAIL" } } -
Jie 提供了发送过来的代码,确认其拥有该电子邮件地址。这样就完成了用户注册。
示例 Amazon CLI 命令
aws cognito-idp confirm-sign-up --client-id 1234567890abcdef0 --username=jie --confirmation-code xxxxxx -
Shirley 注册了一个新的用户账户并提供了电子邮件地址
jie@example.com。Amazon Cognito 不会返回UsernameExistsException错误,而是向 Jie 的电子邮件地址发送确认码。示例 Amazon CLI 命令
aws cognito-idp sign-up --client-id 1234567890abcdef0 --username shirley --password PASSWORD --user-attributes Name="email",Value="jie@example.com"示例响应:
{ "UserConfirmed": false, "UserSub": "<new subId>", "CodeDeliveryDetails": { "AttributeName": "email", "Destination": "j****@e****", "DeliveryMedium": "EMAIL" } } -
在另一种情况下,Shirley 拥有对
jie@example.com的所有权。Shirley 收到了 Amazon Cognito 发送到 Jie 电子邮件地址的代码,并尝试确认该账户。示例 Amazon CLI 命令
aws cognito-idp confirm-sign-up --client-id 1234567890abcdef0 --username=shirley --confirmation-code xxxxxx示例响应:
An error occurred (AliasExistsException) when calling the ConfirmSignUp operation: An account with the email already exists.
尽管已将 jie@example.com 分配给现有用户,Amazon Cognito 不会对 Shirley 的 aws cognito-idp sign-up 请求返回错误。在 Amazon Cognito 返回错误响应之前,Shirley 必须证明对该电子邮件地址的所有权。在具有别名属性的用户池中,此行为会阻止使用公共 SignUp API 来检查是否存在具有给定电子邮件地址或电话号码的用户。
此行为与 Amazon Cognito 向使用现有用户名的 SignUp 请求返回的响应不同,如以下示例所示。尽管 Shirley 从此回复中得知已经存在具有用户名 jie 的用户,但他们并不知道与该用户关联的任何电子邮件地址或电话号码。
示例 CLI 命令
aws cognito-idp sign-up --client-id 1example23456789 --username jie --password PASSWORD --user-attributes Name="email",Value="shirley@example.com"
示例响应:
An error occurred (UsernameExistsException) when calling the SignUp operation: User already exists
密码重置操作
当您防止出现用户存在错误时,Amazon Cognito 会对用户密码重置操作返回以下响应。
- ForgotPassword
-
当找不到用户、用户已停用或没有经过验证的传送机制来恢复其密码时,Amazon Cognito 会为用户返回
CodeDeliveryDetails以及模拟的传递媒介。模拟的传递媒介由用户池的输入用户名格式和验证设置决定。 - ConfirmForgotPassword
-
Amazon Cognito 为不存在或已禁用的用户返回
CodeMismatchException错误。如果在使用ForgotPassword时不请求代码,Amazon Cognito 将返回ExpiredCodeException错误。
确认操作
当您防止出现用户存在错误时,Amazon Cognito 会对用户确认和验证操作返回以下响应。
- ResendConfirmationCode
-
Amazon Cognito 为已禁用或不存在的用户返回
CodeDeliveryDetails。Amazon Cognito 会向现有用户的电子邮件或电话发送确认码。 - ConfirmSignUp
-
ExpiredCodeException如果代码已过期,则将返回 。当用户未被授权时,Amazon Cognito 返回NotAuthorizedException。1如果代码与服务器期望的代码不匹配,则 Amazon Cognito 返回CodeMismatchException。