如何在 AWS Cognito 身份验证过程中包含 TOTP MFA
How to include TOTP MFA in AWS Cognito authentication process
我正在使用 Cognito 用户池来验证我的 Web 应用程序。我现在一切正常,但现在我需要为其启用 MFA。我现在就是这样做的(所有提供的代码都是服务器端代码):
- 注册用户:
const cognito = new AWS.CognitoIdentityServiceProvider();
cognito.signUp({
ClientId,
Username: email,
Password,
}).promise();
一封电子邮件被发送到用户的地址(在之前的函数调用中被称为用户名),其中包含一个代码。
用户读取代码并提供代码给下一个函数调用:
cognito.confirmSignUp({
ClientId,
ConfirmationCode,
Username: email,
ForceAliasCreation: false,
}).promise();
- 用户登录:
const tokens = await cognito.adminInitiateAuth({
AuthFlow: 'ADMIN_NO_SRP_AUTH',
ClientId,
UserPoolId,
AuthParameters: {
'USERNAME': email,
'PASSWORD': password,
},
}).promise();
我对这个过程很满意。但现在我需要为此添加 TOTP MFA 功能。如果我想这样做,有人可以告诉我如何更改这些步骤吗?顺便说一句,我知道在创建用户池时需要为它启用 TOTP MFA。我只是想问一下它如何影响我的 sign-up/log-in 流程。
好的,我自己找到了方法。我必须说,我找不到任何关于此的文档,所以使用它需要您自担风险!
当然,此过程假设您有一个启用了 MFA 的用户池(我使用了 TOTP MFA)。
- 注册用户:
const cognito = new AWS.CognitoIdentityServiceProvider();
cognito.signUp({
ClientId,
Username: email,
Password,
}).promise();
一封电子邮件被发送到用户的地址(在之前的函数调用中被称为用户名),其中包含一个代码。
用户读取代码并提供代码给下一个函数调用:
cognito.confirmSignUp({
ClientId,
ConfirmationCode: code,
Username: email,
ForceAliasCreation: false,
}).promise();
- 首次登录:
await cognito.adminInitiateAuth({
AuthFlow: 'ADMIN_NO_SRP_AUTH',
ClientId,
UserPoolId,
AuthParameters: {
'USERNAME': email,
'PASSWORD': password,
},
}).promise();
此时,return 值将有所不同(与未强制执行 MFA 时您将获得的值相比)。 return 值类似于:
{
"ChallengeName": "MFA_SETUP",
"Session": "...",
"ChallengeParameters": {
"MFAS_CAN_SETUP": "[\"SOFTWARE_TOKEN_MFA\"]",
"USER_ID_FOR_SRP": "..."
}
}
returned 对象说用户需要先完成 MFA_SETUP
挑战才能登录(每个用户注册都会发生一次)。
- 为用户启用 TOTP MFA:
cognito.associateSoftwareToken({
Session,
}).promise();
需要之前的调用,因为有两个选项,通过发出给定的调用,您告诉 Cognito 您希望您的用户启用 TOTP MFA(而不是 SMS MFA)。 Session
输入是前一个函数调用的 return。现在,这次它将 return 这个值:
{
"SecretCode": "...",
"Session": "..."
}
用户必须获取给定的 SecretCode
并将其输入到 "Google Authenticator" 等应用程序中。添加后,该应用程序将开始显示每分钟刷新一次的 6 位数字。
验证验证器应用程序:
cognito.verifySoftwareToken({
UserCode: '123456',
Session,
}).promise()
Session
输入将是在第 5 步中输入的字符串 return,UserCode
是目前验证器应用程序上显示的 6 位数字。如果成功完成,您将获得此 return 值:
{
"Status": "SUCCESS",
"Session": "..."
}
我没有发现此对象对 return 会话有任何用处。现在,注册过程已完成,用户可以登录了。
- 实际登录(每次用户想要验证自己时都会发生):
await cognito.adminInitiateAuth({
AuthFlow: 'ADMIN_NO_SRP_AUTH',
ClientId,
UserPoolId,
AuthParameters: {
'USERNAME': email,
'PASSWORD': password,
},
}).promise();
当然,这与第 4 步相同。但其 returned 值不同:
{
"ChallengeName": "SOFTWARE_TOKEN_MFA",
"Session": "...",
"ChallengeParameters": {
"USER_ID_FOR_SRP": "..."
}
}
这是告诉您,为了完成登录过程,您需要遵循 SOFTWARE_TOKEN_MFA
挑战过程。
- 通过提供 MFA 完成登录过程:
cognito.adminRespondToAuthChallenge({
ChallengeName: "SOFTWARE_TOKEN_MFA",
ClientId,
UserPoolId,
ChallengeResponses: {
"USERNAME": config.username,
"SOFTWARE_TOKEN_MFA_CODE": mfa,
},
Session,
}).promise()
Session
输入是第 8 步 return 编辑的输入,mfa
是需要从身份验证器应用程序读取的 6 位数字。调用该函数后,它将 return 标记:
{
"ChallengeParameters": {},
"AuthenticationResult": {
"AccessToken": "...",
"ExpiresIn": 3600,
"TokenType": "Bearer",
"RefreshToken": "...",
"IdToken": "..."
}
}
我正在使用 Cognito 用户池来验证我的 Web 应用程序。我现在一切正常,但现在我需要为其启用 MFA。我现在就是这样做的(所有提供的代码都是服务器端代码):
- 注册用户:
const cognito = new AWS.CognitoIdentityServiceProvider();
cognito.signUp({
ClientId,
Username: email,
Password,
}).promise();
一封电子邮件被发送到用户的地址(在之前的函数调用中被称为用户名),其中包含一个代码。
用户读取代码并提供代码给下一个函数调用:
cognito.confirmSignUp({
ClientId,
ConfirmationCode,
Username: email,
ForceAliasCreation: false,
}).promise();
- 用户登录:
const tokens = await cognito.adminInitiateAuth({
AuthFlow: 'ADMIN_NO_SRP_AUTH',
ClientId,
UserPoolId,
AuthParameters: {
'USERNAME': email,
'PASSWORD': password,
},
}).promise();
我对这个过程很满意。但现在我需要为此添加 TOTP MFA 功能。如果我想这样做,有人可以告诉我如何更改这些步骤吗?顺便说一句,我知道在创建用户池时需要为它启用 TOTP MFA。我只是想问一下它如何影响我的 sign-up/log-in 流程。
好的,我自己找到了方法。我必须说,我找不到任何关于此的文档,所以使用它需要您自担风险!
当然,此过程假设您有一个启用了 MFA 的用户池(我使用了 TOTP MFA)。
- 注册用户:
const cognito = new AWS.CognitoIdentityServiceProvider();
cognito.signUp({
ClientId,
Username: email,
Password,
}).promise();
一封电子邮件被发送到用户的地址(在之前的函数调用中被称为用户名),其中包含一个代码。
用户读取代码并提供代码给下一个函数调用:
cognito.confirmSignUp({
ClientId,
ConfirmationCode: code,
Username: email,
ForceAliasCreation: false,
}).promise();
- 首次登录:
await cognito.adminInitiateAuth({
AuthFlow: 'ADMIN_NO_SRP_AUTH',
ClientId,
UserPoolId,
AuthParameters: {
'USERNAME': email,
'PASSWORD': password,
},
}).promise();
此时,return 值将有所不同(与未强制执行 MFA 时您将获得的值相比)。 return 值类似于:
{
"ChallengeName": "MFA_SETUP",
"Session": "...",
"ChallengeParameters": {
"MFAS_CAN_SETUP": "[\"SOFTWARE_TOKEN_MFA\"]",
"USER_ID_FOR_SRP": "..."
}
}
returned 对象说用户需要先完成 MFA_SETUP
挑战才能登录(每个用户注册都会发生一次)。
- 为用户启用 TOTP MFA:
cognito.associateSoftwareToken({
Session,
}).promise();
需要之前的调用,因为有两个选项,通过发出给定的调用,您告诉 Cognito 您希望您的用户启用 TOTP MFA(而不是 SMS MFA)。 Session
输入是前一个函数调用的 return。现在,这次它将 return 这个值:
{
"SecretCode": "...",
"Session": "..."
}
用户必须获取给定的
SecretCode
并将其输入到 "Google Authenticator" 等应用程序中。添加后,该应用程序将开始显示每分钟刷新一次的 6 位数字。验证验证器应用程序:
cognito.verifySoftwareToken({
UserCode: '123456',
Session,
}).promise()
Session
输入将是在第 5 步中输入的字符串 return,UserCode
是目前验证器应用程序上显示的 6 位数字。如果成功完成,您将获得此 return 值:
{
"Status": "SUCCESS",
"Session": "..."
}
我没有发现此对象对 return 会话有任何用处。现在,注册过程已完成,用户可以登录了。
- 实际登录(每次用户想要验证自己时都会发生):
await cognito.adminInitiateAuth({
AuthFlow: 'ADMIN_NO_SRP_AUTH',
ClientId,
UserPoolId,
AuthParameters: {
'USERNAME': email,
'PASSWORD': password,
},
}).promise();
当然,这与第 4 步相同。但其 returned 值不同:
{
"ChallengeName": "SOFTWARE_TOKEN_MFA",
"Session": "...",
"ChallengeParameters": {
"USER_ID_FOR_SRP": "..."
}
}
这是告诉您,为了完成登录过程,您需要遵循 SOFTWARE_TOKEN_MFA
挑战过程。
- 通过提供 MFA 完成登录过程:
cognito.adminRespondToAuthChallenge({
ChallengeName: "SOFTWARE_TOKEN_MFA",
ClientId,
UserPoolId,
ChallengeResponses: {
"USERNAME": config.username,
"SOFTWARE_TOKEN_MFA_CODE": mfa,
},
Session,
}).promise()
Session
输入是第 8 步 return 编辑的输入,mfa
是需要从身份验证器应用程序读取的 6 位数字。调用该函数后,它将 return 标记:
{
"ChallengeParameters": {},
"AuthenticationResult": {
"AccessToken": "...",
"ExpiresIn": 3600,
"TokenType": "Bearer",
"RefreshToken": "...",
"IdToken": "..."
}
}