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_FOUND
error.An attempt is made to sign up with an email address that already exists in the system. Identity Platform returns an
EMAIL_EXISTS
error.
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
fetchSignInForEmail
API 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
createAuthUri
REST API or thefetchSignInMethodsForEmail
client 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
update
REST API, thesetAccountInfo
REST API, or theupdateEmail
client SDK method on all platforms.You can use
verifyBeforeUpdateEmail
for Web and Android orsendEmailVerification(beforeUpdatingEmail:)
for iOS instead.You can no longer use the
setAccountInfo
REST API to link an email/password provider to an existing user account. You can no longer use thelinkWithCredential
client SDK method with anEmailAuthCredential
on any platform. Use the REST APIsignUp
instead, passing the user's ID token in theidToken
field and theemail
,password
fields to link.Removes error responses for email verification flows, such as those initiated by calling the
sendOobCode
REST API with request typesVERIFY_AND_CHANGE_EMAIL
orPASSWORD_RESET
, and when callingverifyBeforeUpdateEmail
for Web and Android,sendEmailVerification(beforeUpdatingEmail:)
for iOS, orsendPasswordResetEmail
client SDK methods on 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 do not allow users to sign up without an email verification flow.
Invalid sign-in cases return an
INVALID_LOGIN_CREDENTIALS
error response. Invalid sign-up cases continue to returnEMAIL_EXISTS
errors—see the recommendations in the next section.
If your app relies on any of the behaviors changed by email enumeration protection, you can currently 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 Firebase Auth Settings page.
In the navigation 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_ID
with 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-token
command:gcloud auth print-access-token --project=PROJECT_ID
Enable 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 Firebase Auth Settings page.
In the navigation 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_ID
with 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-token
command:gcloud auth print-access-token --project=PROJECT_ID
Disable 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\"}]}}"
}