您可以通过将多个身份验证提供方凭据关联至现有用户帐号,让用户可以使用多个身份验证提供方登录您的应用。无论用户使用哪个身份验证提供方登录,系统均可通过同一 Firebase 用户 ID 识别用户。例如,使用密码登录的用户可以关联 Google 帐号,以后便可使用这两种方法中的任意一种登录。或者,匿名用户可以关联 Facebook 帐号,以后就可以使用 Facebook 帐号登录并继续使用您的应用。
准备工作
为您的应用增加对两个或多个身份验证提供方(可能包括匿名身份验证)的支持。
将联合身份验证提供方凭据与用户帐号关联
如需将如 Google 或 Facebook 等身份验证提供方的凭据与现有用户帐号关联,请按以下步骤操作:
- 使用任意身份验证提供方或方法让用户登录。
- 获取要关联至用户帐号的提供方所对应的
AuthProvider
对象。示例:Web 模块化 API
import { GoogleAuthProvider, FacebookAuthProvider, TwitterAuthProvider, GithubAuthProvider } from "firebase/auth"; const googleProvider = new GoogleAuthProvider(); const facebookProvider = new FacebookAuthProvider(); const twitterProvider = new TwitterAuthProvider(); const githubProvider = new GithubAuthProvider();
Web 命名空间型 API
var googleProvider = new firebase.auth.GoogleAuthProvider(); var facebookProvider = new firebase.auth.FacebookAuthProvider(); var twitterProvider = new firebase.auth.TwitterAuthProvider(); var githubProvider = new firebase.auth.GithubAuthProvider();
- 提示用户使用要关联的提供方进行登录。您可以通过弹出式窗口或重定向至提供方的登录页面,提示用户进行登录。在移动设备上最好使用重定向方法。
- 如需使用弹出式窗口登录,请调用
linkWithPopup
:Web 模块化 API
import { getAuth, linkWithPopup, GoogleAuthProvider } from "firebase/auth"; const provider = new GoogleAuthProvider(); const auth = getAuth(); linkWithPopup(auth.currentUser, provider).then((result) => { // Accounts successfully linked. const credential = GoogleAuthProvider.credentialFromResult(result); const user = result.user; // ... }).catch((error) => { // Handle Errors here. // ... });
Web 命名空间型 API
auth.currentUser.linkWithPopup(provider).then((result) => { // Accounts successfully linked. var credential = result.credential; var user = result.user; // ... }).catch((error) => { // Handle Errors here. // ... });
- 如需重定向到提供方的登录页面进行登录,请调用
linkWithRedirect
:使用“linkWithRedirect”时,请遵循最佳实践。Web 模块化 API
import { getAuth, linkWithRedirect, GoogleAuthProvider } from "firebase/auth"; const provider = new GoogleAuthProvider(); const auth = getAuth(); linkWithRedirect(auth.currentUser, provider) .then(/* ... */) .catch(/* ... */);
Web 命名空间型 API
auth.currentUser.linkWithRedirect(provider) .then(/* ... */) .catch(/* ... */);
getRedirectResult
来检索登录结果:Web 模块化 API
import { getRedirectResult } from "firebase/auth"; getRedirectResult(auth).then((result) => { const credential = GoogleAuthProvider.credentialFromResult(result); if (credential) { // Accounts successfully linked. const user = result.user; // ... } }).catch((error) => { // Handle Errors here. // ... });
Web 命名空间型 API
auth.getRedirectResult().then((result) => { if (result.credential) { // Accounts successfully linked. var credential = result.credential; var user = result.user; // ... } }).catch((error) => { // Handle Errors here. // ... });
如果凭据已与另一用户帐号关联,帐号关联将失败。在这种情况下,您必须根据需要为您的应用合并帐号和相关数据:
Web 模块化 API
import { getAuth, signInWithCredential, linkWithCredential, OAuthProvider } from "firebase/auth"; // The implementation of how you store your user data depends on your application const repo = new MyUserDataRepo(); // Get reference to the currently signed-in user const auth = getAuth(); const prevUser = auth.currentUser; // Get the data which you will want to merge. This should be done now // while the app is still signed in as this user. const prevUserData = repo.get(prevUser); // Delete the user's data now, we will restore it if the merge fails repo.delete(prevUser); // Sign in user with the account you want to link to signInWithCredential(auth, newCredential).then((result) => { console.log("Sign In Success", result); const currentUser = result.user; const currentUserData = repo.get(currentUser); // Merge prevUser and currentUser data stored in Firebase. // Note: How you handle this is specific to your application const mergedData = repo.merge(prevUserData, currentUserData); const credential = OAuthProvider.credentialFromResult(result); return linkWithCredential(prevUser, credential) .then((linkResult) => { // Sign in with the newly linked credential const linkCredential = OAuthProvider.credentialFromResult(linkResult); return signInWithCredential(auth, linkCredential); }) .then((signInResult) => { // Save the merged data to the new user repo.set(signInResult.user, mergedData); }); }).catch((error) => { // If there are errors we want to undo the data merge/deletion console.log("Sign In Error", error); repo.set(prevUser, prevUserData); });
Web 命名空间型 API
// The implementation of how you store your user data depends on your application var repo = new MyUserDataRepo(); // Get reference to the currently signed-in user var prevUser = auth.currentUser; // Get the data which you will want to merge. This should be done now // while the app is still signed in as this user. var prevUserData = repo.get(prevUser); // Delete the user's data now, we will restore it if the merge fails repo.delete(prevUser); // Sign in user with the account you want to link to auth.signInWithCredential(newCredential).then((result) => { console.log("Sign In Success", result); var currentUser = result.user; var currentUserData = repo.get(currentUser); // Merge prevUser and currentUser data stored in Firebase. // Note: How you handle this is specific to your application var mergedData = repo.merge(prevUserData, currentUserData); return prevUser.linkWithCredential(result.credential) .then((linkResult) => { // Sign in with the newly linked credential return auth.signInWithCredential(linkResult.credential); }) .then((signInResult) => { // Save the merged data to the new user repo.set(signInResult.user, mergedData); }); }).catch((error) => { // If there are errors we want to undo the data merge/deletion console.log("Sign In Error", error); repo.set(prevUser, prevUserData); });
- 如需使用弹出式窗口登录,请调用
将电子邮件地址和密码凭据与用户帐号相关联
如需将电子邮件地址和密码凭据添加到现有用户帐号,请按以下步骤操作:
- 使用任意身份验证提供方或方法让用户登录。
- 提示用户输入电子邮件地址和新密码。
- 使用电子邮件地址和密码创建一个
AuthCredential
对象:Web 模块化 API
import { EmailAuthProvider } from "firebase/auth"; const credential = EmailAuthProvider.credential(email, password);
Web 命名空间型 API
var credential = firebase.auth.EmailAuthProvider.credential(email, password);
将
AuthCredential
对象传递给已登录用户的linkWithCredential
方法:Web 模块化 API
import { getAuth, linkWithCredential } from "firebase/auth"; const auth = getAuth(); linkWithCredential(auth.currentUser, credential) .then((usercred) => { const user = usercred.user; console.log("Account linking success", user); }).catch((error) => { console.log("Account linking error", error); });
Web 命名空间型 API
auth.currentUser.linkWithCredential(credential) .then((usercred) => { var user = usercred.user; console.log("Account linking success", user); }).catch((error) => { console.log("Account linking error", error); });
如果凭据已与另一用户帐号关联,则无法调用
linkWithCredential
。在这种情况下,您必须根据需要为您的应用合并帐号和相关数据(请参阅上方示例)。
取消身份验证提供方与用户帐号的关联
您可以取消身份验证提供方与帐号的关联,这样用户就无法再通过该提供方登录了。
如需解除身份验证提供方与用户帐号的关联,请将提供方 ID 传递给 unlink
方法。您可以从 providerData
属性中获取与用户相关联的身份验证提供方的 ID。
Web 模块化 API
import { getAuth, unlink } from "firebase/auth"; const auth = getAuth(); unlink(auth.currentUser, providerId).then(() => { // Auth provider unlinked from account // ... }).catch((error) => { // An error happened // ... });
Web 命名空间型 API
user.unlink(providerId).then(() => { // Auth provider unlinked from account // ... }).catch((error) => { // An error happened // ... });