aws-amplify / amplify-js

A declarative JavaScript library for application development using cloud services.
https://docs.amplify.aws/lib/q/platform/js
Apache License 2.0
9.4k stars 2.11k forks source link

How to implement "Delete Facebook!" #6300

Open jonsmirl opened 4 years ago

jonsmirl commented 4 years ago

For various reasons some of our users want to delete their Facebook accounts. Our app has nothing to do with Facebook, except for "Login with Facebook". And that's a problem since when these users delete their Facebook accounts they also lose the ability to login into our app. I'm exploring solutions to address this without needing manual intervention to restore account access.

The fundamental problem with Amplify is that the user entries it creates in either User Pool or Identity Pool are not linked to multiple login options. Each user entry created by Amplify in User Pool or Identity Pool is only associated with a single login method and if that method is Facebook and the Facebook account is deleted, then access to that UserID is lost.

So how to fix this issue? My first observation is that every user should have an AWS-type user entry in the User Pool, not a linked federated user. This is required so that if the Federated account is deleted then there will still be a way to log into the AWS account. I see no need for Federated user entries in User Pool. Instead social logins should be linked to an AWS-type user via Identity Pool.

I'm unclear on how to implement this next step, but I'm fairly sure Cognito already supports it. If a new user picks "Login with Facebook" the first thing that has to happen is to create an AWS-type user in the user pool. Then this new AWS-user has to create an entry in the identity pool. Then... you use the token from Facebook to authorize against the identity pool while including the identityId of the AWS-user in the call. That will result in a linked Indentity Pool entry with two ways to login -- AWS and Facebook.

Some Amplify UI is needed to implement this. After a user clicks on "Login with Facebook" first you need to detect if the user is a new user. For a new user create the AWS-type entry in User Pool and have the human provide an account name. The account name is how they recover access to their account so this needs to come up in the UI. The account name and email should have defaulted values based on the social login. Click an "ok" button to validate that the user name is available, and include a warning if the email address is from the federated site. No need to set the password now, it can be set later via the recover password option. After clicking 'ok' the Identity Pool entry should get created. That pool entry can then be linked to the social login.

An example of a website that works this way is [pixabay.] (https://pixabay.com/) Check out the user profile page. Note that there are are buttons to unlink your federated logins.

One way to implement this might be with a public lambda function. That lambda would take the authentication 'code' not the 'token' from the social login and exchange it for the 'token' using the client secret (more secure than the Oauth implicit flow). This lambda would then need to check for the existence of the social login in the identity pool, if it is not there then trigger the new account sequence which will build the user pool entry and then link it to the social login.

Would a flow like this work? 1) App gets code from social provider 2) Send code to public lambda. 2a) exchange code for token 2b) check for existence of login in identity pool. 2c) return status of that check and the long lived token 3) if the login exists in the identity pool then login via pool with the token. done. 4) use name and email from token to create AWS-type user pool entry 5) validate that the entry can be created. 6) use that entry to create an identify pool entry. can this be done without logging in? 7) login into identity pool using identityId from previous line and token to created linked entry. done.

This also solves another problem we encountered -- how to turn an ordinary federated user into an admin user. We can go into the user pool and set the AWS-type user to have an admin role. Now if this person logs in using a federated id they will login with normal user role. If instead they login with their AWS-type credential they will gain admin role..

cwomack commented 1 year ago

Related to #5104 and #3431

abdallahshaban557 commented 1 year ago

Cognito has recently resolved an issue with linking federated users to an existing user profile in Cognito User Pools. As a result, your Amplify application can now merge user identities from 3rd party social identity providers to a Cognito user in a user pool using the Pre sign-up Lambda trigger. You can use the AdminLinkProviderForUser API from Cognito to set up custom logic to determine how your user identities get merged. To learn more about the use of this feature, you can check out the following documentation pages.

We will work on resources to share with you to explain how to integrate this feature into your Amplify app.