Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AWS Cognito AdminLinkProviderForUser - User Pool Account and Facebook

Our setup is:

  • Email/Password account creation or Facebook Sign In

I am able to create both successfully independent of each other with AWS Cognito.

The problem I want to solve is if a user has an Email/Password account first, and clicks Facebook Sign In, I want them to link and prompt the user to confirm they had access to the Email/Password account.

Once the user confirms that going forward, they should be able to either Facebook Sign In or Email/Password login to access and adjust the same account.

Facebook User in Cognito User Pool: - Facebook User in Cognito User Pool

Email/Password User Linked in Cognito User Pool to Facebook User: Email/Password User Linked in Cognito User Pool to Facebook User

I'm currently using the Pre Sign Up Trigger to Auto Verify Email, Confirm, and Link Account. For Social (Facebook), I'm using:

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

POST amazoncognito.com/oauth2/token

This works but I authenticate as the Facebook_user and my expectation (and want) is to authenticate as the link user at that point. I feel like I'm missing something obvious.

like image 581
Dan Avatar asked Nov 12 '19 03:11

Dan


People also ask

What is the main difference between Cognito user pool and Cognito identity pool?

With a user pool, your app users can sign in through the user pool or federate through a third-party identity provider (IdP). Identity pools are for authorization (access control). You can use identity pools to create unique identities for users and give them access to other AWS services.

Which public identity providers can I use with Amazon Cognito identity?

Q: When using public identity providers, does Amazon Cognito Identity store users' credentials? No, your app communicates directly with the supported public identity provider (Amazon, Facebook, Twitter, Google, or an Open ID Connect-compliant provider) to authenticate users.

What is the function of Amazon Cognito user pools?

A user pool is a user directory in Amazon Cognito. With a user pool, your users can sign in to your web or mobile app through Amazon Cognito. Your users can also sign in through social identity providers like Google, Facebook, Amazon, or Apple, and through SAML identity providers.


1 Answers

Ultimately, the answer was I was not removing Facebook_ from the userid. So I was in theory linking my Cognito Email / Password to 'Facebook_USERID' not 'USERID.'

Once I made that change, I was able to authenticate as 1 account linked.

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

Update - 4/24/2020

We added a Native Account for anyone who signs up, so that we don't run into the problem. They just have to activate/reset their password if they try to sign in via Native. The below script is in our Pre-Sign Up Trigger Lambda Function:

  {
    // 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);
          }
        }
      });
    }
  }

If helpful here is the whole lambda code: https://pastebin.com/4cyF9Nkw

like image 154
Dan Avatar answered Sep 27 '22 22:09

Dan