javascript - AWS Cognito 中的用户需要 MFA 时的身份验证流程

标签 javascript amazon-web-services sdk amazon-cognito multi-factor-authentication

我正在尝试将用于用户身份验证的 MFA 添加到 AWS Cognito 中用于设备管理的现有解决方案(内置于 Angular 中)。

我无法弄清楚如何从用户体验的 Angular 很好地处理这个特定的响应。它实际上感觉很 splinter ,所以如果其他人在这里遇到痛点,我会很高兴。

参见 Use Case 23.例如实现,我的如下:

authenticate(username: string, password: string): Observable<any> {

    // init cognitoUser here

    return new Observable((observer) => {
        cognitoUser.authenticateUser(authenticationDetails, {
            onSuccess: (result: any) => {},
            onFailure: (err: Error) => {},
            mfaRequired: (codeDeliveryDetails: any) => {

                // SMS has just been sent automatically 
                // and it needs to be confirmed within this scope

                // The example linked requests the code via `confirm()`
                // which is awful UX...and since this is a service
                // probably non-compliant with best practice
                // However, without this `confirm` at this point in                     
                // time, we have no confirmationCode below

                cognitoUser.sendMFACode(confirmationCode, {
                    onSuccess: (result) => {
                        observer.next(result);
                        observer.complete();
                    }, onFailure: (err: Error) => {
                        observer.error(err);
                        observer.complete();
                    }
                });
            }
        });
    });
}

预期:

  • 如果用户验证成功但未通过 MFA 添加此设备,我们可以管理重定向到适当的确认代码表单页面并手动触发 sendMFACode 函数(可能通过某种有限 session ? )

问题:

  • 我们没有 session ,所以我们无法询问用户在此登录屏幕之外自动发送的 MFA 代码...第 22 条?
  • 在登录表单中添加另一个显示/隐藏字段不起作用,因为它会多次点击 sendMfaCode 函数,导致发送多个 SMS 代码。

有没有人幸运地走出了这个流程?

最佳答案

虽然我确信非常有才华的人致力于 amazon-cognito-identity-js API,但它的设计很糟糕。这就是为什么它被贬低的原因。我个人的建议是迁移到 Amplify,这样我就不那么生气了。

借助 Amplify,您可以做到这些。

import Amplify from 'aws-amplify'
import Auth from '@aws-amplify/auth'

let mfaRequired = false

Amplify.configure({
    Auth: {
        userPoolWebClientId: '',
        userPoolId: ''
    }
})

const logUserIn = (user) => {
  // Go forth and be happy
}

// Run me on your login form's submit event
const login = async (username, password) => {
  const user = await Auth.signIn(username, password)

  if (user.challengeName === 'SMS_MFA') {
    // Change UI to show MFA Code input
    mfaRequired = true
    return
  }
  return logUserIn(user)
}

// Run me when the user submits theire MFA code
const senfMfaCode = async (mfaCode) => {
  const user = await Auth.confirmSignIn(mfaCode)
  return logUserIn(user)
}

但是,如果出于某些可悲的原因您需要继续使用 amazon-cognito-identity-js,请不要担心。我找到你了。

只需将 cognitoUser 对象存储在回调之外。该文档有点误导,因为它只显示了自包含的示例,但没有理由不能在需要 MFA 时通知您的 UI,然后稍后调用 cognitoUser.sendMFACode()

请记住,文档显示将 this 传递给 sendMFACode() 以进行范围界定(这很糟糕),但您可以将回调声明为变量并共享它在您的 authenticateUser()sendMFACode() 函数(或您喜欢的任意多个函数)之间。

import { CognitoUserPool, AuthenticationDetails, CognitoUser } from 'amazon-cognito-identity-js'

export let mfaRequired = false
export let cognitoUser = null

export const cognitoCallbacks = {
  mfaRequired () {
    // Implement you functionality to show UI for MFA form
    mfaRequired = true
  },
  onSuccess (response) {
    // Dance for joy the code gods be glorious.
  },
  onFailure () {
    // Cry.
  }
}

export const logUserIn = payload => {
  cognitoUser = new CognitoUser({
    Username: 'Matt Damon',
    Pool: new CognitoUserPool({
      UserPoolId: '',
      ClientId: ''
    })
  })
  return cognitoUser.authenticateUser(new AuthenticationDetails(payload), cognitoCallbacks)
}

export const sendMfaCode = MFACode => {
  cognitoUser.sendMFACode(MFACode, cognitoCallbacks)
}

这是一个 super 基本的实现,除此之外你还可以,

  1. 只需覆盖外部模块中的 mfaRequired 函数即可执行任何您想要的操作。
  2. 将整个内容包装在一个发布/订阅插件中并订阅事件。

希望对您有所帮助!

关于javascript - AWS Cognito 中的用户需要 MFA 时的身份验证流程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48801238/

相关文章:

javascript - 我正在尝试删除重复项并返回结果。我缺少什么?

javascript - 如何在当前日期之前获得 30 天?

amazon-web-services - CodeDeploy找不到我的AWS Lambda函数

android - 错误 : Android Source Generator: Cannot parse SDK

javascript - 如何创建一个 java 脚本库 - 从头开始​​跟踪用户在网站上的操作?

javascript - 获取编辑后的输入文本框的内容

java - 如何将动态 html 安全地嵌入到动态 javascript 文件中,以免破坏 javascript

python - AWS Lambda python 库函数错误

amazon-web-services - 可以通过 CLI/API 更改 AWS 支持计划吗?

ios - FBSDKShareLinkContent 没有设置 contentDescription 和 contentTitle