Обработка связывания аккаунтов в Firebase

Я следую инструкциям 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);
}

2 ответа

Решение

Это примерно шаги для обработки аутентификации / учетной записи "существует с разными учетными данными": вы получите эту ошибку, если войдете в новую учетную запись Facebook, которая использует электронную почту другой учетной записи, которая уже существует. Допустим, существующая учетная запись является учетной записью Google.

Вы получите эту ошибку в getRedirectResult().catch(function(error) {})

Ошибка также будет содержать адрес электронной почты и учетные данные. Вам нужно будет сохранить учетные данные (используя рекомендуемое sessionStorage). Проверьте этот пост для получения дополнительной информации об этом: Аутентификация Firebase Javascript: setCookie для ожидающих учетных данных для перенаправления

Вы тогда звоните 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

Я думаю, что Firebase API немного изменился и firebase.auth().currentUser.link(savedCred);сейчас firebase.auth().currentUser.linkWithRedirect(provider), В моей реализации я сохраняю изначально выбранного провайдера в sessionStorage и использую его вышеуказанным методом на случай, если требуется привязка аккаунта.

Вы также можете сделать linkWithPopUp если это соответствует вашим потребностям лучше.

Внимательно прочитайте пример https://firebase.google.com/docs/auth/web/google-signin раздел "Обработка ошибок учетной записи" существует с разными учетными данными ""

Режим перенаправления Эта ошибка обрабатывается аналогичным образом в режиме перенаправления, с той разницей, что ожидающие учетные данные должны кэшироваться между перенаправлениями страниц (например, с использованием хранилища сеансов).

Ниже приведен соответствующий фрагмент рабочего кода (он находится внутри асинхронной функции). Обратите внимание, что "яблоки" - это просто упрощенная запись теста в 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);
    }
}
Другие вопросы по тегам