我正在使用 Firebase 身份验证和 Firestore 在 React 应用程序中构建注册组件。我想实现以下功能:
如果用户尝试向 Google 注册并且他们已存在于 Firestore 中,则应将他们重定向到主页。 如果它们不存在,我想在 Firestore 中创建一个新文档。 如果用户已经拥有一个包含电子邮件/密码的帐户,我想将 Google 帐户链接为附加提供商。
我遇到一个问题,当我测试它时,如果用户有电子邮件/密码提供商,它将删除它并仅添加 Google 提供商。
const handleEmailPasswordRegistration = async (e) => {
e.preventDefault();
setEmailloading(true);
setMessage({ type: "", text: "" });
try {
const userCredential = await createUserWithEmailAndPassword(
auth,
email,
password
);
const user = userCredential.user;
await setDoc(doc(db, "users", user.uid), {
firstName,
lastName,
email: user.email,
createdAt: new Date(),
});
setMessage({ type: "success", text: "Registration successful!" });
navigate("/");
} catch (error) {
console.error(error);
setMessage({ type: "error", text: error.message });
} finally {
setEmailloading(false);
}
};
const handleGoogleRegistration = async () => {
setGoogleloading(true);
setMessage({ type: "", text: "" });
try {
const result = await signInWithPopup(auth, googleProvider);
const user = result.user;
const userRef = doc(db, "users", user.uid);
const docSnap = await getDoc(userRef);
if (docSnap.exists()) {
if (
user.providerData.some(
(provider) => provider.providerId === "google.com"
)
) {
setMessage({
type: "success",
text: "You are already registered with Google!",
});
} else {
const credential = GoogleAuthProvider.credentialFromResult(result);
await linkWithCredential(user, credential);
setMessage({
type: "success",
text: "Google account successfully linked to your existing account!",
});
}
} else {
await setDoc(doc(db, "users", user.uid), {
firstName: user.displayName?.split(" ")[0] || "",
lastName: user.displayName?.split(" ")[1] || "",
email: user.email,
createdAt: new Date(),
});
setMessage({
type: "success",
text: "Registration successful with Google!",
});
}
navigate("/");
} catch (error) {
console.error(error);
setMessage({ type: "error", text: error.message });
} finally {
setGoogleloading(false);
}
};
我正在努力解决如何正确检查 Firestore 中的用户是否存在并链接其他(谷歌)身份验证提供商而不覆盖现有身份验证提供商(电子邮件/密码)。
我使用了
linkWithCredentials
以及 linkWithPopUp
但它仍然会删除并添加 google 提供商作为身份验证提供商。
它不会覆盖用户,而是覆盖用户身份验证提供程序。如果用户使用电子邮件/密码注册,然后注销并尝试使用其 Google 帐户登录,它将删除电子邮件和密码并使用 Google 身份验证作为提供商。
您所遇到的是预期行为,因为当用户使用电子邮件和密码登录并随后使用 Google 提供商登录时,Firebase 身份验证中的数据始终会被覆盖。这意味着 Google 凭据仍为默认凭据,之前选择的电子邮件和密码将不再用于对用户进行身份验证。发生这种情况的原因很明显,Google 帐户是比任何其他提供商(包括电子邮件和密码)更值得信赖的来源。
如果您想同时使用两种身份验证类型,我建议您根据电子邮件地址将这 2 个帐户链接到一个帐户中。