首页 > 解决方案 > 如何将 AWS Cognito 本机用户链接到联合用户

问题描述

目前Cognito 允许将联合用户(从外部身份提供者登录的用户,如Google)合并到本地用户(通过用户名和密码组合注册的用户)。

有没有办法将现有的联合用户与新的本地用户合并?

标签: amazon-cognitofederated-identity

解决方案


不可以。您只能从从未登录的用户创建链接。也就是说,您只能在创建新用户时(在预授权触发器中)链接新用户。

“这允许您创建从现有用户帐户到尚未用于登录的外部联合用户身份的链接”。

就我个人而言,我在预注册触发器中发现了这种情况,并使用自定义消息拒绝了注册(“此电子邮件地址已存在帐户,请使用 Google 登录”)。

这是我的预注册 lambda,以防你觉得它有用

const AWS = require("aws-sdk");
const cognito = new AWS.CognitoIdentityServiceProvider();

exports.handler = (event, context, callback) => {

  function checkForExistingUsers(event, linkToExistingUser) {

    console.log("Executing checkForExistingUsers");

    var params = {
      UserPoolId: event.userPoolId,
      AttributesToGet: ['sub', 'email'],
      Filter: "email = \"" + event.request.userAttributes.email + "\""
    };

    return new Promise((resolve, reject) =>
      cognito.listUsers(params, (err, result) => {
        if (err) {
          reject(err);
          return;
        }
        if (result && result.Users && result.Users[0] && result.Users[0].Username && linkToExistingUser) {
          console.log("Found existing users: ", result.Users);
          if (result.Users.length > 1){
            result.Users.sort((a, b) => (a.UserCreateDate > b.UserCreateDate) ? 1 : -1);
            console.log("Found more than one existing users. Ordered by createdDate: ", result.Users);
          }
          linkUser(result.Users[0].Username, event).then(result => {
              resolve(result);
            })
            .catch(error => {
              reject(err);
              return;
            });
        } else {
          resolve(result);
        }

      })
    );

  }

  function linkUser(sub, event) {
    console.log("Linking user accounts with target sub: " + sub + "and event: ", event);

    //By default, assume the existing account is a Cognito username/password
    var destinationProvider = "Cognito";
    var destinationSub = sub;
    //If the existing user is in fact an external user (Xero etc), override the the provider
    if (sub.includes("_")) {
      destinationProvider = sub.split("_")[0];
      destinationSub = sub.split("_")[1];
    }
    var params = {
      DestinationUser: {
        ProviderAttributeValue: destinationSub,
        ProviderName: destinationProvider
      },
      SourceUser: {
        ProviderAttributeName: 'Cognito_Subject',
        ProviderAttributeValue: event.userName.split("_")[1],
        ProviderName: event.userName.split("_")[0]
      },
      UserPoolId: event.userPoolId
    };
    console.log("Parameters for adminLinkProviderForUser: ", params);
    return new Promise((resolve, reject) =>
      cognito.adminLinkProviderForUser(params, (err, result) => {
        if (err) {
          console.log("Error encountered whilst linking users: ", err);
          reject(err);
          return;
        }
        console.log("Successfully linked users.");
        resolve(result);
      })
    );
  }

  console.log(JSON.stringify(event));

  if (event.triggerSource == "PreSignUp_SignUp" || event.triggerSource == "PreSignUp_AdminCreateUser") {

    checkForExistingUsers(event, false).then(result => {
        if (result != null && result.Users != null && result.Users[0] != null) {
          console.log("Found at least one existing account with that email address: ", result);
          console.log("Rejecting sign-up");
          //prevent sign-up
          callback("An external provider account alreadys exists for that email address", null);
        } else {
          //proceed with sign-up
          callback(null, event);
        }
      })
      .catch(error => {
        console.log("Error checking for existing users: ", error);
        //proceed with sign-up
        callback(null, event);
      });

  }

  if (event.triggerSource == "PreSignUp_ExternalProvider") {

    checkForExistingUsers(event, true).then(result => {
        console.log("Completed looking up users and linking them: ", result);
        callback(null, event);
      })
      .catch(error => {
        console.log("Error checking for existing users: ", error);
        //proceed with sign-up
        callback(null, event);
      });

  }

};

推荐阅读