处理Firebase中的关联帐户

问题描述 投票:4回答:4

我正在关注Firebase关于社交登录的说明。下面是我正在使用的一个示例,它从登录身份验证的角度来看都很好。

但是,Google和Facebook登录都是独立工作的。

我现在想要做的是链接帐户。你可以在下面看到这可能会发生的事情(见评论):

如果您在应用程序上使用多个身份验证提供程序,则应在此处理用户帐户的链接。

我尝试了很多我认为应该去的地方,但无济于事。谁能引导我关于他们认为应该去哪里?谢谢!

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);
}
javascript firebase facebook-login firebase-authentication social
4个回答
3
投票

这些大致是关于如何处理auth / account-exists-with-different-credential的步骤:如果您登录到使用已存在的另一个帐户的电子邮件的新Facebook帐户,您将收到该错误。假设现有帐户是Google帐户。

您将在getRedirectResult().catch(function(error) {})中收到该错误

该错误还将包含电子邮件和凭据字段。您需要保存凭证(使用推荐的sessionStorage)。查看这篇文章了解更多信息:Firebase Authentication Javascript: setCookie for pending Credential for redirect

然后,您可以调用firebase.auth().fetchProvidersForEmail(error.email)来确定该电子邮件已存在的提供程序。

然后,您将登录其中一个现有提供程序,并声明该电子邮件与error.email相同。成功后,您将从sessionStorage加载待定凭证,按照其他帖子中的描述重新初始化并将其链接到currentUser:

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

您现在将两个帐户关联起来。请记住,现有提供程序可以是密码类型。在这种情况下,您不需要保存凭据,只需要询问用户密码并使用相同的电子邮件error.email对其进行签名。然后,您可以直接使用error.credential调用链接。

顺便说一句,我推荐firebaseui-web为您解决所有这些问题:https://github.com/firebase/firebaseui-web


1
投票

我认为Firebase API changed a bitfirebase.auth().currentUser.link(savedCred);现在是firebase.auth().currentUser.linkWithRedirect(provider)。在我的实现中,我将最初选择的提供程序保存到sessionStorage,并在需要帐户链接的情况下使用上述方法。

如果更适合您的需求,您也可以做linkWithPopUp


1
投票

仔细阅读示例https://firebase.google.com/docs/auth/web/google-signin部分“处理帐户存在与不同凭据错误”

重定向模式此错误在重定向模式下以类似的方式处理,不同之处在于必须在页面重定向之间缓存挂起的凭据(例如,使用会话存储)。


0
投票

下面是相关的工作代码片段(它位于异步函数中)。请注意,“apples”只是表示购物车的Firestore中的简化测试记录。

if(error.code === "auth/email-already-in-use"){
    // REMEMBER AUTH CURRENT USER OBJECT
    previousUser = firebase.auth().currentUser;
    // WE MUST HANDLE DB READ AND DELETE WHILE SIGNED IN AS PREVIOUS USER PER FIRESTORE SECURITY RULES
    if(localUserDoc){ //this was saved from .snapshot firing
        if(localUserDoc.data().apples){
            apples = localUserDoc.data().apples;
        }                    
    }
    //DELETE CURRENT USER RECORD WHILE STILL SIGNED IN
    await firebase.firestore().collection("users").doc(previousUser.uid).delete();
    // CLEAN UP DONE. NOW SIGN IN USING EMAIL LINK CREDENTIAL
    try {
        var firebaseUserObj = await firebase.auth().signInAndRetrieveDataWithCredential(credential);
        // FIRESTORE USER RECORD FOR EMAIL LINK USER WAS CREATED WHEN THEY ADDED APPLE TO CART
        try {
            var doc = await firebase.firestore().collection("users").doc(firebaseUserObj.user.uid).get();
            if (doc.exists) {
                if(doc.data().apples){
                    apples = apples + doc.data().apples;
                }
            }
            await firebase.firestore().collection("users").doc(firebaseUserObj.user.uid).update({
                apples: apples
            });
        } catch(error) {
            console.log("Error getting document:", error);
        }
        previousUser.delete();
    } catch (error) {
        console.log(".signInWithCredential err ", error);
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.