Хорошо, я нашел способ сделать это сам. Должен сказать, что я не смог найти никакой документации по этому вопросу, поэтому используйте ее на свой страх и риск!
Конечно, этот процесс предполагает, что у вас есть пул пользователей с включенным 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();
На этом этапе возвращаемое значение будет другим (по сравнению с тем, что вы получите, если MFA не применяется). Возвращаемое значение будет примерно таким:
{
"ChallengeName": "MFA_SETUP",
"Session": "...",
"ChallengeParameters": {
"MFAS_CAN_SETUP": "[\"SOFTWARE_TOKEN_MFA\"]",
"USER_ID_FOR_SRP": "..."
}
}
Возвращенный объект говорит, что пользователь должен выполнить вызов MFA_SETUP
, прежде чем он сможет войти в систему (это происходит один раз при регистрации пользователя).
Включите TOTP MFA для пользователя:
cognito.associateSoftwareToken({
Session,
}).promise();
Предыдущий вызов необходим, потому что есть две опции, и, отправляя данный вызов, вы сообщаете Cognito, что вы хотите, чтобы ваш пользователь включить TOTP MFA (вместо SMS MFA). Вход Session
- это результат, возвращаемый предыдущим вызовом функции. Теперь на этот раз он вернет это значение:
{
"SecretCode": "...",
"Session": "..."
}
Пользователь должен взять данное SecretCode
и ввести его в приложение, такое как «Google Authenticator». После добавления приложение начнет показывать число 6 git, которое обновляется каждую минуту.
Проверьте приложение-аутентификатор:
cognito.verifySoftwareToken({
UserCode: '123456',
Session,
}).promise()
Вводом Session
будет строка, возвращаемая на шаге 5, а UserCode
- это 6 цифр, отображаемых в приложении для проверки подлинности в данный момент. Если это будет сделано успешно, вы получите это возвращаемое значение:
{
"Status": "SUCCESS",
"Session": "..."
}
Я не нашел никакого использования для сеанса, возвращаемого этим объектом. Теперь процесс регистрации завершен, и пользователь может войти в систему.
Фактический вход в систему (который происходит каждый раз, когда пользователи хотят аутентифицировать себя):
await cognito.adminInitiateAuth({
AuthFlow: 'ADMIN_NO_SRP_AUTH',
ClientId,
UserPoolId,
AuthParameters: {
'USERNAME': email,
'PASSWORD': password,
},
}).promise();
Конечно, это было идентично шагу 4. Но его возвращаемое значение отличается:
{
"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, а mfa
- это 6 цифр, которые необходимо прочитать из приложение для проверки подлинности. Как только вы вызовете функцию, она вернет токены:
{
"ChallengeParameters": {},
"AuthenticationResult": {
"AccessToken": "...",
"ExpiresIn": 3600,
"TokenType": "Bearer",
"RefreshToken": "...",
"IdToken": "..."
}
}