AWS Cognito - 重置用户 MFA

Posted

技术标签:

【中文标题】AWS Cognito - 重置用户 MFA【英文标题】:AWS Cognito - reset user MFA 【发布时间】:2018-11-02 23:24:47 【问题描述】:

我有一个 Cognito 用户池,它的 MFA 设置为 Required,只有 TOTP(即没有 SMS)。

我的问题是如何为用户重置 MFA?例如,如果用户丢失了手机而无法登录怎么办。

我尝试过重设密码,但这只是重设密码,并没有删除 MFA。

在AWS documentation 的底部,上面写着

注意 API 目前不支持删除 TOTP 软件令牌操作。此功能计划在未来的版本中使用。使用 SetUserMFAPreference 为单个用户禁用 TOTP MFA。

所以我尝试了SetUserMFAPreferenceAdminSetUserMFAPreference,它们只是返回 200 OK,但实际上并没有禁用 MFA。我猜这是因为用户池的 MFA 设置为 Required

【问题讨论】:

尝试了 AdminSetUserMFAPreference,但没有成功。你能想出这个吗。我想可能需要将 Do you want to enable Multi-Factor Authentication (MFA)? 设置为 Optional 以允许个人用户选择偏好。 【参考方案1】:

此时,由于 AWS 不支持重置 MFA(如果您的用户池需要 MFA - 使用 AdminSetUserMFAPreference 禁用 MFA 将返回 200 OK 但它不会执行任何操作),唯一的方法是创建一个具有可选 MFA 的新用户池(您必须创建一个新用户池,因为一旦创建用户池,就禁止从 required 更改为 optional)。然后使用新的用户池,您必须在代码中手动强制执行 MFA(如果这是您想要的)。

为此,一旦用户成功登录并且返回对象中包含令牌,您必须调用 AssociateSoftwareToken 而不是返回令牌并开始 MFA 注册过程。只有当用户成功完成对AdminRespondToAuthChallenge的调用时,令牌(如IdToken)才会返回给用户。

底线,使用可选的 MFA,AdminSetUserMFAPreference 将起作用。这是在 AWS 上的用户池中重置 MFA 的唯一方法(此时)。

[更新]

并不是说我原来的答案无效,只是为了提供更多信息,这里有一些关于如何使用AdminSetUserMFAPreference的额外说明:

首先,您需要一个具有可选 MFA 的用户池。可选的是这里的关键字。此解决方案不适用于具有所需 MFA 的用户池。

设置用户池后,我假设有一个用户正确注册了您的用户池。这意味着他们可以根据您的用户池对自己进行身份验证,而不会出现任何问题。当然,重点是他们需要在身份验证过程中提供 MFA。但是由于我们已经建立,MFA 在您的用户池中是可选的,因此如果您坚持对您的用户强制执行 MFA,这意味着您必须在您的代码中手动执行此操作。

好的,到目前为止,每个人都很高兴。但正如现实一样,悲伤的日子来了。您的用户丢失了他们的 MFA 代码,并且无法生成任何新代码。因此,您希望为他们提供通过重新注册新设备来重置其 MFA 的可能性。当然,首先,您需要确保请求此类内容的是实际用户。我的意思是您不希望任何人(但真正的用户)能够提出这样的请求。因此,您需要先对它们进行身份验证。但他们无法进行身份验证(由于缺少 MFA)这一事实是他们最终来到这里的全部原因。那么你现在能做什么呢?好吧,尽管这部分超出了本文的范围,但作为一个小提示,您可以向他们发送一封包含代码的电子邮件,并要求他们将其作为一次性身份验证机制返回给您。

好的,回到手头的问题。现在,您可以确定请求重置 MFA 的是实际帐户所有者。这就是你的做法:

async function resetMfa(username) 
    const cognito = new AWS.CognitoIdentityServiceProvider();
    await cognito.adminSetUserMFAPreference(
            UserPoolId: "user pool ID",
            Username: username,
            SoftwareTokenMfaSettings: 
                Enabled: false,
            
        ).promise();

一旦他们的 MFA 被禁用,为了重新注册新设备,帐户所有者必须尝试重新登录。这种尝试与他们第一次登录帐户时一样,系统会要求他们注册新的 MFA 设备。

我希望这能更清楚地说明问题。如果你想知道如何(手动)使用 MFA,我有这个other post 来解决它。

【讨论】:

我按照您的指示进行操作,但 AdminSetUserMFAPreference 仍然不起作用 @JuanLuis 我不确定你做错了什么,但我会在我的答案中添加更多信息,我希望这能帮助你自己弄清楚。【参考方案2】:

我发现即使在将用户添加到用户池之后,也可以将 MFA 设置更改为“必需”。因此,您不必创建另一个用户池。

不可能从控制台更改它,但是 aws cli(可能通过 set_user_pool_mfa_config() API)可以像这样更改它:

% aws cognito-idp set-user-pool-mfa-config --user-pool-id <userpool_id> --mfa-configuration ON --software-token-mfa-configuration Enabled=true

虽然我找不到删除/更改“每个用户的 MFA (OTP)”的方法。

【讨论】:

【参考方案3】:

实际上你需要改变用户的设置,而不是偏好。

删除 MFA var cognitoidentityserviceprovider = new AWS.CognitoIdentityServiceProvider();

    var params = 
        UserPoolId: poolData.UserPoolId,
        Username: userid, /* required */
        MFAOptions: [ /* required */
        ]
    ;
    cognitoidentityserviceprovider.adminSetUserSettings(params, function(err, data) 
        if (err) reject(err);       // an error occurred
        else     resolve(data);     // successful response
    );

添加/更改 MFA:

    var cognitoidentityserviceprovider = new AWS.CognitoIdentityServiceProvider();

    var params = 
        UserPoolId: poolData.UserPoolId,
        Username: userid, /* required */
        MFAOptions: [ /* required */
            
                AttributeName: 'phone_number',
                DeliveryMedium: 'SMS'
            
        ]
    ;
    cognitoidentityserviceprovider.adminSetUserSettings(params, function(err, data) 
        if (err) reject(err);       // an error occurred
        else     resolve(data);     // successful response
    );

【讨论】:

注意:adminSetUserSettings 已被弃用。请改用 SetUserMFAPreference。 该问题明确表示他们对软件 MFA(而不是 SMS)感兴趣。而adminSetUserSettings 没有软件 MFA 的选项。【参考方案4】:

如果您是管理员,则可以使用以下 AWS CLI 命令对其进行更新:

aws cognito-idp admin-set-user-mfa-preference

欲了解更多信息,请查看the documentation。

【讨论】:

根据文档,它可以正常工作,但不确定您面临什么问题 正如 OP 所述,调用该 API 将返回 200 OK 但它什么也不做。我知道文档说它有效,但它没有。我已经在 AWS 上开过一张票。 OP首先问这个问题的原因是API不起作用。 是的,它返回 200 OK,因此 API 可以正常工作,但实际上并未在此处禁用 MFA【参考方案5】:

您可以为每个用户提供一个恢复代码,然后编写一个通过 API 端点公开的 Lambda,检查他们是否提交了正确的恢复代码。如果是这样,您可以在 Lambda 中调用以下命令来禁用用户的 MFA:

  const result = await cognito
    .adminSetUserMFAPreference(
      UserPoolId: AmplifyConfig.Auth.userPoolId,
      Username: userid,
      SoftwareTokenMfaSettings: 
        Enabled: false,
        PreferredMfa: false,
      ,
    )
    .promise();

在检查这些恢复代码时,请务必使用crypto.timingSafeEqual 之类的东西来防御定时攻击。

【讨论】:

您如何实际向用户发送恢复代码。您必须手动执行此操作吗? 这个想法是正确的,但adminSetUserMFAPreference 不会为用户重置 MFA。 @Mehran 在撰写本文时确实重置了 MFA。也许您可以使用正确的函数编辑答案? 没有正确的功能。如果用户池是使用所需的 MFA 创建的,则无法重置 MFA(至少在撰写本文时 - 可能在未来 AWS 会修复此问题)。而且我敢肯定,即使在编写答案时,您也无法重置 MFA,因为 OP 说他们有同样的问题,并且必须在您编写答案之前进行测试。我不知道你的测试用例是什么,但只要你的用户池需要 MFA,你的函数调用就应该默默地失败(它没有说它失败了)。我已经提供了一个解决方案作为答案。你可以参考一下,看看我是怎么做到的。

以上是关于AWS Cognito - 重置用户 MFA的主要内容,如果未能解决你的问题,请参考以下文章

我们将如何发送不同的电子邮件模板以重置密码并确认在 AWS cognito 中注册

Cognito - 导入用户后未发送电子邮件

在 AWS Cognito 中回答 NEW_PASSWORD_REQUIRED 质询后继续使用自定义身份验证流程

text [使用CLI注册Cognito用户] #aws #cognito#aws-cli

在 AWS Cognito 中管理用户

AWS Cognito:Cognito 用户池的元数据 URL 在哪里?