如何等待aws cognito authenticateUser调用(这似乎是一个回调)

时间:2018-04-30 22:57:33

标签: reactjs callback async-await aws-amplify cognito

所以我们使用await / async调用,但是aws-amplify提供的authenticateUser命令似乎使用了回调。我是一个python编码器,并且在很长一段时间内没有用节点编码,所以这可能是一个天真的问题!

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

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';
    } 
  );

但是,无论我如何调整它,代码都会依次流动,然后我得到一个未处理的承诺拒绝(在我的测试中,auth目前失败)

3 个答案:

答案 0 :(得分:5)

尝试使用现代Javascript构造实现对authenticateUser()的调用对您有好处,但是您的方法存在一些问题。我真的很想知道完成的代码。

主要问题是Cognito authenticateUser()需要三个回调,并且Promise只处理两个。如果您从不希望碰到该代码路径,则可以为newPasswordRequired回调传递一个伪函数。另一种方法是对resolveonSuccess回调都使用newPasswordRequired函数。

第二个问题是您的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。

答案 1 :(得分:1)

这是使用asyc / 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)
  }
}




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



filter




答案 2 :(得分:0)

感谢这个问题(来自同一个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"
  }
}