启用或停用电子邮件枚举保护

本指南介绍了电子邮件枚举保护功能,并说明了如何启用和停用该功能。如果您的项目是在 2023 年 9 月 15 日当天或之后创建的,则默认启用了电子邮件枚举保护功能。

概览

电子邮件枚举是一种暴力破解攻击,其中恶意攻击者会尝试通过将电子邮件地址传递给 API 并检查响应,来猜测或确认系统中的用户。

如果未启用电子邮件枚举保护,Identity Platform 会返回可用于电子邮件枚举攻击的信息:

  • 尝试使用系统中不存在的电子邮件地址登录。Identity Platform 会返回 EMAIL_NOT_FOUND 错误。

  • 尝试使用系统中已存在的电子邮件地址进行注册。Identity Platform 会返回 EMAIL_EXISTS 错误。

您可以使用 Identity Platform 的电子邮件枚举保护功能,保护应用中的用户账号免遭此类攻击。

启用电子邮件枚举保护后,您的项目将具有以下行为:

  • fetchSignInForEmail API 将失败。在 Android 版 SDK 22.3.0、iOS 版 SDK 10.18.0 和网站版 SDK 10.6.0 之前,将匿名身份验证用户与电子邮件地址相关联也不起作用。

  • 在所有平台上调用 createAuthUri REST API 或 fetchSignInMethodsForEmail 客户端 SDK 方法时,系统不再返回指定电子邮件地址的登录方法列表。

  • 用户必须先验证新地址,然后才能更改电子邮件地址。例如,您无法再在所有平台上使用 update REST API、setAccountInfo REST API 或 updateEmail 客户端 SDK 方法更改用户的电子邮件地址。

    您可以改用 verifyBeforeUpdateEmail(适用于网页版和 Android 版)或 sendEmailVerification(beforeUpdatingEmail:)(适用于 iOS 版)来代替此参数。

  • 您无法再使用 setAccountInfo REST API 将电子邮件地址/密码提供程序关联到现有用户账号。您无法再在任何平台上将 linkWithCredential Client SDK 方法与 EmailAuthCredential 搭配使用。请改用 REST API signUp,在 idToken 字段中传递用户的 ID 令牌,并在 emailpassword 字段中进行关联。

  • 移除了电子邮件验证流程的错误响应,例如通过使用请求类型 VERIFY_AND_CHANGE_EMAILPASSWORD_RESET 调用 sendOobCode REST API 而发起的验证流程,以及在调用适用于 Web 和 Android 的 verifyBeforeUpdateEmail、适用于 iOS 的 sendEmailVerification(beforeUpdatingEmail:) 或适用于所有平台的 sendPasswordResetEmail 客户端 SDK 方法时发起的验证流程。

    当您提出重设密码请求时,只有在电子邮件地址存在的情况下,系统才会发送验证电子邮件;当您提出更改电子邮件地址请求时,只有在电子邮件地址不存在的情况下,系统才会发送验证电子邮件。在这两种情况下,系统都不会显示具体错误消息来指明电子邮件未发送的情况。

    我们建议您不要允许用户在未完成电子邮件验证流程的情况下注册。

  • 无效的登录会返回 INVALID_LOGIN_CREDENTIALS 错误响应。 无效的注册情形仍会返回 EMAIL_EXISTS 错误,请参阅下一部分中的建议。

如果您的应用依赖于电子邮件枚举保护功能更改的任何行为,您目前可以停用该功能。不过,我们不建议长期这样做;请参阅下一部分。

安全建议

执行账号盗用攻击的最常见方法之一是使用泄露或易于猜到的凭据执行凭据填充攻击。电子邮件枚举还可用于获取用户的敏感信息,或对用户实施钓鱼式攻击。因此,Google 建议您使用电子邮件枚举保护功能来保护您的应用免受此类攻击。

  • 如果您的项目是在 2023 年 9 月 15 日当天或之后创建,则默认启用了电子邮件枚举保护功能。我们建议您让电子邮件枚举保护功能保持启用状态,并避免依赖本指南前面列出的任何行为。

  • 如果您的项目是在 2023 年 9 月 15 日之前创建的,则系统不会自动启用电子邮件枚举保护功能。

    如果您的应用不依赖本指南前面所述的任何行为,我们建议您立即启用电子邮件枚举保护功能。

    如果您的应用依赖于上述任何行为,我们建议您开始停止这样做,并尽快启用电子邮件枚举保护功能。

除了使用电子邮件枚举保护功能之外,您还可以考虑采取措施来防止滥用项目的注册端点(这些端点会持续返回 EMAIL_EXISTS 错误)。您可以通过以下几种方式实现此目标:

  • 启用 App Check
  • reCAPTCHA 集成到您的注册流程中。
  • 禁止使用电子邮件地址和密码或电子邮件链接登录,改用 Google 登录等替代方法。

启用电子邮件枚举保护

如需启用电子邮件枚举保护,请按以下步骤操作:

Firebase 控制台

  1. 在 Firebase 控制台中,前往 Firebase Auth 设置页面。

    前往 Firebase Authentication 设置

    1. 在导航窗格中,选择用户操作

    2. 选择电子邮件枚举保护(推荐)

  2. 点击保存

Node.js

  1. 安装 Admin SDK

  2. 如需启用电子邮件枚举保护,请使用以下任一方法:

    • 如需在项目级提供保护,请执行以下操作:

      import { getAuth } from 'firebase-admin/auth';
      
      getAuth().projectConfigManager().updateProjectConfig(
        {
          emailPrivacyConfig: {
            enableImprovedEmailPrivacy: true,
          },
        }
      );
      
    • 如需在租户级别提供保护,请执行以下操作:

      import { getAuth } from 'firebase-admin/auth';
      
      getAuth().tenantConfigManager().updateTenant(TENANT_ID,
        {
          emailPrivacyConfig: {
            enableImprovedEmailPrivacy: true,
          },
        }
      );
      

      TENANT_ID 替换为您要为其启用电子邮件枚举保护的租户 ID。

REST

  1. 在 Google Cloud 控制台中,使用 gcloud auth print-access-token 命令输出项目 ID 的访问令牌:

    gcloud auth print-access-token --project=PROJECT_ID
    
  2. 使用 Identity Toolkit API 为您的项目 ID 启用电子邮件枚举保护:

    curl -X PATCH -d "{'emailPrivacyConfig':{'enableImprovedEmailPrivacy':true}}" \
        -H 'Authorization: Bearer ACCESS_TOKEN' \
        -H 'Content-Type: application/json' -H 'X-Goog-User-Project: PROJECT_ID' \
        "https://identitytoolkit.googleapis.com/admin/v2/projects/PROJECT_ID/config?updateMask=emailPrivacyConfig"
    

替换以下内容:

  • ACCESS_TOKEN:您之前生成的访问令牌
  • PROJECT_ID:您的项目 ID

停用电子邮件枚举保护

如需停用电子邮件枚举保护,请按以下步骤操作:

Firebase 控制台

  1. 在 Firebase 控制台中,前往 Firebase Auth 设置页面。

    前往 Firebase Authentication 设置

    1. 在导航窗格中,选择用户操作

    2. 取消选中电子邮件枚举保护(推荐)

  2. 点击保存

Node.js

  1. 安装 Admin SDK

  2. 如需停用电子邮件枚举保护,请使用以下方法之一:

    • 如需在项目级提供保护,请执行以下操作:

      import { getAuth } from 'firebase-admin/auth';
      
      getAuth().projectConfigManager().updateProjectConfig(
        {
          emailPrivacyConfig: {
            enableImprovedEmailPrivacy: false,
          },
        }
      );
      
    • 如需在租户级别提供保护,请执行以下操作:

      import { getAuth } from 'firebase-admin/auth';
      
      getAuth().tenantConfigManager().updateTenant(TENANT_ID,
        {
          emailPrivacyConfig: {
            enableImprovedEmailPrivacy: false,
          },
        }
      );
      

      TENANT_ID 替换为您要为其停用电子邮件枚举保护的租户 ID。

REST

  1. 在 Google Cloud 控制台中,使用 gcloud auth print-access-token 命令输出项目 ID 的访问令牌:

    gcloud auth print-access-token --project=PROJECT_ID
    
  2. 使用 Identity Toolkit API 停用电子邮件枚举保护:

    curl -X PATCH -d "{'emailPrivacyConfig':{'enableImprovedEmailPrivacy':false}}" \
        -H 'Authorization: Bearer ACCESS_TOKEN' \
        -H 'Content-Type: application/json' -H 'X-Goog-User-Project: PROJECT_ID' \
        "https://identitytoolkit.googleapis.com/admin/v2/projects/PROJECT_ID/config?updateMask=emailPrivacyConfig"
    

替换以下内容:

  • ACCESS_TOKEN:您之前生成的访问令牌
  • PROJECT_ID:您的项目 ID

错误响应示例

如果用户尝试使用错误的电子邮件地址或密码登录,或者尝试使用系统中已存在的电子邮件地址注册,Identity Platform 会返回类似以下的错误:

{
"code": "auth/internal-error",
"message": "{\"error\":{\"code\":400,\"message\":\"INVALID_LOGIN_CREDENTIALS\",\"errors\":[{\"message\":\"INVALID_LOGIN_CREDENTIALS\",\"domain\":\"global\",\"reason\":\"invalid\"}]}}"
}