Amplify 的completeNewPassword 方法针对用户数据抛出 TypeError

hip*_*r69 5 authentication amazon-web-services vue.js amazon-cognito aws-amplify

我尝试将自定义 UI 与 aws Amplify 结合使用,但遇到了 Auth.completeNewPassword 问题。任何使用此方法的尝试都会引发错误Error in v-on handler: "TypeError: Cannot read property 'username' of null

在此之前使用过给定的 UI,我知道当管理员创建 Cognito 用户时,他们会在首次登录时发送到“新密码”表单。但是,Amplify 文档中的示例一旦发现用户需要新密码,signIn 方法就会立即调用completeNewPassword 方法。

以下片段直接来自亚马逊的文档:

import { Auth } from 'aws-amplify';

Auth.signIn(username, password)
.then(user => {
    if (user.challengeName === 'NEW_PASSWORD_REQUIRED') {
        const { requiredAttributes } = user.challengeParam; // the array of required attributes, e.g ['email', 'phone_number']
        Auth.completeNewPassword(
            user,               // the Cognito User Object
            newPassword,       // the new password
            // OPTIONAL, the required attributes
            {
              email: 'xxxx@example.com',
              phone_number: '1234567890'
            }
        ).then(user => {
            // at this time the user is logged in if no MFA required
            console.log(user);
        }).catch(e => {
          console.log(e);
        });
    } else {
        // other situations
    }
}).catch(e => {
    console.log(e);
});
Run Code Online (Sandbox Code Playgroud)

我尝试用几种不同的方法来实现相同的 TypeError 结果。如果我单独调用completeNewPassword方法,将用户存储为变量并将其传入,尝试重新登录并将该用户传递给completeNewPassword等,那么每次都会出现相同的TypeError,这并不重要。

例如,以下方法将在第一次单击登录按钮时正确记录“用户”对象,但在尝试提交新密码时单击同一按钮时会在该行之前失败。

signIn () {
    Auth.signIn(this.user_name, this.password)
    .then(user => {
        if (user.challengeName === 'NEW_PASSWORD_REQUIRED') {
        console.log(user)
        const { requiredAttributes } = user.challengeParam;
        this.$parent.$parent.pageStatus.passwordSetPanel = true;
        Auth.completeNewPassword(
            user,
            this.newPassword
        )
        }
    })
},
Run Code Online (Sandbox Code Playgroud)

附加信息:

  1. 框架是Vue
  2. 能够使用给定的 UI 确认新用户的新密码
  3. “用户名”类型错误不是来自我的js,而是指用户承诺中的用户名参数(我已经检查过,并且没有尝试将 user_name 传递到它想要用户名的地方)

编辑

设法找到一个半工作的解决方案,代码如下:

signIn () {
    this.$parent.$parent.pageStatus.loginPanel = false;
    this.$parent.$parent.loading = true;
    Auth.signIn(this.user_name, this.password)
    .then(async user => {
        if (user.challengeName === 'NEW_PASSWORD_REQUIRED') {
        const loggedUser = await Auth.completeNewPassword(
            user,
            this.password,
        )
        this.$parent.$parent.pageStatus.passwordSetPanel = true
        }
    })
}
Run Code Online (Sandbox Code Playgroud)

这设法更新用户,但我必须将密码设置为 this.password (原始的、待更改的密码)才能使其正常工作。看起来问题是 Amplify 希望我使用相同的函数来登录并调用completeNewPassword。但这些的 UI 需要分为两个不同的面板。

Sha*_*ank 1

我设法使用 RxJS BehaviourSubject 解决了这个问题。

您可以在此处查看 BehaviourSubject 的典型行为示例。

声明BehaviorSubject:BehaviorSubject的初始值为null。

congitoUser = new BehaviorSubject(null);
Run Code Online (Sandbox Code Playgroud)

订阅从 Auth.SignIn(即认知用户)返回的值。

 login(user: { username: string; password: string }) {
    Auth.signIn(user)
      .then((data) => {
        this.congitoUser.next(data);
        if (user) {
          if (data.challengeName === 'NEW_PASSWORD_REQUIRED') {
            this.router.navigateByUrl('/change-password');
          } else {
            this.router.navigateByUrl('/home');
          }
        }
      });
  }
Run Code Online (Sandbox Code Playgroud)

现在订阅将返回 Cognito 用户的正确值。

updatePassword(password: string) {
// subscribe to cognito user (behaviour subject) and use the value it returned.
    this.congitoUser.subscribe((value) => {
      Auth.completeNewPassword(value, password, [])
        .then((data) => {
         console.log(data);
        })
        .catch((err) => console.error('Error', err));
    });
}
Run Code Online (Sandbox Code Playgroud)