AWS Cognito管理员链接提供程序用于用户 - 用户池账户和Facebook

7

我们的设置如下:

  • 使用电子邮件/密码创建账户或使用Facebook登录

我能够通过AWS Cognito独立成功地创建这两种类型的账户。

我想要解决的问题是,如果一个用户首先拥有一个电子邮件/密码账户,然后点击了Facebook登录,我希望他们可以链接这两个账户,并提示用户确认他们能够访问电子邮件/密码账户。

一旦用户确认,他们应该能够使用Facebook登录或者电子邮件/密码登录来访问和调整同一个账户。

Cognito用户池中的Facebook用户: - Cognito用户池中的Facebook用户

Cognito用户池中链接到Facebook用户的电子邮件/密码用户: Cognito用户池中链接到Facebook用户的电子邮件/密码用户

我目前正在使用Pre Sign Up触发器来自动验证电子邮件、确认并链接账户。对于社交(Facebook),我正在使用:

GET amazoncognito.com/oauth2/authorize?identity_provider=Facebook&response_type=code then

POST amazoncognito.com/oauth2/token

这个代码可以工作,但我认证的是Facebook_user而我的期望(和想要的)是在那一点上作为链接用户进行认证。我觉得我缺少了一些显而易见的东西。
1个回答

19

最终答案是我没有从用户ID中删除Facebook_。因此,在理论上,我将我的Cognito电子邮件/密码链接到'Facebook_USERID'而不是'USERID'。

一旦我进行了更改,我就能够作为一个链接帐户进行身份验证。

// Get Email
        var params = {
          UserPoolId: 'YOUR_USER_POOL',
          AttributesToGet: ['sub','email'],
          Filter: "email = \"" + event.request.userAttributes.email + "\""
        }
        cognito.listUsers(params, (err, data) => {
            if (err) {
                console.log(err, err.stack);
            }
            else {
                console.log(data);
                console.log(event.userName);
                if(data != null && data.Users != null && data.Users[0] != null)
                {
                  console.log(data.Users[0].Username);
                  var params = {
                    DestinationUser: { 
                      ProviderAttributeValue: data.Users[0].Username,
                      ProviderName: 'Cognito'
                    },
                    SourceUser: { 
                      ProviderAttributeName: 'Cognito_Subject',
                      ProviderAttributeValue: event.userName.split("_")[1],
                      ProviderName: 'Facebook'
                    },
                    UserPoolId: 'YOUR_USER_POOL'
                  };
                  cognito.adminLinkProviderForUser(params, function(err, data) {
                    if (err) console.log(err, err.stack); // an error occurred
                    else     console.log(data);           // successful response
                  });
                }
            }
        });

更新 - 2020年4月24日

我们为任何注册的用户添加了一个本地账户,以免遇到问题。他们只需要在尝试通过原生方式登录时激活/重置密码即可。以下脚本位于我们的 Pre-Sign Up 触发器 Lambda 函数中:

  {
    // ExternalProvider (ie. Social)
    if (event.request.userAttributes.hasOwnProperty("email")) {
      // Create Native User Always
      var params = {
        ClientId: backendClientIds[event.userPoolId],
        Password: generatePassword(),
        Username: event.request.userAttributes.email
      };
      cognito.signUp(params, function(err, data) {
        if (err) { 
          console.log('cognito.signUp:');
          console.log(err, err.stack); 
          if(err.code === 'UsernameExistsException')
          {
            // Get and Link Existing User
            getUsersAndLink(event.userPoolId, event.request.userAttributes.email, event);
          }
        }
        else {
          console.log('cognito.signUp:');
          console.log(data);
          if(data.UserConfirmed)
          {
            // Link Newly Created User
            linkUser(data.UserSub, event);
          }
        }
      });
    }
  }

如果有帮助的话,这里是完整的Lambda代码:https://pastebin.com/4cyF9Nkw


1
你是如何处理相反的情况的?一个用户首先使用 Facebook 登录,然后同一个用户使用相同的电子邮件创建了一个电子邮件/密码账户。 - Jun
3
我们使用Lambda函数来自动创建本地账户,这样当您通过Facebook注册/登录时,您始终拥有“两个”帐户:一个是本地帐户,另一个是社交账户。Lambda函数位于Pre-Sign Up Trigger中。请参见上面主贴中的代码。 - Dan
1
我并不直接使用signUp事件的返回值。我们正在使用.NET SDK,所以当Cognito触发器触发时,我们已经超越了那一点了。 - Dan
3
代码:https://pastebin.com/4cyF9Nkw我移除了两个区域:(1)我们用户池/后端客户端ID中的值(2)我们生成密码的代码,享受吧! @KevinWang,当然没问题,伙计! - Dan
2
嗨@Dan,你有没有遇到“用户名已存在”的情况?使用你用过的策略时,我在第一次用户登录时就遇到了这个错误。 - gwdp
显示剩余9条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接