Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅
中国的 Amazon Web Services 服务入门
(PDF)。
身份验证流程
Amazon Cognito 用户池的身份验证过程最好可以描述为一个流程:用户首先做出初始选择,提交凭证,并响应额外的质询。当您在应用程序中实现托管登录身份验证时,Amazon Cognito 会自动管理这些提示和质询的流程。当您在应用程序后端通过 Amazon SDK 实现身份验证流程时,则需要自行构建请求逻辑、提示用户输入,并响应各项质询。
作为应用程序管理员,您的用户特征、安全需求和授权模型将帮助您确定允许用户如何登录。请思考以下问题。
当您回答了这些问题后,就可以学习如何激活相关功能,并在应用程序发起的身份验证请求中加以实现。
为用户设置登录流程后,您可以通过 GetUserAuthFactors API 操作请求,检查其当前的 MFA 状态和基于选择的身份验证因素。此操作需要使用已登录用户的访问令牌进行授权,并返回该用户的身份验证因素及 MFA 设置。
使用第三方 IdP 登录
Amazon Cognito 用户池充当 IdP(例如“通过 Apple 登录”、“使用 Amazon 登录”和 OpenID Connect(OIDC)服务)之间身份验证会话的中间代理。此过程也称为联合登录 或联合身份验证。联合身份验证不使用您在应用程序客户端中配置的任何内置身份验证流程。相反,您需要将已配置的用户池 IdP 分配给应用程序客户端。当用户在托管登录页面选择其 IdP,或您的应用程序通过重定向到该 IdP 的登录页面来发起会话时,联合登录便会触发。
通过联合登录,您将主要身份验证因素和 MFA 身份验证因素委托给用户的 IdP。除非您将联合用户与本地用户关联,否则 Amazon Cognito 不会为该联合用户添加本节中提到的其他高级身份验证流程。未关联的联合用户虽有用户名,但其本质上是映射属性数据的存储,通常不会独立于基于浏览器的流程用于登录。
使用永久密码登录
在 Amazon Cognito 用户池中,每个用户都有一个用户名。这可能是电话号码、电子邮件地址,或由用户选择或管理员提供的标识符。此类用户可使用用户名和密码登录,并可选择性地提供 MFA。用户池可通过公开的或经 IAM 授权的 API 操作及 SDK 方法执行用户名密码登录。您的应用程序可以直接将密码发送至用户池进行身份验证。用户池会返回额外的质询,或在身份验证成功后返回 JSON Web 令牌(JWT)。
- Activate password sign-in
-
要激活使用用户名和密码的基于客户端的身份验证,请配置您的应用程序客户端以允许该方式。在 Amazon Cognito 控制台中,导航到用户池配置中应用程序下的应用程序客户端菜单。要为客户端移动应用程序或原生应用程序启用明文密码登录,请编辑应用程序客户端,并在身份验证流程下选择使用用户名和密码登录:ALLOW_USER_PASSWORD_AUTH。要为服务器端应用程序启用明文密码登录,请编辑应用程序客户端,并选择使用服务器端管理凭证登录:ALLOW_ADMIN_USER_PASSWORD_AUTH。
要激活使用用户名和密码的基于选择的身份验证,请配置您的应用程序客户端以允许该方式。编辑应用程序客户端,然后选择基于选择的登录:ALLOW_USER_AUTH。
要验证密码身份验证在基于选择的身份验证流程中是否可用,请导航到登录菜单,查看基于选择的登录选项下的部分。如果密码在可用选项下可见,则可以使用明文密码身份验证进行登录。密码选项包括明文和 SRP 用户名密码身份验证变体。
在 CreateUserPoolClient 或 UpdateUserPoolClient 请求中,通过配置 ExplicitAuthFlows 来指定您首选的用户名和密码身份验证选项。
"ExplicitAuthFlows": [
"ALLOW_USER_PASSWORD_AUTH",
"ALLOW_ADMIN_USER_PASSWORD_AUTH",
"ALLOW_USER_AUTH"
]
在 CreateUserPool 或 UpdateUserPool 请求中,通过配置 Policies 来指定您希望支持的基于选择的身份验证流程。AllowedFirstAuthFactors 中的 PASSWORD 值同时包括明文密码和 SRP 身份验证流程选项。
"Policies": {
"SignInPolicy": {
"AllowedFirstAuthFactors": [
"PASSWORD",
"EMAIL_OTP",
"WEB_AUTHN"
]
}
}
- Choice-based sign-in with a password
-
要通过用户名密码身份验证将用户登录到应用程序,请按如下方式配置 AdminInitiateAuth 或 InitiateAuth 请求的正文。如果当前用户符合使用用户名密码身份验证的条件,该登录请求将成功,或继续进入下一个质询。否则,系统将返回一份可用的主要因素身份验证质询列表。以下参数集合是登录所需的最低要求。此外还支持其他参数。
{
"AuthFlow": "USER_AUTH",
"AuthParameters": {
"USERNAME" : "testuser",
"PREFERRED_CHALLENGE" : "PASSWORD",
"PASSWORD" : "[User's password]"
},
"ClientId": "1example23456789"
}
您也可以省略 PREFERRED_CHALLENGE 值,然后将收到一个响应,其中包含该用户符合条件的登录因素列表。
{
"AuthFlow": "USER_AUTH",
"AuthParameters": {
"USERNAME" : "testuser"
},
"ClientId": "1example23456789"
}
如果您未提交首选质询,或所提交的用户不符合其首选质询的条件,Amazon Cognito 将在 AvailableChallenges 中返回一个可用选项列表。当 AvailableChallenges 的 ChallengeName 为 PASSWORD 时,您可以按照以下格式,通过 RespondToAuthChallenge 或 AdminRespondToAuthChallenge 提交质询响应以继续身份验证。您必须传递一个 Session 参数,将该质询响应与初始登录请求的 API 响应关联起来。以下参数集合是登录所需的最低要求。此外还支持其他参数。
{
"ChallengeName": "PASSWORD",
"ChallengeResponses": {
"USERNAME" : "testuser",
"PASSWORD" : "[User's Password]"
},
"ClientId": "1example23456789",
"Session": "[Session ID from the previous response"
}
对于符合条件且成功的首选质询请求,以及 PASSWORD 质询响应,Amazon Cognito 会返回令牌,或要求用户完成额外的质询,例如多重身份验证(MFA)。
- Client-based sign-in with a password
-
要通过用户名密码身份验证将用户登录到客户端应用程序,请按如下方式配置 InitiateAuth 请求的正文。以下参数集合是登录所需的最低要求。此外还支持其他参数。
{
"AuthFlow": "USER_PASSWORD_AUTH",
"AuthParameters": {
"USERNAME" : "testuser",
"PASSWORD" : "[User's password]"
},
"ClientId": "1example23456789"
}
要通过用户名密码身份验证将用户登录到服务器应用程序,请按如下方式配置 AdminInitiateAuth 请求的正文。应用程序必须使用 Amazon 凭证签署此请求。以下参数集合是登录所需的最低要求。此外还支持其他参数。
{
"AuthFlow": "ADMIN_USER_PASSWORD_AUTH",
"AuthParameters": {
"USERNAME" : "testuser",
"PASSWORD" : "[User's password]"
},
"ClientId": "1example23456789"
}
对于成功的请求,Amazon Cognito 会返回令牌,或要求用户完成额外的质询,例如多重身份验证(MFA)。
使用永久密码和安全有效载荷登录
用户池中的另一种用户名密码登录方式是使用安全远程密码(SRP)协议。该选项会发送对密码的“知识证明”,即一个密码哈希值和一个加密盐,供用户池进行验证。由于发送给 Amazon Cognito 的请求中不包含任何可读的密钥信息,因此您的应用程序是能够处理用户输入密码的唯一实体。SRP 身份验证涉及数学计算,建议使用 SDK 中可导入的现有组件来实现。SRP 通常在客户端应用程序(如移动应用程序)中实现。有关该协议的更多信息,请参阅 The Stanford SRP Homepage。维基百科也提供了相关资源和示例。此外,多种公开的库可用于在您的身份验证流程中执行 SRP 计算。
Amazon Cognito 身份验证中的“发起-质询-响应”序列通过 SRP 验证用户及其密码。您必须先配置用户池和应用程序客户端以支持 SRP 身份验证,然后在应用程序中实现登录请求与质询响应的逻辑。您的 SRP 库可生成随机数和计算值,用以向用户池证明您持有用户的密码。应用程序需将这些计算得出的值填入 Amazon Cognito 用户池 API 操作或 SDK 方法中用于身份验证的 JSON 格式的 AuthParameters 和 ChallengeParameters 字段。
- Activate SRP sign-in
-
要激活使用用户名和 SRP 的基于客户端的身份验证,请配置您的应用程序客户端以允许该方式。在 Amazon Cognito 控制台中,导航到用户池配置中应用程序下的应用程序客户端菜单。要为客户端移动应用程序或原生应用程序启用 SRP 登录,请编辑应用程序客户端,并在身份验证流程下选择使用安全远程密码(SRP)登录:ALLOW_USER_SRP_AUTH。
要激活使用用户名和 SRP 的基于选择的身份验证,请编辑您的应用程序客户端,并选择基于选择的登录:ALLOW_USER_AUTH。
要验证 SRP 身份验证在基于选择的身份验证流程中是否可用,请导航到登录菜单,查看基于选择的登录选项下的部分。如果密码在可用选项下可见,则可以使用 SRP 身份验证进行登录。密码选项包括明文和 SRP 用户名密码身份验证变体。
在 CreateUserPoolClient 或 UpdateUserPoolClient 请求中,通过配置 ExplicitAuthFlows 来指定您首选的用户名和密码身份验证选项。
"ExplicitAuthFlows": [
"ALLOW_USER_SRP_AUTH",
"ALLOW_USER_AUTH"
]
在 CreateUserPool 或 UpdateUserPool 请求中,通过配置 Policies 来指定您希望支持的基于选择的身份验证流程。AllowedFirstAuthFactors 中的 PASSWORD 值同时包括明文密码和 SRP 身份验证流程选项。
"Policies": {
"SignInPolicy": {
"AllowedFirstAuthFactors": [
"PASSWORD",
"EMAIL_OTP",
"WEB_AUTHN"
]
}
}
- Choice-based sign-in with SRP
-
要通过 SRP 用户名密码身份验证将用户登录到应用程序,请按如下方式配置 AdminInitiateAuth 或 InitiateAuth 请求的正文。如果当前用户符合使用用户名密码身份验证的条件,该登录请求将成功,或继续进入下一个质询。否则,系统将返回一份可用的主要因素身份验证质询列表。以下参数集合是登录所需的最低要求。此外还支持其他参数。
{
"AuthFlow": "USER_AUTH",
"AuthParameters": {
"USERNAME" : "testuser",
"PREFERRED_CHALLENGE" : "PASSWORD_SRP",
"SRP_A" : "[g^a % N]"
},
"ClientId": "1example23456789"
}
您也可以省略 PREFERRED_CHALLENGE 值,然后将收到一个响应,其中包含该用户符合条件的登录因素列表。
{
"AuthFlow": "USER_AUTH",
"AuthParameters": {
"USERNAME" : "testuser"
},
"ClientId": "1example23456789"
}
如果您未提交首选质询,或所提交的用户不符合其首选质询的条件,Amazon Cognito 将在 AvailableChallenges 中返回一个可用选项列表。当 AvailableChallenges 的 ChallengeName 为 PASSWORD_SRP 时,您可以按照以下格式,通过 RespondToAuthChallenge 或 AdminRespondToAuthChallenge 提交质询响应以继续身份验证。您必须传递一个 Session 参数,将该质询响应与初始登录请求的 API 响应关联起来。以下参数集合是登录所需的最低要求。此外还支持其他参数。
{
"ChallengeName": "PASSWORD_SRP",
"ChallengeResponses": {
"USERNAME" : "testuser",
"SRP_A" : "[g^a % N]"
},
"ClientId": "1example23456789",
"Session": "[Session ID from the previous response"
}
Amazon Cognito 会对符合条件的首选质询请求以及 PASSWORD_SRP 质询响应返回一个 PASSWORD_VERIFIER 质询。您的客户端必须完成 SRP 计算,并通过 RespondToAuthChallenge 或 AdminRespondToAuthChallenge 请求对该质询作出响应。
{
"ChallengeName": "PASSWORD_VERIFIER",
"ChallengeResponses": {
"PASSWORD_CLAIM_SIGNATURE" : "string",
"PASSWORD_CLAIM_SECRET_BLOCK" : "string",
"TIMESTAMP" : "string"
},
"ClientId": "1example23456789",
"Session": "[Session ID from the previous response]"
}
在成功响应 PASSWORD_VERIFIER 质询后,Amazon Cognito 会颁发令牌,或要求用户完成另一项必需的质询,例如多重身份验证(MFA)。
- Client-based sign-in with SRP
-
SRP 身份验证更常用于客户端身份验证,而非服务器端。不过,您也可以在 InitiateAuth 和 AdminInitiateAuth 中使用 SRP 身份验证。要将用户登录到应用程序,请按如下方式配置 InitiateAuth 或 AdminInitiateAuth 请求的正文。以下参数集合是登录所需的最低要求。此外还支持其他参数。
客户端通过将生成元 g(模 N)的幂次提升到一个秘密随机整数 a 来生成 SRP_A。
{
"AuthFlow": "USER_SRP_AUTH",
"AuthParameters": {
"USERNAME" : "testuser",
"SRP_A" : "[g^a % N]"
},
"ClientId": "1example23456789"
}
Amazon Cognito 以 PASSWORD_VERIFIER 质询进行响应。您的客户端必须完成 SRP 计算,并通过 RespondToAuthChallenge 或 AdminRespondToAuthChallenge 请求对该质询作出响应。
{
"ChallengeName": "PASSWORD_VERIFIER",
"ChallengeResponses": {
"PASSWORD_CLAIM_SIGNATURE" : "string",
"PASSWORD_CLAIM_SECRET_BLOCK" : "string",
"TIMESTAMP" : "string"
},
"ClientId": "1example23456789",
"Session": "[Session ID from the previous response]"
}
在成功响应 PASSWORD_VERIFIER 质询后,Amazon Cognito 会颁发令牌,或要求用户完成另一项必需的质询,例如多重身份验证(MFA)。
使用一次性密码进行无密码登录
密码可能会丢失或被盗。您可能希望仅验证用户是否能够访问已验证的电子邮件地址、电话号码或身份验证器应用程序。解决方法是采用无密码 登录。应用程序可以提示用户输入其用户名、电子邮件地址或电话号码。随后,Amazon Cognito 会生成一个一次性密码(OTP),即一个用户必须确认的验证码。用户成功提交该验证码后,身份验证即完成。
无密码身份验证流程与用户池中必需的多重身份验证(MFA)不兼容。如果您的用户池将 MFA 设为可选,则已启用 MFA 的用户无法使用无密码方式作为第一重身份验证因素进行登录。在 MFA 为可选的用户池中,没有 MFA 偏好的用户可以使用无密码身份验证因素进行登录。有关更多信息,请参阅有关用户池 MFA 的需知信息。
当用户在无密码身份验证流程中正确输入其通过短信或电子邮件收到的验证码时,除了完成用户身份验证外,您的用户池还会将该用户原先未验证的电子邮件地址或电话号码属性标记为已验证。无论您是否将用户池配置为自动验证电子邮件地址或电话号码,该用户的状态都会从 UNCONFIRMED 变更为 CONFIRMED。
启用无密码登录后的新选项
当您在用户池中激活无密码身份验证时,某些用户流程的工作方式会发生变化。
-
用户在注册时无需设置密码,并在登录时选择一个无密码身份验证因素。您也可以以管理员身份创建不带密码的用户。
-
通过 CSV 文件导入的用户可以立即使用无密码身份验证因素登录,无需在登录前设置密码。
-
没有密码的用户在提交 ChangePassword API 请求时,可以不提供 PreviousPassword 参数。
使用 OTP 自动登录
通过电子邮件或短信 OTP 注册并确认其用户账户的用户,可以自动使用与其确认消息匹配的无密码身份验证因素进行登录。在托管登录 UI 中,完成账户确认且符合使用确认码传送方式进行 OTP 登录的条件的用户,在提供确认码后会自动进入首次登录流程。在您使用 Amazon SDK 的定制应用程序中,请向 InitiateAuth 或 AdminInitiateAuth 操作传递以下参数。
您可以传递值为 EMAIL_OTP 或 SMS_OTP 的 PREFERRED_CHALLENGE,但这不是必需的。Session 参数提供身份验证的证明,当您传入有效的会话代码时,Amazon Cognito 会忽略 AuthParameters。
如果满足以下条件,登录操作将返回表示身份验证成功的响应 AuthenticationResult,且不再要求额外的质询。
-
Session 代码有效且未过期。
-
用户符合使用 OTP 身份验证方法的条件。
- Activate passwordless sign-in
-
控制台
要激活无密码登录,请先配置您的用户池,以允许使用一种或多种无密码类型作为主要登录方式,然后配置您的应用程序客户端以允许 USER_AUTH 身份验证流程。在 Amazon Cognito 控制台中,导航到用户池配置中身份验证下的登录菜单。编辑基于选择的登录选项,然后选择电子邮件消息一次性密码或 SMS 消息一次性密码。您可以同时激活这两个选项。保存更改。
导航到应用程序客户端菜单,然后选择一个应用程序客户端或新建一个。选择编辑,然后选择登录时选择身份验证类型:ALLOW_USER_AUTH。
API/SDK
在用户池 API 中,在 CreateUserPool 或 UpdateUserPool 请求中使用相应的无密码登录选项配置 SignInPolicy。
"SignInPolicy": {
"AllowedFirstAuthFactors": [
"EMAIL_OTP",
"SMS_OTP"
]
}
在 CreateUserPoolClient 或 UpdateUserPoolClient 请求中,为您的应用程序客户端 ExplicitAuthFlows 配置所需的选项。
"ExplicitAuthFlows": [
"ALLOW_USER_AUTH"
]
- Sign in with passwordless
-
无密码登录没有可在 InitiateAuth 和 AdminInitiateAuth 中指定的基于客户端的 AuthFlow。OTP 身份验证仅在基于选择的 AuthFlow USER_AUTH 中可用:在此流程中,您可以请求一个首选登录选项,或从用户的 AvailableChallenges 中选择无密码选项。要将用户登录到应用程序,请按如下方式配置 InitiateAuth 或 AdminInitiateAuth 请求的正文。以下参数集合是登录所需的最低要求。此外还支持其他参数。
在此示例中,我们不知道用户想要通过哪种方式登录。如果我们添加一个 PREFERRED_CHALLENGE 参数并且用户可以使用该首选质询,则 Amazon Cognito 将返回该质询。
{
"AuthFlow": "USER_AUTH",
"AuthParameters": {
"USERNAME" : "testuser"
},
"ClientId": "1example23456789"
}
您也可以在本例中向 AuthParameters 添加 "PREFERRED_CHALLENGE": "EMAIL_OTP" 或 "PREFERRED_CHALLENGE": "SMS_OTP"。如果用户符合该首选方式的使用条件,您的用户池会立即向该用户的电子邮件地址或电话号码发送验证码,并返回 "ChallengeName": "EMAIL_OTP" 或 "ChallengeName":
"SMS_OTP"。
如果您没有指定首选质询,Amazon Cognito 会返回一个 AvailableChallenges 参数。
{
"AvailableChallenges": [
"EMAIL_OTP",
"SMS_OTP",
"PASSWORD"
],
"Session": "[Session ID]"
}
该用户符合以下登录方式的条件:通过电子邮件消息 OTP 进行无密码登录、通过短信 OTP 进行无密码登录以及使用用户名密码登录。您的应用程序可以提示用户选择其中一种方式,也可以根据内部逻辑自动做出选择。随后,应用程序通过 RespondToAuthChallenge or AdminRespondToAuthChallenge 请求来选定对应的质询。假设用户希望使用电子邮件消息一次性密码完成无密码身份验证。
{
"ChallengeName": "SELECT_CHALLENGE",
"ChallengeResponses": {
"USERNAME" : "testuser",
"ANSWER" : "EMAIL_OTP"
},
"ClientId": "1example23456789",
"Session": "[Session ID from the previous response]"
}
Amazon Cognito 会返回一个 EMAIL_OTP 质询,并向该用户已验证的电子邮件地址发送一个验证码。随后,您的应用程序必须再次对该质询作出响应。
如果您之前请求了 EMAIL_OTP 作为 PREFERRED_CHALLENGE,那么这同样会是接下来的质询响应步骤。
{
"ChallengeName": "EMAIL_OTP",
"ChallengeResponses": {
"USERNAME" : "testuser",
"EMAIL_OTP_CODE" : "123456"
},
"ClientId": "1example23456789",
"Session": "[Session ID from the previous response]"
}
使用 WebAuthn 通行密钥进行无密码登录
通行密钥是安全的,对用户施加的工作量相对较低。通行密钥登录利用身份验证器,即用户可用于身份验证的外部设备。常规密码容易使用户面临钓鱼攻击、密码猜测和凭证盗用等漏洞。而使用通行密钥,您的应用程序可以利用手机及其他与信息系统连接或内置的设备中的高级安全措施。常见的通行密钥登录工作流通常始于向您的设备发起一次调用,以触发您的密码或凭证 管理器,例如 iOS 钥匙串或 Google Chrome 密码管理器。设备上的凭证管理器会提示用户选择一个通行密钥,并通过已有的凭据或设备解锁机制进行授权。现代手机配备了人脸识别、指纹识别、解锁图案等机制,其中一些机制可同时满足强身份验证中的所知因素 和所有因素 原则。在使用生物识别进行通行密钥身份验证的情况下,通行密钥还体现了所是因素.这一身份验证因素。
您可能希望用指纹、面部识别或安全密钥身份验证来替代密码。这就是通行密钥 或 WebAuthn 身份验证。应用程序开发人员通常允许用户在首次使用密码登录后注册生物识别设备。通过 Amazon Cognito 用户池,您的应用程序可以为用户配置此登录选项。通行密钥身份验证不符合多重身份验证(MFA)的条件。
无密码身份验证流程与用户池中必需的多重身份验证(MFA)不兼容。如果您的用户池将 MFA 设为可选,则已启用 MFA 的用户无法使用无密码方式作为第一重身份验证因素进行登录。在 MFA 为可选的用户池中,没有 MFA 偏好的用户可以使用无密码身份验证因素进行登录。有关更多信息,请参阅有关用户池 MFA 的需知信息。
通行密钥是什么?
通行密钥无需记住复杂的密码或输入 OTP,从而简化了用户体验。通行密钥基于由 World Wide Web Consortium(W3C)和 FIDO(Fast Identity Online)联盟共同制定的 WebAuthn 和 CTAP2 标准。浏览器和平台实现了这些标准,为 Web 或移动应用程序提供 API,以启动通行密钥注册或身份验证流程,同时也提供 UI,供用户选择通行密钥身份验证器 并与之进行交互。
当用户在网站或应用程序中注册一个身份验证器时,该身份验证器会生成一对公有-私有密钥对。支持 WebAuthn 的浏览器和平台会将公有密钥提交给该网站或应用程序的后端。身份验证器则保留私有密钥、密钥 ID 以及关于用户和应用程序的元数据。当用户希望使用已注册的身份验证器在注册的应用程序中进行身份验证时,该应用程序会生成一个随机质询。对该质询的响应是由身份验证器使用其为该用户和应用程序所保存的私有密钥生成的质询数字签名,并附带相关元数据。浏览器或应用程序平台接收到该数字签名后,会将其传递给应用程序后端。然后,应用程序使用之前存储的公有密钥来验证该签名。
您的应用程序不会收到用户向其身份验证器提供的任何身份验证密钥,也不会获得有关私有密钥的任何信息。
以下是一些当前市场上身份验证器的示例及其功能。某个身份验证器可能符合其中任意一类或多类。
-
某些身份验证器在授予访问权限前会执行用户验证,使用的因素包括 PIN、面部或指纹等生物识别输入或密码,以确保只有合法用户才能授权操作。另一些身份验证器则不具备任何用户验证功能,还有一些在应用程序未要求时可以跳过用户验证。
-
某些身份验证器,例如 YubiKey 硬件令牌,具有便携性。它们可通过 USB、蓝牙或 NFC 连接与设备通信。有些身份验证器则属于本地身份验证器,并与特定平台绑定,例如 PC 上的 Windows Hello 或 iPhone 上的 Face ID。如果设备足够小巧(如移动设备),设备绑定的身份验证器可由用户随身携带。有时,用户还能通过无线通信方式将硬件身份验证器连接到多个不同平台。例如,在桌面浏览器中,用户扫描一个二维码后,即可使用自己的智能手机作为通行密钥身份验证器。
-
一些平台绑定的通行密钥会同步到云端,从而支持用户在多个设备上使用。例如,iPhone 上的 Face ID 通行密钥会将通行密钥元数据通过用户的 Apple 账户同步至 iCloud 钥匙串。这类通行密钥可在 Apple 设备之间实现无缝身份验证,不需要用户为每台设备单独注册。1Password、Dashlane 和 Bitwarden 等基于软件的身份验证器应用程序,也会在用户安装了该应用程序的所有平台上同步通行密钥。
在 WebAuthn 术语中,网站和应用程序被称为依赖方。每个通行密钥都与一个特定的依赖方 ID 关联,依赖方 ID 是一个统一标识符,代表接受该通行密钥进行身份验证的网站或应用程序。开发人员必须谨慎选择其依赖方 ID,以确保身份验证的范围恰当。典型的依赖方 ID 是 Web 服务器的根域名。使用该依赖方 ID 规范的通行密钥可用于该域及其所有子域的身份验证。当用户尝试访问的网站 URL 与依赖方 ID 不匹配时,浏览器和平台会拒绝通行密钥身份验证。类似地,对于移动应用程序,只有当应用程序路径出现在由该应用程序在依赖方 ID 所指定的路径下公开提供的 .well-known 关联文件中时,通行密钥才能被使用。
通行密钥具有可发现性。浏览器或平台可以自动识别并使用它们,无需用户手动输入用户名。当用户访问支持通行密钥身份验证的网站或应用程序时,可以从浏览器或平台已知的通行密钥列表中进行选择,也可以扫描二维码。
Amazon Cognito 如何实现通行密钥身份验证?
通行密钥是一项可选功能,在除精简版外的所有功能计划中均可用。它仅支持基于选择的身份验证流程。使用托管登录时,Amazon Cognito 会处理通行密钥身份验证的逻辑。您也可以在应用程序后端使用 Amazon SDK 中的 Amazon Cognito 用户池 API 来实现通行密钥身份验证。
Amazon Cognito 支持使用两种非对称加密算法创建的通行密钥:ES256(-7) 和 RS256(-257)。大多数身份验证器都支持这两种算法。默认情况下,用户可以设置任意类型的身份验证器,例如硬件令牌、移动智能手机或软件身份验证器应用程序。Amazon Cognito 目前不支持证明强制执行。
在用户池中,您可以将用户验证配置为首选或必需。在未提供值的 API 请求中,该选项默认选择首选,而在 Amazon Cognito 控制台中,该选项也默认选择首选。当您将用户验证设置为首选时,用户可以设置不具备用户验证功能的身份验证器,且注册和身份验证操作可在不执行用户验证的情况下成功完成。要强制在通行密钥注册和身份验证过程中进行用户验证,请将此设置更改为必需。
您在通行密钥配置中设置的依赖方(RP)ID 是一项关键决策。如果您未另行指定,且您的域品牌版本使用的是托管登录,则用户池默认会将您的自定义域作为预期的 RP ID。如果您没有配置自定义域,也未另行指定 RP ID,则用户池默认使用您的前缀域作为 RP ID。您也可以将 RP ID 配置为任意一个不在公共后缀列表(PSL)中的域名。您的 RP ID 条目适用于托管登录和 SDK 身份验证中的通行密钥注册与身份验证。在移动应用程序中,通行密钥仅在 Amazon Cognito 能够在以您的 RP ID 为域的路径下找到 .well-known 关联文件时才能正常工作。作为最佳实践,请在您的网站或应用程序公开上线前,确定并设置好依赖方 ID 的值。如果您更改了 RP ID,用户必须使用新的 RP ID 重新注册。
每个用户最多可以注册 20 个通行密钥。用户必须至少成功登录过您的用户池一次后,才能注册通行密钥。托管登录能大幅简化通行密钥的注册流程。当您为用户池和应用程序客户端启用通行密钥身份验证后,使用托管登录域的用户池会在最终用户注册新用户账户后,自动提示其注册通行密钥。您也可以在任意时间引导用户的浏览器跳转至托管登录页面,以完成通行密钥注册。用户必须先提供用户名,Amazon Cognito 才能启动通行密钥身份验证。托管登录会自动处理这一过程。登录页面会先提示用户输入用户名,验证该用户是否已注册至少一个通行密钥,然后提示其使用通行密钥登录。同样地,在基于 SDK 的应用程序中,也必须先提示用户输入用户名,并在身份验证请求中提供该用户名。
当您为用户池配置通行密钥身份验证,并且同时拥有自定义域和前缀域时,RP ID 默认会使用您自定义域的完全限定域名(FQDN)。要在 Amazon Cognito 控制台中将前缀域设置为 RP ID,请删除您的自定义域,或将前缀域的 FQDN 作为第三方域手动输入。
- Activate passkey sign-in
-
控制台
要激活通行密钥登录,请先配置您的用户池,以允许使用一种或多种无密码类型作为主要登录方式,然后配置您的应用程序客户端以允许 USER_AUTH 身份验证流程。在 Amazon Cognito 控制台中,导航到用户池配置中身份验证下的登录菜单。编辑基于选择的登录选项,然后将通行密钥添加到可用选项列表中。
导航到身份验证方法菜单并编辑通行密钥。
-
用户验证是一项设置,用于控制您的用户池是否要求通行密钥设备执行额外的检查,以确认当前用户有权使用通行密钥。要鼓励用户配置设备以支持用户验证,但不强制要求,请选择首选。要仅支持具备用户验证功能的设备,请选择必需。有关更多信息,请参阅 w3.org 上的用户验证。
-
依赖方 ID 的域是应用程序将在用户的通行密钥注册请求中传递的标识符。它设定了与用户通行密钥颁发者的信任关系的目标。您的依赖方 ID 可以是:您的用户池的域,前提是
- Cognito 域
-
您的用户池中的 Amazon Cognito 前缀域。
- 自定义域
-
您的用户池的自定义域。
- 第三方域
-
指用于不使用用户池托管登录页面的应用程序的域。此设置通常适用于未配置域的用户池,其身份验证通过后端的 Amazon SDK 和用户池 API 来完成。
导航到应用程序客户端菜单,然后选择一个应用程序客户端或新建一个。选择编辑,在身份验证流程下,选择登录时选择身份验证类型:ALLOW_USER_AUTH。
API/SDK
在用户池 API 中,在 CreateUserPool 或 UpdateUserPool 请求中使用相应的通行密钥选项配置 SignInPolicy。通行密钥身份验证的 WEB_AUTHN 选项必须至少附带一个其他选项。通行密钥注册需要现有的身份验证会话。
"SignInPolicy": {
"AllowedFirstAuthFactors": [
"PASSWORD",
"WEB_AUTHN"
]
}
在 SetUserPoolMfaConfig 请求的 WebAuthnConfiguration 参数中,配置您的用户验证首选项和 RP ID。其中,RelyingPartyId(即通行密钥身份验证结果的预期目标)可以是您的用户池前缀域、自定义域,或您自行指定的其他域。
"WebAuthnConfiguration": {
"RelyingPartyId": "example.auth.us-east-1.amazoncognito.com",
"UserVerification": "preferred"
}
在 CreateUserPoolClient 或 UpdateUserPoolClient 请求中,为您的应用程序客户端 ExplicitAuthFlows 配置所需的选项。
"ExplicitAuthFlows": [
"ALLOW_USER_AUTH"
]
- Register a passkey (managed login)
-
托管登录负责处理用户通行密钥的注册。当您的用户池启用了通行密钥身份验证后,Amazon Cognito 会在用户注册新账户时提示其设置通行密钥。
当用户已完成注册但尚未设置通行密钥,或您作为管理员为其创建了账户时,Amazon Cognito 不会提示用户设置通行密钥。处于这种状态的用户必须先使用其他身份验证因素(例如密码或无密码 OTP)成功登录,才能注册通行密钥。
注册通行密钥
-
将用户引导至您的登录页面。
https://auth.example.com/oauth2/authorize/?client_id=1example23456789&response_type=code&scope=email+openid+phone&redirect_uri=https%3A%2F%2Fwww.example.com
-
处理用户的身份验证结果。在此示例中,Amazon Cognito 会将用户重定向到 www.example.com,并附带一个应用程序可用来换取令牌的授权码。
-
将用户引导至您的注册通行密钥页面。用户浏览器中有一个 Cookie,用于维持其已登录会话。该通行密钥页面的 URL 需包含 client_id 和 redirect_uri 参数。Amazon Cognito 仅允许已通过身份验证的用户访问此页面。请先使用密码、电子邮件 OTP 或短信 OTP 让用户完成登录,然后调用符合以下模式的 URL。
您还可以在此请求中添加其他对端点授权参数,例如 response_type 和 scope。
https://auth.example.com/passkeys/add?client_id=1example23456789&redirect_uri=https%3A%2F%2Fwww.example.com
- Register a passkey (SDK)
-
您可以通过一个 PublicKeyCreationOptions 对象来注册包含元数据的通行密钥凭证。您可以使用已登录用户的凭证生成该对象,并将其以 API 请求的形式提交给用户的通行密钥颁发者。颁发者将返回一个 RegistrationResponseJSON 对象,用于确认通行密钥注册。
要开始通行密钥注册过程,请使用现有登录选项登录用户。使用当前用户的访问令牌,对经过令牌授权的 StartWebAuthnRegistration API 请求进行授权。以下是一个示例 GetWebAuthnRegistrationOptions 请求的正文。
{
"AccessToken": "eyJra456defEXAMPLE"
}
您的用户池返回的响应中包含 PublicKeyCreationOptions 对象。请将该对象以 API 请求的方式发送给用户的颁发者。此对象提供公有密钥和依赖方 ID 等信息。颁发者随后将返回一个 RegistrationResponseJSON 对象。
将注册响应通过 CompleteWebAuthnRegistration API 请求提交,该请求同样需使用用户的访问令牌进行授权。当您的用户池返回一个 HTTP 200 响应且正文为空时,即表示该用户的通行密钥已注册。
- Sign in with a passkey
-
无密码登录没有可在 InitiateAuth 和 AdminInitiateAuth 中指定的 AuthFlow。相反,您必须声明 AuthFlow 为 USER_AUTH,然后请求一个登录选项,或根据用户池返回的响应选择您的无密码登录方式。要将用户登录到应用程序,请按如下方式配置 InitiateAuth 或 AdminInitiateAuth 请求的正文。以下参数集合是登录所需的最低要求。此外还支持其他参数。
在此示例中,我们知道用户希望使用通行密钥登录,因此我们添加了一个 PREFERRED_CHALLENGE 参数。
{
"AuthFlow": "USER_AUTH",
"AuthParameters": {
"USERNAME" : "testuser",
"PREFERRED_CHALLENGE" : "WEB_AUTHN"
},
"ClientId": "1example23456789"
}
Amazon Cognito 以 WEB_AUTHN 质询进行响应。您的应用程序必须对该质询作出响应。向用户的通行密钥提供商发起一个登录请求。这将返回一个 AuthenticationResponseJSON 对象。
{
"ChallengeName": "WEB_AUTHN",
"ChallengeResponses": {
"USERNAME" : "testuser",
"CREDENTIAL" : "{AuthenticationResponseJSON}"
},
"ClientId": "1example23456789",
"Session": "[Session ID from the previous response]"
}
登录后进行 MFA
您可以设置用户在通过用户名密码流程完成登录后,被提示进行额外的验证,例如通过电子邮件消息、短信或验证码生成应用程序提供的一次性密码。MFA 不同于无密码登录,后者使用一次性密码或 WebAuthn 通行密钥作为第一重身份验证因素,并不包含 MFA。而在用户池中,MFA 采用质询-响应模式,即用户首先证明自己知道密码,然后再证明自己能够访问已注册的第二因素设备。
刷新令牌
当您希望用户在无需重新输入凭证的情况下保持登录状态时,刷新令牌 是您的应用程序可用于持久化用户会话的工具。应用程序可以向您的用户池提供刷新令牌,并将其兑换为新的 ID 令牌和访问令牌。通过令牌刷新,您可以在无需用户干预的情况下,确保已登录用户仍处于活跃状态、获取更新后的属性信息,并更新访问控制权限。
自定义身份验证
您可能希望为用户配置一种此处未列出的身份验证方法。您可以使用带有 Lambda 触发器的自定义身份验证 来实现这一点。在一系列 Lambda 函数中,Amazon Cognito 会发出一个质询,向用户提出一个用户必须回答的问题,验证回答的准确性,并确定是否应发出另一个质询。这些问题和回答可以包括安全问题、对 CAPTCHA 服务的请求、对外部 MFA 服务 API 的请求,或按顺序组合使用以上所有方式。
自定义身份验证流程
Amazon Cognito 用户池实现了使用自定义身份验证流程,这可以帮助您使用 Amazon Lambda 触发器创建基于质询/响应的身份验证模型。
自定义身份验证流程可以自定义质询和响应周期,以满足不同需求。该流程首先调用 InitiateAuth API 操作,该调用指示将使用的身份验证类型并提供了所有初始身份验证参数。Amazon Cognito 将使用以下类型的信息之一响应 InitiateAuth 调用:
如果 Amazon Cognito 使用质询响应 InitiateAuth 调用,则应用程序将收集更多输入并调用 RespondToAuthChallenge 操作。此调用提供质询响应并将其传回会话。Amazon Cognito 对 RespondToAuthChallenge 的响应类似于对 InitiateAuth 调用的响应。如果用户已登录,Amazon Cognito 会提供令牌,如果用户未登录,则 Amazon Cognito 会提供另一个质询或错误。如果 Amazon Cognito 返回另一质询,则序列重复,应用程序调用 RespondToAuthChallenge 直到用户成功登录或返回错误。有关 InitiateAuth 和 RespondToAuthChallenge API 操作的详细信息,请参阅 API 文档。
自定义身份验证流程和质询
应用程序可以启动自定义身份验证流程,具体方法是:调用 InitiateAuth 并将 CUSTOM_AUTH 用作 Authflow。借助自定义身份验证流程,三个 Lambda 触发器控制响应的质询和验证。
-
DefineAuthChallenge Lambda 触发器将以前的质询和响应的会话数组作为输入。然后,它生成下一个质询名称和布尔值,指示用户是否通过身份验证并且应被授予令牌。此 Lambda 触发器是一个状态机,可通过质询控制用户的路径。
-
CreateAuthChallenge Lambda 触发器将质询名称作为输入并生成质询和参数以评估响应。当 DefineAuthChallenge 返回 CUSTOM_CHALLENGE 作为下一次质询时,身份验证流程调用 CreateAuthChallenge。CreateAuthChallenge Lambda 触发器在质询元数据参数中传递下一个类型的质询。
-
VerifyAuthChallengeResponse Lambda 函数会评估响应并返回布尔值以表明响应是否有效。
自定义身份验证流程还可以使用内置质询的组合,例如 SRP 密码验证和通过短信进行的 MFA。它可以使用自定义质询,如验证码或秘密问题。
在自定义身份验证流程中使用 SRP 密码验证
如果您希望将 SRP 包含在自定义身份验证流程中,则您必须开始使用 SRP。
-
要在自定义流程中启动 SRP 密码验证,应用程序将 InitiateAuth 作为 CUSTOM_AUTH 来调用 Authflow。在 AuthParameters 映射 中,来自应用程序的请求包括 SRP_A:(SRP A 值)和 CHALLENGE_NAME:
SRP_A。
-
CUSTOM_AUTH 流会使用 challengeName: SRP_A 和 challengeResult: true 的初始会话调用 DefineAuthChallenge Lambda 触发器。您的 Lambda 函数使用 challengeName: PASSWORD_VERIFIER、issueTokens: false 和 failAuthentication: false 作出响应。
-
接下来,该应用程序必须使用 challengeName: PASSWORD_VERIFIER 和 challengeResponses 映射中 SRP 所需的其它参数调用 RespondToAuthChallenge。
-
如果 Amazon Cognito 验证了密码,RespondToAuthChallenge 使用 challengeName: PASSWORD_VERIFIER 和 challengeResult:
true 的第二个会话调用 DefineAuthChallenge Lambda 触发器。此时,DefineAuthChallenge Lambda 触发器可以使用 challengeName: CUSTOM_CHALLENGE 响应来开启自定义质询。
-
如果为用户启用了 MFA,则在 Amazon Cognito 验证密码后,您的用户将被要求设置 MFA 或使用 MFA 登录。
有关 Lambda 触发器的更多信息,包括示例代码,请参阅使用 Lambda 触发器自定义用户池工作流。
用户迁移身份验证流程
用户迁移 Lambda 触发器可帮助您将用户从旧式用户管理系统迁移到您的用户池。如果选择 USER_PASSWORD_AUTH 身份验证流程,则用户在用户迁移过程中无需重置密码。此流程在身份验证期间通过加密的 SSL 连接向服务发送用户的密码。
所有用户均完成迁移后,请切换为更安全的 SRP 流程。SRP 流程不通过网络发送任何密码。
要了解有关 Lambda 触发器的更多信息,请参阅使用 Lambda 触发器自定义用户池工作流。
有关使用 Lambda 触发器迁移用户的更多信息,请参阅利用用户迁移 Lambda 触发器导入用户。