0

背景:

我有一个 React Web 应用程序(正在使用aws-amplify),它连接到/使用 AWS Cognito 用户池进行身份验证。

我正在尝试启用 MFA,更具体地说,我希望我的用户可以选择使用软件令牌 TOTP MFA(即 Google Authenticator 或类似应用程序)。

当我将我的用户池设置为需要 MFA 时,我被迫启用 SMS MFA,然后软件 TOTP 是可选的。就我而言,我启用了 TOTP。

在我的网络应用程序中,我通过以下方式添加了必要的组件:

import { SelectMFAType } from 'aws-amplify-react';

# other code

<SelectMFAType authData={user} MFATypes={{ SMS: true, TOTP: true }} />

# other code

如果您不熟悉aws-amplify-reactand/or SelectMFAType,此组件提供了一个 UI 元素,用户可以在其中选择是否喜欢使用 SMS 或软件 TOTP 作为其 MFA 方法。如果他们选择 SMS,则使用他们之前验证的电话号码,一切正常。

如果用户选择 TOTP,他们会在他们选择的身份验证器应用程序中显示一个 QR 码以进行扫描,并提示他们输入字段以输入来自身份验证器应用程序的 6 位数字以验证 TOTP。对于在任何其他网站上使用 TOTP MFA 选项的任何人来说,这都是非常标准的。如果用户从应用程序输入正确的代码,他们的 TOTP 选择就会得到验证。

简而言之SelectMFAType,它只是快速原型和测试的捷径/替身,无需创建自定义组件。

问题:

现在,这是问题以及如何重现它。(起点是刚刚启用 TOTP 的用户。):

  1. 用户注销。
  2. 用户登录。
  3. 如果用户名/密码正确,则提示用户输入 TOTP。
  4. 如果 TOTP 正确,则用户已登录。到目前为止,这一切正常,但不会一直如此。
  5. 用户注销。
  6. 用户登录。
  7. 如果用户名/密码正确,系统将提示用户输入 SMS MFA,并将收到一条带有 6 位代码的短信。这是意外的行为。我希望它会继续从他们的身份验证器应用程序请求 TOTP MFA,除非用户将他们的首选方法更改回 SMS。
  8. 从现在开始,用户将只会被要求 SMS MFA。

在步骤 4 和步骤 7 之间,用户的偏好没有改变。React 应用程序或 AWS 用户池设置中绝对没有任何变化。

此外,如果我通过 AWS CLI 命令询问用户 aws cognito-idp admin-get-user --user-pool-id ${MY_ID} --username ${MY_USER_NAME},我可以确认用户的 MFA 首选项正是我所期望的:

{
    <other irrelevant keys redacted>
    "PreferredMfaSetting": "SOFTWARE_TOKEN_MFA",
    "UserMFASettingList": [
        "SMS_MFA",
        "SOFTWARE_TOKEN_MFA"
    ]
}

MFA 质询是用户尝试进行身份验证时来自 AWS Cognito 的 API 响应,它是SMS_MFASOFTWARE_TOKEN_MFA。就我而言,我得到了一个SOFTWARE_TOKEN_MFA挑战,但随后所有未来的挑战都会违背我的意愿恢复为SMS_MFA.

如果我重复 TOTP 设置过程(从验证器应用程序中删除条目,重新验证等),我可以再次重复所有步骤。我的意思是,MFA 会期待一次 TOTP,然后在第一次之后再次恢复到 SMS。

任何人都可以阐明这种情况吗?你经历过吗?它是 AWS Cognito 中的已知问题/错误吗?难道我做错了什么?我觉得如果这个坏了,会产生相当大的噪音,但我找不到其他人有同样的问题。

我尝试过的事情:

  • 在这里、谷歌和 AWS 论坛广泛搜索有相同问题的其他人。
  • 我已经在 AWS 论坛上发帖,但没有任何结果: https ://forums.aws.amazon.com/thread.jspa?threadID=324131
  • 在. SelectMFAType_ aws-amplify-react我将把这个自定义组件粘贴到这个问题的底部作为参考。
  • 完全销毁并重新创建了 AWS Cognito 用户池。我认为它可能已损坏或无法正常工作。这没什么区别。

SetupTOTP.js零件:

import React, { useContext, useEffect, useState } from 'react';
import {
  Button,
  Dialog,
  DialogActions,
  DialogContent,
  DialogContextText,
  DialogTitle,
  TextField,
} from '@material-ui/core';
import { Auth } from 'aws-amplify';
import { ToastsStore } from 'react-toasts';
import QRCode from 'qrcode.react';

import { AuthStateContext } from 'Context/auth-context';

const SetupTOTP = React.memo(props => {
  const { open, handleClose } = props;
  const { username } = useContext(AuthStateContext);
  const [user, setUser] = useState(null);
  const [qrCode, setQrCode] = useState('');
  const [token, setToken] = useState('');

  const handleSave = () => {
    Auth.verifyTotpToken(user, token)
      .then(() => {
        Auth.setPreferredMFA(user, 'TOTP').then(() => {
          ToastsStore.success('Token Verified Updated');
          handleClose();
        });
      })
      .catch(err => {
        console.log(err);
        ToastsStore.error(err.message);
      });
  };

  useEffect(() => {
    Auth.currentAuthenticatedUser().then(user => {
      setUser(user);
    });
  }, []);

  useEffect(() => {
    if (username && user) {
      Auth.setupTOTP(user).then(code => {
        setQrCode(
          `otpauth://totp/AWSCognito:${username}?secret=${code}&issuer=REDACTED`
        );
      });
    }
  }, [username, user]);

  return (
    <Dialog
      open={open}
      onClose={handleClose}
      aria-labelledby="form-dialog-title"
    >
      <DialogTitle id="form-dialog-title">Change Password</DialogTitle>
      <DialogContent>
        <QRCode value={qrCode} />

        <TextField
          margin="dense"
          id="name"
          label="Verify Token"
          type="text"
          fullWidth
          onChange={e => setToken(e.target.value)}
        />
      </DialogContent>
      <DialogActions>
        <Button onClick={handleClose} color="primary">
          Cancel
        </Button>
        <Button onClick={handleSave} color="primary">
          Save
        </Button>
      </DialogActions>
    </Dialog>
  );
});

export default SetupTOTP;
4

1 回答 1

0

我相信这是 Cognito 中的一个错误。请参阅此放大问题

于 2020-08-25T23:00:18.557 回答