Обработка связывания аккаунтов в 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);
}
}