[英]React & AWS Amplify - User does not have delivery config set to turn on SMS_MFA
I have a React web application (utilizing aws-amplify) which is connecting to AWS Cognito User Pool for authentication.我有一个 React web 应用程序(使用 aws-amplify),它连接到 AWS Cognito 用户池进行身份验证。
User of my application can optionally enable SMS MFA from settings.我的应用程序的用户可以选择从设置中启用 SMS MFA。
I tried to enable SMS MFA using aws amplify npm package but I'm facing an error saying我尝试使用aws amplify npm package启用 SMS MFA,但我遇到一个错误说
{
"__type": "InvalidParameterException",
"message": "User does not have delivery config set to turn on SMS_MFA"
}
I have set MFA to "Optional" on AWS Cognito User Pools settings as seen in the screenshot below.我已在 AWS Cognito 用户池设置中将 MFA 设置为“可选”,如下面的屏幕截图所示。
And here's my component logic这是我的组件逻辑
import React, { useState, useEffect } from 'react';
import { Card, Grid, Typography, Box, Switch } from '@material-ui/core';
import { Auth } from 'aws-amplify';
const Profile = () => {
const [currentUser, setCurrentUser] = useState(null);
// use this state to highlight MFA status
const [isMFAEnabled, setIsMFAEnabled] = useState(false);
const toggleMFA = async () => {
const preferredMFA = isMFAEnabled ? 'NOMFA' : 'SMS';
try {
const result = await Auth.setPreferredMFA(currentUser, preferredMFA);
setIsMFAEnabled(!isMFAEnabled);
// Auth.enableSMS(currentUser);
} catch (error) {
console.log('error :: ', error);
}
};
useEffect(() => {
async function fetchProfileData() {
const user = await Auth.currentAuthenticatedUser();
setCurrentUser(user);
// enable or disabled MFA switch
const { preferredMFA } = user;
setIsMFAEnabled(!(preferredMFA && preferredMFA === 'NOMFA'));
}
fetchProfileData();
}, []);
return (
<>
<Grid
container
direction="row"
justifyContent="center"
alignItems="center"
>
<Grid item xs={12} sm={12} md={10} lg={8} xl={6}>
<Card>
<Typography variant="h4">Security</Typography>
<Box
display="flex"
flexDirection="row"
alignItems="center"
>
<Typography variant="subtitle">
Two factor authentication
</Typography>
<Switch
checked={isMFAEnabled}
onChange={toggleMFA}
name="MFA"
/>
</Box>
</Card>
</Grid>
</Grid>
</>
);
};
export default Profile;
I got this error too and it took me a while to figure out what was wrong我也遇到了这个错误,我花了一段时间才弄清楚出了什么问题
My Cognito's configuration:我的 Cognito 的配置:
No Verification
No Verification
This is how I solved the issue:这就是我解决问题的方法:
First, I used AWS CLI to reproduce the steps to onboard users:首先,我使用 AWS CLI 向板载用户重现这些步骤:
aws cognito-idp admin-create-user \
--user-pool-id <user-pool-id> \
--username <user_email> \
--user-attributes Name="email",Value="<user_email>" Name="name",Value="Alice" Name="family_name",Value="Doe" Name="email_verified",Value="true" \
--force-alias-creation \
--temporary-password "LongSecret132@" \
--desired-delivery-mediums "EMAIL" \
--profile <aws_config_profile>
This is why I create users with --desired-delivery-mediums "EMAIL"
, above这就是为什么我使用
--desired-delivery-mediums "EMAIL"
创建用户的原因
FORCE_CHANGE_PASSWORD
statusFORCE_CHANGE_PASSWORD
状态aws cognito-idp admin-set-user-password --user-pool-id <user-pool-id> --username <user_email> --password "NewSecret@111" --permanent --profile <aws_config_profile>
Name="phone_number",Value="<user_phone_number>"
and Name="phone_number_verified",Value="true"
in step 1.Name="phone_number",Value="<user_phone_number>"
和Name="phone_number_verified",Value="true"
.aws cognito-idp admin-update-user-attributes \
--user-pool-id <user-pool-id> \
--username <user_email> \
--user-attributes Name="phone_number",Value="+447000200100" Name="phone_number_verified",Value="true" \
--profile <aws_config_profile>
aws cognito-idp admin-set-user-mfa-preference \
--user-pool-id <user-pool-id> \
--username <user_email> \
--sms-mfa-settings Enabled=true,PreferredMfa=true \
--profile <aws_config_profile>
So I did this all manually and then using the UI I tried to authenticate and Cognito did send me an SMS.所以我手动完成了这一切,然后使用我尝试进行身份验证的 UI,Cognito 确实向我发送了一条短信。 And no error.
并且没有错误。
My conclusion is that the error happens when the user attributes (step 5) and mfa preference (step 6) arent setup properly and in the correct order.我的结论是,当用户属性(第 5 步)和 mfa 首选项(第 6 步)没有按正确顺序正确设置时,就会发生错误。
You can try the commands above with a test user.
您可以使用测试用户尝试上述命令。
Second, Amplify docs were useful.其次, Amplify 文档很有用。 The React code could do something like:
React 代码可以执行以下操作:
All you are left with is handling the MFA either for the first time or after,剩下的就是第一次或之后处理 MFA,
const fetchCognitoUser = async (flag = false) => {
const user = await Auth.currentAuthenticatedUser({
bypassCache: flag,
});
return user;
};
const handleMfaAuth = async ({ userObject, mfaToken }) => {
try {
// when MFA is being setup the first time
// checks if this does not exist because
// setting mfa to optional in cognito will not give you a challengeName
if (!userObject.challengeName) {
await Auth.verifyTotpToken(userObject, mfaToken);
// This would be step 6 in the CLI version above.
await Auth.setPreferredMFA(userObject, 'SMS');
const cognitoUser = await fetchCognitoUser().catch((err) => {
console.error(err);
});
if (cognitoUser) {
// any logic to ensure correct Authentication
// Load apps landing page.
}
}
// when the user enters the MFA token
else if (userObject.challengeName === 'SMS_MFA') {
await Auth.confirmSignIn(userObject, mfaToken, 'SMS_MFA');
const cognitoUser = await fetchCognitoUser().catch((err) => {
console.error(err);
});
if (cognitoUser) {
// any logic to ensure correct Authentication
// Load apps landing page.
}
}
} catch (error) {
// Token is not verified
setShowError(true);
}
};
const handleSignIn = async ({ username, password }) => {
try{
const user = await Auth.signIn(username, password);
// if MFA hasn't been setup
// checks if this does not exist because
// setting mfa to optional in cognito will not give you a challengeName
if (!user.challengeName) {
// show the page to set up MFA
setShowSetupMfa(true);
} else if (user.challengeName === 'SMS_MFA') {
// If MFA is enabled, sign-in should be confirmed with the confirmation code
const loggedUser = await Auth.confirmSignIn(
user, // Return object from Auth.signIn()
code, // Confirmation code captured in the UI
mfaType // MFA Type e.g. SMS_MFA, SOFTWARE_TOKEN_MFA
);
// show the page to enter mfa token
setShowMfa(true);
}
} catch (error) {
// handle error
}
}
Hope this helps
希望这可以帮助
Make sure Cognito is correctly configured.确保 Cognito 配置正确。 You need SMS enabled, the documentation explains how to do it
您需要启用 SMS, 文档说明了如何执行此操作
I must say that boto3's documentation helped me understand my options and how some things work in cognito, I definetly recommend taking a look for those of you having similar or slightly different issues.我必须说, boto3 的文档帮助我了解了我的选择以及某些事情在 cognito 中的工作原理,我绝对建议您查看那些有类似或略有不同问题的人。
You will see this MFA issue if you don't have phone_number ready.如果您没有准备好 phone_number,您将看到此 MFA 问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.