You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

firebase_ui_auth的ForgotPasswordScreen账户存在状态泄露及枚举防护问题

解决Firebase UI Auth的账户状态泄露问题

问题现状

  • 密码重置流程:输入格式有效但系统不存在的邮箱时,前端直接显示EMAIL_NOT_FOUND提示,后端API返回明确的账户不存在错误(请求示例及响应如下)
  • 重复注册流程:即使开启Email Enumeration protection,注册已存在的邮箱时仍会泄露账户已存在的状态

密码重置请求示例

curl "https://identitytoolkit.googleapis.com/v1/accounts:sendOobCode?key=AgwiSyC-tRO9CaBdWeRMU_a1234567-Jl1234ec" \
  -H "authority: identitytoolkit.googleapis.com" \
  -H "accept: */*" \
  -H "accept-language: en-US,en;q=0.9" \
  -H "content-type: application/json" \
  -H "origin: http://localhost:63865" \
  -H "sec-ch-ua: \"Not_A Brand\";v=\"99\", \"Google Chrome\";v=\"109\", \"Chromium\";v=\"109\"" \
  -H "sec-ch-ua-mobile: ?0" \
  -H "sec-ch-ua-platform: \"Windows\"" \
  -H "sec-fetch-dest: empty" \
  -H "sec-fetch-mode: cors" \
  -H "sec-fetch-site: cross-site" \
  -H "user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36" \
  -H "x-client-data: CInaygE=" \
  -H "x-client-version: Chrome/JsCore/9.15.0/FirebaseCore-web" \
  -H "x-firebase-gmpid: 1:621401234567:web:7d6e685agh2315aea7f93b" \
  --data-raw "{\"requestType\":\"PASSWORD_RESET\",\"email\":\"example1@example.com\"}" \
  --compressed

对应错误响应

{
"error": {
"code": 400,
"message": "EMAIL_NOT_FOUND",
"errors": [
{
"message": "EMAIL_NOT_FOUND",
"domain": "global",
"reason": "invalid"
}
]
}
}

解决方案

1. 密码重置流程:统一错误提示

Firebase UI Auth默认会直接暴露API错误,需自定义错误拦截逻辑,无论邮箱是否存在,返回通用提示:

const uiConfig = {
  signInOptions: [firebase.auth.EmailAuthProvider.PROVIDER_ID],
  callbacks: {
    signInFailure: (error) => {
      // 拦截邮箱不存在错误
      if (error.code === 'auth/email-not-found') {
        document.getElementById('auth-error').textContent = '如果该邮箱已注册,重置邮件已发送至对应邮箱';
        return false; // 阻止UI显示默认错误
      }
      // 其他错误正常抛出
      return true;
    }
  },
  // 其他UI配置项
};

// 初始化Firebase UI
const ui = new firebaseui.auth.AuthUI(firebase.auth());
ui.start('#firebaseui-auth-container', uiConfig);

2. 重复注册流程:自定义注册逻辑

通过Firebase Cloud Functions拦截注册请求,统一返回相同提示,避免泄露账户状态:

const functions = require("firebase-functions");
const admin = require("firebase-admin");
admin.initializeApp();

exports.customSignUp = functions.https.onCall(async (data) => {
  const { email, password } = data;

  try {
    // 尝试创建用户
    await admin.auth().createUser({
      email,
      password,
      emailVerified: false
    });
    return { message: '注册请求已处理,请检查邮箱完成验证' };
  } catch (error) {
    // 拦截邮箱已存在错误,返回通用提示
    if (error.code === 'auth/email-already-exists') {
      return { message: '注册请求已处理,请检查邮箱完成验证' };
    }
    // 其他错误抛出通用异常
    throw new functions.https.HttpsError('internal', '注册失败,请稍后重试');
  }
});

3. 启用官方枚举防护

在Firebase控制台Authentication > 设置 > 高级中开启Email Enumeration protection,该功能会自动在登录场景隐藏邮箱不存在的错误,配合上述自定义逻辑覆盖全场景漏洞。

内容的提问来源于stack exchange,提问作者puzzled

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 13:31:01