已验证邮箱但Firebase可调用云函数中email_verified仍为false如何解决
问题原因
两个验证状态的数据源不同,出现差异是正常现象:
- 前端
firebase.auth().currentUser的emailVerified是客户端本地缓存的用户状态,你完成邮箱验证后客户端会同步更新这个本地状态,所以打印出来是true。 - 云函数侧
context.auth.token里的email_verified取自用户登录时Firebase签发的JWT身份令牌,JWT的特性是签发后内容不可篡改,默认有效期为1小时,在有效期内不会自动刷新,所以你完成验证后如果没刷新令牌,调用云函数时传的还是旧的、存着email_verified: false的令牌,就会出现两边状态不一致的问题。
解决方案
- 邮箱验证流程完成后,主动强制刷新用户ID令牌
在前端完成邮箱验证的逻辑后添加如下代码即可,调用前注意判断currentUser是否存在避免空指针报错:
// 强制刷新ID令牌,从服务端拉取最新的用户状态生成新令牌 await firebase.auth().currentUser.getIdToken(true);
这个操作完成后,后续所有云函数调用都会自动携带新令牌,云函数侧就能读到正确的email_verified: true状态,无需修改原有云函数调用逻辑。
可选降级方案
如果不想处理令牌刷新逻辑,也可以在邮箱验证完成后引导用户重新登录,重新登录时签发的新令牌也会包含最新的邮箱验证状态,缺点是会打断用户操作流程,体验不如主动刷新令牌好。云函数侧补充错误返回(可选优化)
可以在云函数的未验证分支给前端返回明确的错误标识,前端收到对应错误后可以自动触发令牌刷新,再重试一次云函数调用,避免用户操作后还是调用失败的问题:
export const myFunction = functions.https.onCall(async (data, context) => { if (context.auth && context.auth.token.email_verified) { //my actual function code } else { if (!context.auth) { functions.logger.log("unauthenticated call to myFunction"); throw new functions.https.HttpsError('unauthenticated', '用户未登录'); } else if (!context.auth.token.email_verified) { functions.logger.log("unverified email call to myFunction with token", context.auth.token); throw new functions.https.HttpsError('permission-denied', '邮箱未验证'); } } });
内容的提问来源于stack exchange,提问作者jeannot789
相关产品推荐
相关产品推荐

