firebase - 使用密码身份验证向用户添加电子邮件链接身份验证时,linkWithCredential 会引发提供程序已链接的错误
问题描述
我有一个使用电子邮件/密码进行身份验证的用户。当我尝试使用credentialWithLink
and为用户添加电子邮件链接身份验证时linkWithCredential
,出现错误:
code: "auth/provider-already-linked"
message: "User can only be linked to one identity for the given provider."
错误消息告诉我,我无法为用户添加电子邮件链接身份验证,因为用户已经使用密码通过电子邮件提供商进行了身份验证。
那么使用密码身份验证为现有用户添加电子邮件链接身份验证的正确方法是什么?
这是我尝试抛出“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
and linkWithCredential
。那我该怎么办?
解决方案
您正在尝试将使用电子邮件创建的帐户与另一个电子邮件链接。正如错误所说,“用户只能链接到给定提供者的一个身份。”。这意味着一个帐户只能将一个电子邮件、谷歌帐户、Facebook 等链接在一起。
如果您希望一个用户拥有多封电子邮件,那么您可能必须使用数据库。
如果您使用 Firestore,那么您可以像这样存储电子邮件,并在需要时进行如下查询:
userRef.where("emails", "array-contains", "emailEnteredByUser");
PS:用户只能使用他们最初用来创建帐户的主要电子邮件来登录或注册。
一种解决方法:您实际上可以依靠电子邮件链接身份验证来允许用户登录。当用户输入他们的电子邮件并单击登录时,您可以运行云功能(或您自己服务器中的功能)来生成登录链接,然后验证用户的文档是否包含他们输入的电子邮件,并使用Nodemailer 之类的东西来发送电子邮件他们是登录链接。
编辑: OP 假定密码和登录链接是不同的身份验证提供程序。如此处的文档中所述:
用户首次登录后,会创建一个新用户帐户并将其链接到凭据(即用户名和密码、电话号码或身份验证提供商信息),即用户登录时使用的凭据。因此,如果用户存在电子邮件,您仍然可以使用电子邮件链接。
推荐阅读
- reactjs - 无法从后端 API 检索授权标头
- spring - 如何从内部测试访问默认静态内部类
- awk - 在多个文件中查找模式并对它们执行一些操作
- mysql - sql条件至少有一个子项是状态成功
- performance - 如何提高 Julia the Storkey 的学习表现?
- dns - 如何通过动态 ip 将我的域设置为覆盆子?
- node.js - “任何型号”是否有猫鼬类型?
- python-3.x - python 中的 sys.exit 给出了 SystemExit 错误
- neo4j - 在 neo4j 中为特定节点获取树
- java - 在 Java 中使用 vlcj 时,VLC 无法打开 th MRL