通过 link 进行 Cognito 无密码身份验证

Cognito paswordless auth via link

我正在尝试通过 link 实现无密码身份验证。例如。用户输入他的电子邮件 -> cognito 发送一封带有 link 的电子邮件,用户可以单击并登录。它

Cognito 通过自定义挑战支持它。例如。 https://aws-amplify.github.io/amplify-js/media/authentication_guide#using-a-custom-challenge

我已经创建了 DefineAuthChallengeCreateAuthChallengeVerifyAuthChallenge 与我的认知池关联的 lambda 函数。 CreateAuthChallenge 生成发送到用户电子邮件的代码 link 到站点。

接下来我打算从 url 网站上获取该代码并通过它登录用户,就像它在文档中一样

Auth.signIn(username)
    .then(user => {
        if (user.challengeName === 'CUSTOM_CHALLENGE') {
            Auth.sendCustomChallengeAnswer(user, challengeResponse)
                .then(user => console.log(user))
                .catch(err => console.log(err));
        } else {
            console.log(user);
        }
    })
    .catch(err => console.log(err));

但问题来了。 Auth.sendCustomChallengeAnswer 需要从 Auth.signIn 传递的用户对象。但是,如果用户只是从电子邮件中单击 link,则根本不会有任何用户对象。并且放大 lib 不保存那个中间会话用户对象,所以在页面上重新加载它丢失了。它仅在完成存储的身份验证后才保存 https://github.com/aws-amplify/amplify-js/blob/master/packages/amazon-cognito-identity-js/src/CognitoUser.js#L175

所以问题是如何在页面重新加载时从 Auth.signIn 函数保存和重建用户对象。或者是否有更好的方法通过 link 免密码登录?

首先要解决这个问题,您需要将用户名和会话保存到本地存储或 cookie 中。然后当用户通过 link 时可以使用此代码:

 const userPoolData = {
    UserPoolId: process.env.COGNITO_POOL_ID,
    ClientId: process.env.COGNITO_POOL_WEB_CLIENT_ID,
    Storage: customStorageClass // default is localstorage
  }

  const userPool = new CognitoUserPool(userPoolData)

  const userData = {
    Username: getUsernameFromCookiesOrLocalstorage,
    Pool: userPool,
    Storage: customStorageClass // default is localstorage
  }
  const user = new CognitoUser(userData)
  user.Session = getSessionFromCookiesOrLocalstorage
  Auth.sendCustomChallengeAnswer(user, code)