Enable or disable email enumeration protection
This guide explains the email enumeration protection feature and shows you how to enable and disable it. If you created your project on or after September 15, 2023, email enumeration protection is enabled by default.
Overview
Email enumeration is a type of brute-force attack in which a malicious actor attempts to guess or confirm users in a system by passing an email address to the API and checking the response.
Without email enumeration protection, Identity Platform returns information that can be used in an email enumeration attack:
An attempt is made to sign in with an email address that doesn't exist in the system. Identity Platform returns an
EMAIL_NOT_FOUNDerror.An attempt is made to sign up with an email address that already exists in the system. Identity Platform returns an
EMAIL_EXISTSerror.
You can use Identity Platform's email enumeration protection feature to protect user accounts in your app from these attacks.
When email enumeration protection is enabled, your project has the following behavior:
The
fetchSignInForEmailAPI will fail. Linking anonymous authenticated users with an email address will also not work prior to SDK version 22.3.0 for Android, 10.18.0 for iOS, and 10.6.0 for Web.A list of sign-in methods for a specified email address is no longer returned when calling the
createAuthUriREST API or thefetchSignInMethodsForEmailclient SDK method on all platforms.Users cannot change their email address without first verifying the new address. For example, you can no longer change a user's email address with the
updateREST API, thesetAccountInfoREST API, or theupdateEmailclient SDK method on all platforms.You can use
verifyBeforeUpdateEmailfor Web and Android orsendEmailVerification(beforeUpdatingEmail:)for iOS instead.You can no longer use the
setAccountInfoREST API to link an email/password provider to an existing user account. You can no longer use thelinkWithCredentialclient SDK method with anEmailAuthCredentialon any platform. Use the REST APIsignUpinstead, passing the user's ID token in theidTokenfield and theemail,passwordfields to link.Removes error responses for email verification flows, including flows that were initiated by calling the
sendOobCodeREST API with theVERIFY_AND_CHANGE_EMAILorPASSWORD_RESETrequest types, and by callingverifyBeforeUpdateEmailfor Web and Android,sendEmailVerification(beforeUpdatingEmail:)for iOS, orsendPasswordResetEmailon all platforms.When you make a password reset request, a verification email is sent only if the email address exists; when you make an email address change request, a verification email is sent only if the email address doesn't already exist. In both cases, there are no specific error messages indicating when emails aren't sent.
We recommend that you don't allow users to sign up without an email verification flow.
Invalid sign-in cases return an
INVALID_LOGIN_CREDENTIALSerror response. Invalid sign-up cases continue to returnEMAIL_EXISTSerrors—see the recommendations in the next section.
If your app relies on any of the behaviors changed by email enumeration protection, you can disable it. However, this is not recommended in the long term; see the following section.
Security recommendations
One of the most common methods to perform an account takeover attack is to perform credential-stuffing attacks using credentials that are leaked or easy to guess. Email enumeration can also be used to gain sensitive information about your users, or to perform phishing attacks against them. For these reasons, Google advises using the email enumeration protection feature to protect your apps against such attacks.
If you created your project on or after September 15, 2023, email enumeration protection is enabled by default. We recommend that you leave email enumeration protection enabled and refrain from relying on any of the behaviors listed earlier in this guide.
If you created your project before September 15, 2023, email enumeration protection is not automatically enabled.
If your apps don't rely on any of the behaviors described earlier in this guide, we recommend that you enable email enumeration protection immediately.
If your apps rely on any of the behaviors described earlier, we recommend that you begin migrating away from doing so, and enable email enumeration protection as soon as you can.
In addition to using email enumeration protection, consider taking measures to
prevent abuse of your project's sign-up endpoints that continue to return
EMAIL_EXISTS errors. The following are some ways to do so:
- Enable App Check.
- Integrate reCAPTCHA into your sign-up flow.
- Disallow signing in with email addresses and passwords or email links, and use alternative methods, such as Google Sign-in, instead.
Enable email enumeration protection
To enable email enumeration protection, follow these steps:
Firebase console
In the Firebase console, go to the Authentication Settings page.
In the User account management pane, select User actions.
Select Email enumeration protection (recommended).
Click Save.
Node.js
Install the Admin SDK.
To enable email enumeration protection, use one of the following:
For protection at the project level:
import { getAuth } from 'firebase-admin/auth'; getAuth().projectConfigManager().updateProjectConfig( { emailPrivacyConfig: { enableImprovedEmailPrivacy: true, }, } );For protection at the tenant level:
import { getAuth } from 'firebase-admin/auth'; getAuth().tenantConfigManager().updateTenant(TENANT_ID, { emailPrivacyConfig: { enableImprovedEmailPrivacy: true, }, } );Replace
TENANT_IDwith the tenant ID that you want to enable email enumeration protection for.
REST
In the Google Cloud console, print an access token for your project ID using the
gcloud auth print-access-tokencommand:gcloud auth print-access-token --project=PROJECT_IDEnable email enumeration protection for your project ID using the Identity Toolkit API:
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"
Replace the following:
- ACCESS_TOKEN: the access token you generated earlier
- PROJECT_ID: your project ID
Disable email enumeration protection
To disable email enumeration protection, follow these steps:
Firebase console
In the Firebase console, go to the Authentication Settings page.
In the User account management pane, select User actions.
Clear Email enumeration protection (recommended).
Click Save.
Node.js
Install the Admin SDK.
To disable email enumeration protection, use one of the following:
For protection at the project level:
import { getAuth } from 'firebase-admin/auth'; getAuth().projectConfigManager().updateProjectConfig( { emailPrivacyConfig: { enableImprovedEmailPrivacy: false, }, } );For protection at the tenant level:
import { getAuth } from 'firebase-admin/auth'; getAuth().tenantConfigManager().updateTenant(TENANT_ID, { emailPrivacyConfig: { enableImprovedEmailPrivacy: false, }, } );Replace
TENANT_IDwith the tenant ID that you want to disable email enumeration protection for.
REST
In the Google Cloud console, print an access token for your project ID using
gcloud auth print-access-tokencommand:gcloud auth print-access-token --project=PROJECT_IDDisable email enumeration protection using the 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"
Replace the following:
- ACCESS_TOKEN: the access token you generated earlier
- PROJECT_ID: your project ID
Example of an error response
If a user attempts to sign in with an incorrect email address or password, or attempts to sign up with an email address that already exists in the system, Identity Platform returns an error similar to the following:
{
"code": "auth/internal-error",
"message": "{\"error\":{\"code\":400,\"message\":\"INVALID_LOGIN_CREDENTIALS\",\"errors\":[{\"message\":\"INVALID_LOGIN_CREDENTIALS\",\"domain\":\"global\",\"reason\":\"invalid\"}]}}"
}