我有一个使用电子邮件/密码进行身份验证的用户。当我尝试使用 credentialWithLink
和 linkWithCredential
为用户添加电子邮件链接身份验证时,出现错误:
code: "auth/provider-already-linked"
message: "User can only be linked to one identity for the given provider."
错误消息告诉我,我无法为用户添加电子邮件链接身份验证,因为用户已经使用密码通过电子邮件提供商的身份验证。
那么使用密码认证为现有用户添加 emaillink 认证的正确方法是什么?
这是我尝试抛出“auth/provider-already-linked”错误的尝试:
const userCred = await firebase
.auth()
.createUserWithEmailAndPassword(email, password);
if (userCred) {
const { user } = userCred;
await user.sendEmailVerification());
}
await firebase.auth().applyActionCode(actionCode)
await firebase.auth().currentUser.reload()
此时,用户已登录,fetchSignInMethodsForEmail
返回 ['password']
。
const signInMethods = await firebase.auth().fetchSignInMethodsForEmail(email)
if (signInMethods) {
console.log(signInMethods) // returns ['password']
}
await firebase.auth().sendSignInLinkToEmail(email, actionCodeSettings)
window.localStorage.setItem('emailForSignIn', email)
if (firebase.auth().isSignInWithEmailLink(href)) {
let email = window.localStorage.getItem('emailForSignIn')
if (!email) {
email = window.prompt('Please provide your email for confirmation')
}
const credential = firebase.auth.EmailAuthProvider.credentialWithLink(
email,
window.location.href
);
firebase
.auth()
.currentUser.linkWithCredential(credential)
.then((result) => {
console.log('success linking with email link')
window.localStorage.removeItem('emailForSignIn')
})
.catch((error) => {
// Some error occurred.
console.log('error linking with email link')
console.log(error)
})
}
由于我已经登录并与电子邮件提供商关联,因此调用 firebase.auth.EmailAuthProvider.credentialWithLink
会引发错误。
那么如何为已经通过电子邮件提供商进行身份验证的用户添加 emaillink
登录方法,该电子邮件提供商只有 password
登录方法?从错误消息中,我知道我不应该使用 credentialWithLink
和 linkWithCredential
。那我该怎么办?
答案 0 :(得分:1)
您正尝试将使用电子邮件创建的帐户与另一个电子邮件相关联。正如错误所说,“用户只能链接到给定提供者的一个身份。”。这意味着一个帐户只能将一个电子邮件、Google 帐户、Facebook 等链接在一起。
如果您使用 Firestore,那么您可以像这样存储电子邮件,并在需要时进行如下查询:
userRef.where("emails", "array-contains", "emailEnteredByUser");
PS:用户只能使用他们最初用于创建帐户的主电子邮件来登录或注册。
解决方法:您实际上可以依靠 Email-Link Authentication 来允许用户登录。当用户输入他们的电子邮件并单击登录时,您可以运行云功能(或您自己服务器中的功能)以生成登录链接,然后验证用户的文档是否包含他们输入的电子邮件并使用类似 {{3 }} 将登录链接通过电子邮件发送给他们。
编辑: OP 假定的密码和登录链接是不同的身份验证提供程序。如文档中所述Nodemailer:
<块引用>用户第一次登录后,一个新的用户帐户 创建并链接到凭据 - 即用户名和 密码、电话号码或身份验证提供商信息——用户签名 在与。 因此,如果用户存在电子邮件,您仍然可以使用电子邮件链接。
答案 1 :(得分:0)
所以我想出了如何向使用电子邮件/密码登录的用户添加电子邮件链接。
TL/DR;使用 firebase.auth().signInWithEmailLink(email, href)
。不要使用 credentialWithLink
和 linkWithCredential
步骤 1 - 3 是正确的,但我需要更改步骤 4 以使用 firebase.auth().signInWithEmailLink(email, href)
而不是 credentialWithLink
和 linkWithCredential
这是正确的步骤 4:
if (firebase.auth().isSignInWithEmailLink(href)) {
let email = window.localStorage.getItem('emailForSignIn')
if (!email) {
email = window.prompt('Please provide your email for confirmation')
}
firebase
.auth()
.signInWithEmailLink(email, href)
.then((result) => {
console.log('success linking with email link')
window.localStorage.removeItem('emailForSignIn')
})
.catch((error) => {
// Some error occurred.
console.log('error signing in with email link')
console.log(error)
})
}