4

所以我们正在使用等待/异步调用,但 aws-amplify 提供的 authenticateUser 命令似乎使用了回调。我是一个 python 编码器,很长一段时间没有用 node 编码,所以这可能是一个幼稚的问题!

我尝试将其转换为这样的承诺:

function authenticateUserAsync(user, authDetails) {
    return new Promise(function(resolve, reject, challenge) {
          user.authenticateUser(authDetails, { 
                          onSuccess: resolve,
                          onFailure: reject, 
                          newPasswordRequired: challenge });

    }).then(
        function(result) { 
           return result; 
        });
}

然后

 idToken = await authenticateUserAsync(user, authDetails,
    function(result) {
        console.log("Token: ");
        console.log(result.idToken);
        return result.idToken;
    },
    function(err) {
        console.log(err);
        this.setState({idToken: ''});
        if (err.code == 'NotAuthorizedException') {
                return 'not_authorized';
        } else {
                return 'unknown_error';
        }

    },
    function(userAttrs, reqAttrs) {
        return 'challenge';
    } 
  );

但是,无论我如何调整它,代码都会继续运行,然后我得到一个未处理的承诺拒绝(在我的测试中,身份验证目前失败)

4

3 回答 3

8

您尝试authenticateUser()使用现代 Javascript 结构实现调用,这对您很好,但是您的方法存在几个问题。我真的很想看到完成的代码。

主要问题是 CognitoauthenticateUser()需要三个回调,而 Promise 只处理两个。newPasswordRequired如果您从不希望访问该代码路径,则可以为回调传递一个虚拟函数。另一种方法是将resolve函数用于回调onSuccessnewPasswordRequired回调。

第二个问题是您authenticateUserAsync()只需要两个参数。您正在尝试向它传递一些额外的回调。这些回调被忽略。就是为什么它会继续运行并且你会得到一个未处理的 promise 异常。不必要的.then()也无济于事。

我的实现最终是这样的:

function asyncAuthenticateUser(cognitoUser, cognitoAuthenticationDetails) {
  return new Promise(function(resolve, reject) {
    cognitoUser.authenticateUser(cognitoAuthenticationDetails, {
      onSuccess: resolve,
      onFailure: reject,
      newPasswordRequired: resolve
    })
  })
}

async signIn({ commit }, authData) {
  let cognitoUserPool = new CognitoUserPool(config.poolDetails)
  let cognitoAuthenticationDetails = new AuthenticationDetails(authData);
  let userData = { Username: authData.Username, Pool: cognitoUserPool }
  let cognitoUser = new CognitoUser(userData)

  try {
    let result =
      await asyncAuthenticateUser(cognitoUser, cognitoAuthenticationDetails)

    if ('idToken' in result) {
      console.log('We have a token:  ' + JSON.stringify(p));
    }
    else {
      console.log('We need a new password.')
      delete result.email_verified // Not accepted by the challenge call
      delete result.phone_number_verified // Also not accepted

      // Get a new password from the user then call
      // cognitoUser.completeNewPasswordChallenge()
    }
    catch (error) {
      // Probably a mis-typed password
      console.log(error.message)
    }
}

amazon-cognito-identity-js欢迎使用通用 ES6 概念(如 async/await)的替代库。

于 2020-04-22T23:13:34.503 回答
1

这是使用 asyc/await 的正确方法,不能await单独使用关键字,它应该async在函数签名中带有关键字的函数内部

const fetchData = async () => {
  try{
  const res = await fetch('https://jsonplaceholder.typicode.com/posts/1')
  const data = await res.json()
   console.log(data)
  }catch(err){
     console.log('error from fetch : ',err)
  }
}

fetchData()

我认为在你的例子中你可以做这样的事情

const getIdToken = async () => {
  try{
  idToken = await authenticateUserAsync(user, authDetails,
    function(result) {
        console.log("Token: ");
        console.log(result.idToken);
        return result.idToken;
    },
    function(err) {
        console.log(err);
        this.setState({idToken: ''});
        if (err.code == 'NotAuthorizedException') {
                return 'not_authorized';
        } else {
                return 'unknown_error';
        }

    },
    function(userAttrs, reqAttrs) {
        return 'challenge';
    } 
  );
  return idToken;
  }catch(err){
     console.log('error from fetch : ',err)
  }
}

于 2018-04-30T23:02:25.290 回答
1

感谢这个问题(来自一位 Python 开发人员,对最近的节点模式有一些追赶)。基于这个 SO 和其他一些 OSS 源,以下似乎工作,给定一个合适的配置文件(见下文)。这是一个 nodejs 模块(解决方案在浏览器中会略有不同)。

/* jshint esversion: 8 */
/* jshint node: true */

// The amazon-cognito-identity-js package assumes fetch is available in a web browser.  Since
// nodejs does not have fetch built-in it is emulated like this:
global.fetch = require("node-fetch");
const AmazonCognitoIdentity = require("amazon-cognito-identity-js");

function asyncCognitoAuthentication(cognitoConfig) {
  const cognitoUserPool = new AmazonCognitoIdentity.CognitoUserPool({
    UserPoolId: cognitoConfig.userPoolId,
    ClientId: cognitoConfig.clientId,
  });
  const cognitoUser = new AmazonCognitoIdentity.CognitoUser({
    Username: cognitoConfig.username,
    Pool: cognitoUserPool,
  });
  const authenticationDetails = new AmazonCognitoIdentity.AuthenticationDetails(
    {
      Username: cognitoConfig.username,
      Password: cognitoConfig.password,
    }
  );

  return new Promise(function (resolve, reject) {
    cognitoUser.authenticateUser(authenticationDetails, {
      onSuccess: resolve,
      onFailure: reject,
      newPasswordRequired: resolve,
    });
  });
}

const cognitoJWT = {
  session: undefined,
  jwtAccess: undefined,
  jwtId: undefined,
  jwtRefresh: undefined,
  jwtPayloads: undefined,
};

module.exports.getCognitoJWT = async function (cognitoConfig) {
  try {
    const session = await asyncCognitoAuthentication(cognitoConfig);
    cognitoJWT.session = session;
    cognitoJWT.jwtAccess = session.getAccessToken().getJwtToken();
    cognitoJWT.jwtId = session.getIdToken().getJwtToken();
    cognitoJWT.jwtRefresh = session.getRefreshToken().getToken();
    cognitoJWT.jwtPayloads = {
      jwtAccess: session.getAccessToken().decodePayload(),
      jwtId: session.getIdToken().decodePayload(),
    };
    return cognitoJWT;
  } catch (error) {
    console.log(error.message);
  }
};

const process = require("process");
if (process.env.TEST_AUTH === "test") {
  const config = require("config");
  const cognitoConfig = config.get("cognito");
  console.log(cognitoConfig);

  Promise.resolve(module.exports.getCognitoJWT(cognitoConfig)).then(
    (cognitoJWT) => {
      console.log(cognitoJWT);
    }
  );
}

config文件位于 中./config/default.json,其结构如下(将实际值替换为{}字段):

{
    "logLevel": "info",
    "cognito": {
        "clientId": "{client-app-id}",
        "userPoolId": "{aws-coginto-pool-id}",
        "region": "{aws-region}",
        "username": "{your-username}",
        "password": "{your-password}"
    }
}

package.json就像:

{
  "scripts": {
    "test-cognito-auth": "TEST_AUTH=test node ./cognito_auth.js"
  },
  "license": "Apache 2.0",
  "dependencies": {
    "amazon-cognito-identity-js": "^4.3.0",
    "aws-sdk": "^2.686.0",
    "config": "^3.3.1",
    "node-fetch": "^2.6.0",
    "process": "^0.11.10",
  },
  "devDependencies": {
    "prettier": "^2.0.5"
  }
}
于 2020-07-14T22:20:43.387 回答