Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Handling linking accounts in Firebase

I am following Firebase's instruction on social login. Below is an example of what I am using and it is all working fine from a login authentication perspective.

I have, however, both Google and Facebook login working independently.

What I would like now to be able to do is link the accounts. You can see below in fact where this might go (see the comment):

If you are using multiple auth providers on your app you should handle linking the user's accounts here.

I have tried many variations of what I think should go here, but to no avail. Can anyone guide me in relation to what they think should go here? Thanks!

function initFBApp() {
    // Result from Redirect auth flow.
    // [START getidptoken]
    firebase.auth().getRedirectResult().then(function (result) {
        if (result.credential) {
            // This gives you a Facebook Access Token. You can use it to access the Facebook API.
            var token = result.credential.accessToken;
            // [START_EXCLUDE]
            document.getElementById('FBquickstart-oauthtoken').textContent = token;
        }
        else {
            document.getElementById('FBquickstart-oauthtoken').textContent = 'null';
            // [END_EXCLUDE]
        }
        // The signed-in user info.
        var user = result.user;
    }).catch(function (error) {
        // Handle Errors here.
        var errorCode = error.code;
        var errorMessage = error.message;
        // The email of the user's account used.
        var email = error.email;
        // The firebase.auth.AuthCredential type that was used.
        var credential = error.credential;
        // [START_EXCLUDE]
        if (errorCode === 'auth/account-exists-with-different-credential') {
            alert('You have already signed up with a different auth provider for that emails.');
            // If you are using multiple auth providers on your app you should handle linking
            // the user's accounts here.
        }
        else {
            console.error(error);
        }
        // [END_EXCLUDE]
    });
    // [END getidptoken]
    // Listening for auth state changes.
    // [START authstatelistener]
    firebase.auth().onAuthStateChanged(function (user) {
        if (user) {
            // User is signed in.
            var displayName = user.displayName;
            var email = user.email;
            var emailVerified = user.emailVerified;
            var photoURL = user.photoURL;
            var isAnonymous = user.isAnonymous;
            var uid = user.uid;
            var providerData = user.providerData;
            // [START_EXCLUDE]
            document.getElementById('FBquickstart-sign-in-status').textContent = 'Signed in';
            document.getElementById('FBquickstart-sign-in').textContent = 'Log out';
            document.getElementById('FBquickstart-account-details').textContent = JSON.stringify(user, null, '  ');
            // [END_EXCLUDE]
        }
        else {
            // User is signed out.
            // [START_EXCLUDE]
            document.getElementById('FBquickstart-sign-in-status').textContent = 'Signed out';
            document.getElementById('FBquickstart-sign-in').textContent = 'Log in with Facebook';
            document.getElementById('FBquickstart-account-details').textContent = 'null';
            document.getElementById('FBquickstart-oauthtoken').textContent = 'null';
            // [END_EXCLUDE]
        }
        // [START_EXCLUDE]
        document.getElementById('FBquickstart-sign-in').disabled = false;
        // [END_EXCLUDE]
    });
    // [END authstatelistener]
    document.getElementById('FBquickstart-sign-in').addEventListener('click', toggleFBSignIn, false);
}
like image 832
Alan Power Avatar asked Sep 12 '16 22:09

Alan Power


Video Answer


2 Answers

These are roughly the steps on how to handle auth/account-exists-with-different-credential: You will get that error if you are signing in to a new Facebook account that uses the email of another account that already exists. Let's say the existing account is a google account.

You will get that error in getRedirectResult().catch(function(error) {})

The error will also contain an email and credential field. You will need to save the credential (using the recommended sessionStorage). Check this post for more on that: Firebase Authentication Javascript: setCookie for pending Credential for redirect

You then call firebase.auth().fetchProvidersForEmail(error.email) to determine the providers that already exist for that email.

You will then sign in to one of those existing providers and assert that the email is the same as error.email. On success, you will load the pending credential from sessionStorage, re-initialize as described in the other post and link it to the currentUser:

firebase.auth().currentUser.linkWithCredential(savedCred);

You will now have both accounts linked. Keep in mind the existing provider could be a password type. In that case you don't need to save the credential, you just ask the user for the password and sign them in using the same email error.email. You can then call link directly with the error.credential.

BTW, I recommend firebaseui-web which takes care of all this for you: https://github.com/firebase/firebaseui-web

like image 143
bojeil Avatar answered Oct 22 '22 16:10

bojeil


I think the Firebase API changed a bit and firebase.auth().currentUser.link(savedCred); is now firebase.auth().currentUser.linkWithRedirect(provider). In my implementation I'm saving the initially selected provider to sessionStorage and use that with the above method in case account linking is required.

You can also do linkWithPopUp if that suits your needs better.

like image 34
Ashton Avatar answered Oct 22 '22 14:10

Ashton