Firebase邮箱/密码认证:如何要求邮箱验证并配置未验证时不返回Bearer Token?
好问题!我对Firebase Auth这块熟得很,直接给你说结论:Firebase邮箱/密码认证提供程序没有开箱即用的配置项,能让用户未完成邮箱验证时就阻止返回Bearer Token并返回403错误。
为什么没有这个默认配置?
Firebase Auth的设计逻辑和Cognito不一样:邮箱验证在Firebase里是一个额外的用户状态标记,而非登录的前置条件。只要用户输入正确的邮箱和密码,不管邮箱是否验证,系统都会正常颁发ID Token(也就是你说的Bearer Token)。这个设计是为了支持一些不需要强制验证邮箱的场景,比如允许用户先体验部分功能,再引导验证。
替代方案:不用写复杂处理函数也能实现类似效果
虽然没有直接的开关,但有几种简洁的方式可以达到类似Cognito的强制验证效果:
用Cloud Functions自定义登录逻辑
放弃直接调用signInWithEmailAndPassword,让前端调用一个Cloud Functions的Callable函数,在函数里先检查用户的邮箱验证状态,只有验证通过才生成自定义令牌返回给前端,前端再用signInWithCustomToken登录。未验证的用户会在函数层被拦截,直接返回403。
示例函数代码:const functions = require("firebase-functions"); const admin = require("firebase-admin"); admin.initializeApp(); exports.signInWithVerifiedEmail = functions.https.onCall(async (data, context) => { const { email, password } = data; try { // 先验证账号密码有效性 const userRecord = await admin.auth().getUserByEmail(email); // 检查邮箱是否已验证 if (!userRecord.emailVerified) { throw new functions.https.HttpsError("permission-denied", "请先验证邮箱"); } // 生成自定义令牌供前端登录 const customToken = await admin.auth().createCustomToken(userRecord.uid); return { token: customToken }; } catch (error) { throw new functions.https.HttpsError("invalid-argument", error.message); } });用Security Rules保护核心资源
如果你主要是想阻止未验证用户访问Firebase的核心资源(比如Firestore、Storage),直接在Security Rules里添加邮箱验证检查即可。这样即使用户拿到了Token,也无法访问受保护的资源,效果和强制验证登录差不多。
示例Firestore规则:rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { match /{document=**} { allow read, write: if request.auth != null && request.auth.token.email_verified == true; } } }前端/后端拦截未验证用户
可以在前端路由守卫或者后端API拦截器里,检查登录用户的emailVerified状态,如果为false就强制登出并返回403提示。比如前端用React的路由守卫:import { getAuth, onAuthStateChanged, signOut } from "firebase/auth"; const auth = getAuth(); onAuthStateChanged(auth, (user) => { if (user && !user.emailVerified) { signOut(auth); alert("请先验证邮箱才能登录"); // 跳转到验证引导页 window.location.href = "/verify-email"; } });
总结
Firebase确实没有开箱即用的配置来直接阻止未验证用户获取Token,但通过上面几种方式,不需要写太多复杂的处理逻辑就能实现类似Cognito的强制邮箱验证效果,其中Cloud Functions的方式最接近你想要的“认证环节拦截”需求,而Security Rules则是保护资源最省心的方案。
内容的提问来源于stack exchange,提问作者codeAndStuff

