我使用Firebase认证与电子邮件和密码,所以没有外部Id提供程序。
我想要的行为:
- 只有某个邮件域的用户才能注册。我将其命名为"domain"。
- 用户注册时收到一封验证邮件。
- 用户每次尝试使用未经验证的电子邮件登录时,都会收到一封验证电子邮件。
- 应该阻止访问,直到电子邮件被验证。
这是我认为在注册时发生的事情:
- beforeCreate()只在创建用户之前触发一次,并且不会为该用户再次触发。如果域不是"@domain.com"则抛出错误,否则失败。此功能似乎工作正常。
- beforeignign()在forecreate()之前触发。由于此时尚未验证电子邮件,因此用户应该收到一封验证电子邮件。问题是代码没有发送邮件。
我从beforeignignin()得到这个错误:未处理的错误FirebaseAuthError:没有与提供的标识符相对应的用户记录。因为用户没有被创建。如果我移动"发送电子邮件"代码片段到beforeCreate(),用户被创建,但我仍然得到相同的"没有用户记录"from beforeCreate().
请建议。
const functions = require('firebase-functions');
exports.beforeCreate = functions.auth.user().beforeCreate((user, context) => {
if (!user?.email?.includes('@domain.com')) {
throw new functions.auth.HttpsError(
'invalid-argument', 'Unauthorized email');
}
});
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
exports.beforeSignIn = functions.auth.user().beforeSignIn((user, context) => {
if (user.email && !user.emailVerified) {
// Send custom email verification on sign-up.
const locale = context.locale;
return admin.auth().generateEmailVerificationLink(user.email).then((link) => {
return sendCustomVerificationEmail(user.email, link, locale);
});
}
});
UPDATE:人们在尝试执行这种广受欢迎的流程时浪费了大量时间。正如我所提到的,在第一次登录(与注册同时发生)执行之前,不可能生成链接。
如果您使用OG电子邮件/密码提供程序(不是无密码的),唯一的方法是在注册后立即将用户签出。由于这是客户端代码(可以被任何人更改),因此您必须通过检查每个请求是否验证电子邮件来保护您的资源。
我最近做了一个身份平台用户授权的终极指南,在那里我深入探讨了如何实现这一点。您可以在本节中看到退出,以及如何在保护数据部分中保护您的数据(检查email_verified == true
)。你既可以使用Firebase规则,也可以在后端使用中间件。
我昨天注意到同样的bug。在beforeignin函数中调用generateEmailVerificationLink
时,我得到同样的错误。这个谷歌级别的权限怎么能被如此破坏,真是太蠢了。
关于这个问题,我又写了一个StackOverflow问题。我更深入地解释:阻止功能被破坏,无法在验证电子邮件地址之前阻止登录(谷歌身份平台&重火力点Auth)我认为你不能用你目前的方法来解决这个问题,在这里有阻止功能来生成验证电子邮件。
编辑:我只是想补充一下,目前我能找到的唯一方法是在创建和后发送电子邮件登录和检查email_verified
索赔每次有一个请求后端(无论是通过使用Firestore规则或使用管理员SDK为您的自定义服务器路由)
您需要使用beforeCreate
阻止功能在用户创建帐户之前对其进行管理:
要求注册时进行电子邮件验证
下面的示例显示了如何要求用户在注册后验证他们的电子邮件:
exports.beforeCreate = authClient.functions().beforeCreateHandler((user, context) => {
const locale = context.locale;
if (user.email && !user.emailVerified) {
// Send custom email verification on sign-up.
return admin.auth().generateEmailVerificationLink(user.email).then((link) => {
return sendCustomVerificationEmail(user.email, link, locale);
});
}
});
exports.beforeSignIn = authClient.functions().beforeSignInHandler((user, context) => {
if (user.email && !user.emailVerified) {
throw new gcipCloudFunctions.https.HttpsError(
'invalid-argument', `"${user.email}" needs to be verified before access is granted.`);
}
});