ajo*_*nno 8 javascript firebase firebase-authentication
我们在尝试解决此问题时遇到了实际问题,因此希望获得一些Firebase帮助/解决了同样问题的帮助.
该应用程序是React Native(0.43.2)并使用Firebase JS API(最新)
我们提供Facebook和Google身份验证.工作良好.
但是,如果用户:
auth/account-exists-with-different-credential
从阅读文档和SO上的一些帖子,我们认为以下是正确的,但显然不是因为我们得到了相同的身份验证错误.
...error returned by Firebase auth after trying Facebook login...
const email = error.email;
const pendingCred = error.credential;
firebase.auth().fetchProvidersForEmail(email)
.then(providers => {
//providers returns this array -> ["google.com"]
firebase.auth().signInWithCredential(pendingCred)
.then(result => {
result.user.link(pendingCred)
})
.catch(error => log(error))
Run Code Online (Sandbox Code Playgroud)
对signInWithCredential的调用抛出相同的错误auth/account-exists-with-different-credential.
任何人都可以帮助指出我们在这个实现中做错了什么吗?非常感激.
boj*_*eil 13
发生的事情是Firebase为所有电子邮件强制执行相同的帐户.由于您已经拥有同一封电子邮件的Google帐户,因此您需要将该Facebook帐户与Google帐户相关联,以便用户可以访问相同的数据,并且下次可以使用Google或Facebook登录同一帐户.
您的代码段中的问题是您使用相同的凭据进行签名和链接.修改如下.当您收到错误'auth/account-exists-with-different-credential'时,错误将包含error.email和error.credential(Facebook OAuth凭证).您需要先查找error.email以获取现有提供程序.
firebase.auth().fetchProvidersForEmail(error.email)
.then(providers => {
//providers returns this array -> ["google.com"]
// You need to sign in the user to that google account
// with the same email.
// In a browser you can call:
// var provider = new firebase.auth.GoogleAuthProvider();
// provider.setCustomParameters({login_hint: error.email});
// firebase.auth().signInWithPopup(provider)
// If you have your own mechanism to get that token, you get it
// for that Google email user and sign in
firebase.auth().signInWithCredential(googleCred)
.then(user => {
// You can now link the pending credential from the first
// error.
user.linkWithCredential(error.credential)
})
.catch(error => log(error))
Run Code Online (Sandbox Code Playgroud)
我觉得 Firebase 选择这种行为作为默认行为很奇怪也很不方便,而且解决方案很重要。这是截至撰写本文时基于 @bojeil 的回答的 Firebase 的完整且更新的解决方案。
function getProvider(providerId) {
switch (providerId) {
case firebase.auth.GoogleAuthProvider.PROVIDER_ID:
return new firebase.auth.GoogleAuthProvider();
case firebase.auth.FacebookAuthProvider.PROVIDER_ID:
return new firebase.auth.FacebookAuthProvider();
case firebase.auth.GithubAuthProvider.PROVIDER_ID:
return new firebase.auth.GithubAuthProvider();
default:
throw new Error(`No provider implemented for ${providerId}`);
}
}
const supportedPopupSignInMethods = [
firebase.auth.GoogleAuthProvider.PROVIDER_ID,
firebase.auth.FacebookAuthProvider.PROVIDER_ID,
firebase.auth.GithubAuthProvider.PROVIDER_ID,
];
async function oauthLogin(provider) {
try {
await firebase.auth().signInWithPopup(provider);
} catch (err) {
if (err.email && err.credential && err.code === 'auth/account-exists-with-different-credential') {
const providers = await firebase.auth().fetchSignInMethodsForEmail(err.email)
const firstPopupProviderMethod = providers.find(p => supportedPopupSignInMethods.includes(p));
// Test: Could this happen with email link then trying social provider?
if (!firstPopupProviderMethod) {
throw new Error(`Your account is linked to a provider that isn't supported.`);
}
const linkedProvider = getProvider(firstPopupProviderMethod);
linkedProvider.setCustomParameters({ login_hint: err.email });
const result = await firebase.auth().signInWithPopup(linkedProvider);
result.user.linkWithCredential(err.credential);
}
// Handle errors...
// toast.error(err.message || err.toString());
}
}
Run Code Online (Sandbox Code Playgroud)
@Bojeil 的答案是正确的,但我想为其添加一些颜色。
首先,为什么 Firebase 不直接处理这个问题而不让我参与?IOW,为什么我们auth/account-exists-with-different-credential首先会收到错误?
谷歌认为(正确或错误)Facebook(和其他)登录可能使用未经验证的电子邮件地址(请参阅此已关闭的问题等)。对于未经验证的电子邮件,此流程的安全问题如下:
因此,在第 4 步,Firebase 拒绝执行此操作,而是将auth/account-exists-with-different-credential失败返回给您的应用程序。您的应用程序现在要求 Alice 使用她的 Google 帐户登录(Eve 不能这样做),以便将 Facebook 帐户链接到与 Google 帐户相同的身份。
如果 Alice 首先使用她的 @gmail.com 帐户通过 Facebook 进行身份验证,她就可以通过 Facebook 访问她的帐户。如果她稍后通过 Google 使用相同的 @gmail.com 帐户进行身份验证,Firebase 会自动链接 Google 帐户并从帐户身份中删除之前的 Facebook 登录信息。
这是为了避免另一个攻击媒介:如果 Eve 可以在 Alice 登录之前通过她的 Facebook 帐户和 Alice 的电子邮件地址创建一个应用程序帐户,那么 Eve 就提前获得了对 Alice 帐户的访问权限。换句话说,Alice 可能会高兴地创建一个帐户/以 alice@gmail.com 身份登录,但没有意识到 Eve 的 Facebook 帐户已附加到该登录帐户,因此 Eve 可以登录该帐户。由于 Firebase 只是删除了非规范的 Facebook 登录信息,因此 Eve 无法再访问它,并且该攻击媒介也被消除了。
同样,假设您想保留 Firebase“链接使用同一电子邮件的帐户”设置,@bojeil 的答案是正确的。但是,请注意,在浏览器环境中,通过弹出窗口获取规范凭据通常不起作用,因为第二个弹出窗口不会是用户操作的直接结果,浏览器将阻止它。
解决此问题的一种方法是通过重定向执行规范登录。另一种解决方案是向用户显示凭据问题,并显示一条消息,例如“您已经拥有与此电子邮件关联的 Gmail 帐户,单击以使用该帐户登录并确认此 Facebook 帐户的所有权”。然后,明确单击另一个按钮,以便使用该帐户的规范凭据登录。由于第二次登录现在是用户操作的直接结果,因此弹出窗口不会被阻止。
| 归档时间: |
|
| 查看次数: |
3264 次 |
| 最近记录: |