diff --git a/.changeset/tall-bottles-promise.md b/.changeset/tall-bottles-promise.md
new file mode 100644
index 00000000000..cb7084916ba
--- /dev/null
+++ b/.changeset/tall-bottles-promise.md
@@ -0,0 +1,5 @@
+---
+'@firebase/auth': patch
+---
+
+Exposed INVALID_LOGIN_CREDENTIALS as auth/invalid-login-credentials error and updated docs for various auth SDK methods.
diff --git a/common/api-review/auth.api.md b/common/api-review/auth.api.md
index 0b1e7d0fb76..c34d5793e80 100644
--- a/common/api-review/auth.api.md
+++ b/common/api-review/auth.api.md
@@ -165,6 +165,7 @@ export const AuthErrorCodes: {
readonly INVALID_EMAIL: "auth/invalid-email";
readonly INVALID_EMULATOR_SCHEME: "auth/invalid-emulator-scheme";
readonly INVALID_IDP_RESPONSE: "auth/invalid-credential";
+ readonly INVALID_LOGIN_CREDENTIALS: "auth/invalid-login-credentials";
readonly INVALID_MESSAGE_PAYLOAD: "auth/invalid-message-payload";
readonly INVALID_MFA_SESSION: "auth/invalid-multi-factor-session";
readonly INVALID_OAUTH_CLIENT_ID: "auth/invalid-oauth-client-id";
diff --git a/docs-devsite/auth.md b/docs-devsite/auth.md
index 684e81eee07..93519c81b87 100644
--- a/docs-devsite/auth.md
+++ b/docs-devsite/auth.md
@@ -28,7 +28,7 @@ Firebase Authentication
| [confirmPasswordReset(auth, oobCode, newPassword)](./auth.md#confirmpasswordreset) | Completes the password reset process, given a confirmation code and new password. |
| [connectAuthEmulator(auth, url, options)](./auth.md#connectauthemulator) | Changes the [Auth](./auth.auth.md#auth_interface) instance to communicate with the Firebase Auth Emulator, instead of production Firebase Auth services. |
| [createUserWithEmailAndPassword(auth, email, password)](./auth.md#createuserwithemailandpassword) | Creates a new user account associated with the specified email address and password. |
-| [fetchSignInMethodsForEmail(auth, email)](./auth.md#fetchsigninmethodsforemail) | Gets the list of possible sign in methods for the given email address. |
+| [fetchSignInMethodsForEmail(auth, email)](./auth.md#fetchsigninmethodsforemail) | Gets the list of possible sign in methods for the given email address. This method returns an empty list when \[Email Enumeration Protection\](https://cloud.google.com/identity-platform/docs/admin/email-enumeration-protection) is enabled, irrespective of the number of authentication methods available for the given email. |
| [getMultiFactorResolver(auth, error)](./auth.md#getmultifactorresolver) | Provides a [MultiFactorResolver](./auth.multifactorresolver.md#multifactorresolver_interface) suitable for completion of a multi-factor flow. |
| [getRedirectResult(auth, resolver)](./auth.md#getredirectresult) | Returns a [UserCredential](./auth.usercredential.md#usercredential_interface) from the redirect-based sign-in flow. |
| [initializeRecaptchaConfig(auth)](./auth.md#initializerecaptchaconfig) | Loads the reCAPTCHA configuration into the Auth
instance. |
@@ -36,7 +36,7 @@ Firebase Authentication
| [onAuthStateChanged(auth, nextOrObserver, error, completed)](./auth.md#onauthstatechanged) | Adds an observer for changes to the user's sign-in state. |
| [onIdTokenChanged(auth, nextOrObserver, error, completed)](./auth.md#onidtokenchanged) | Adds an observer for changes to the signed-in user's ID token. |
| [revokeAccessToken(auth, token)](./auth.md#revokeaccesstoken) | Revokes the given access token. Currently only supports Apple OAuth access tokens. |
-| [sendPasswordResetEmail(auth, email, actionCodeSettings)](./auth.md#sendpasswordresetemail) | Sends a password reset email to the given email address. |
+| [sendPasswordResetEmail(auth, email, actionCodeSettings)](./auth.md#sendpasswordresetemail) | Sends a password reset email to the given email address. This method does not throw an error when \[Email Enumeration Protection\](https://cloud.google.com/identity-platform/docs/admin/email-enumeration-protection) is enabled. |
| [sendSignInLinkToEmail(auth, email, actionCodeSettings)](./auth.md#sendsigninlinktoemail) | Sends a sign-in email link to the user with the specified email. |
| [setPersistence(auth, persistence)](./auth.md#setpersistence) | Changes the type of persistence on the [Auth](./auth.auth.md#auth_interface) instance for the currently saved Auth
session and applies this type of persistence for future sign-in requests, including sign-in with redirect requests. |
| [signInAnonymously(auth)](./auth.md#signinanonymously) | Asynchronously signs in as an anonymous user. |
@@ -397,7 +397,7 @@ Promise<[UserCredential](./auth.usercredential.md#usercredential_interface).EMAIL\_PASSWORD and [SignInMethod](./auth.md#signinmethod).EMAIL\_LINK.
@@ -412,7 +412,7 @@ export declare function fetchSignInMethodsForEmail(auth: Auth, email: string): P
| Parameter | Type | Description |
| --- | --- | --- |
| auth | [Auth](./auth.auth.md#auth_interface) | The [Auth](./auth.auth.md#auth_interface) instance. |
-| email | string | The user's email address. |
+| email | string | The user's email address.Deprecated Migrating off of this method is recommended as a security best-practice. |
Returns:
@@ -622,7 +622,7 @@ Promise<void>
## sendPasswordResetEmail()
-Sends a password reset email to the given email address.
+Sends a password reset email to the given email address. This method does not throw an error when \[Email Enumeration Protection\](https://cloud.google.com/identity-platform/docs/admin/email-enumeration-protection) is enabled.
To complete the password reset, call [confirmPasswordReset()](./auth.md#confirmpasswordreset) with the code supplied in the email sent to the user, along with the new password specified by the user.
@@ -825,7 +825,7 @@ Promise<[UserCredential](./auth.usercredential.md#usercredential_interface).
@@ -1633,7 +1633,7 @@ export declare function updateEmail(user: User, newEmail: string): Promise
| Parameter | Type | Description |
| --- | --- | --- |
| user | [User](./auth.user.md#user_interface) | The user. |
-| newEmail | string | The new email address. |
+| newEmail | string | The new email address.Throws "auth/operation-not-allowed" error when \[Email Enumeration Protection\](https://cloud.google.com/identity-platform/docs/admin/email-enumeration-protection) is enabled. Deprecated - Use [verifyBeforeUpdateEmail()](./auth.md#verifybeforeupdateemail) instead. |
Returns:
@@ -1851,6 +1851,7 @@ AUTH_ERROR_CODES_MAP_DO_NOT_USE_INTERNALLY: {
readonly INVALID_EMAIL: "auth/invalid-email";
readonly INVALID_EMULATOR_SCHEME: "auth/invalid-emulator-scheme";
readonly INVALID_IDP_RESPONSE: "auth/invalid-credential";
+ readonly INVALID_LOGIN_CREDENTIALS: "auth/invalid-login-credentials";
readonly INVALID_MESSAGE_PAYLOAD: "auth/invalid-message-payload";
readonly INVALID_MFA_SESSION: "auth/invalid-multi-factor-session";
readonly INVALID_OAUTH_CLIENT_ID: "auth/invalid-oauth-client-id";
diff --git a/packages/auth/demo/src/index.js b/packages/auth/demo/src/index.js
index 48aeb07d380..a053a4a9149 100644
--- a/packages/auth/demo/src/index.js
+++ b/packages/auth/demo/src/index.js
@@ -317,6 +317,11 @@ function onAuthError(error) {
if (error.code === 'auth/user-token-expired') {
alertError('Token expired, please reauthenticate.');
}
+ if (error.code === 'auth/invalid-login-credentials') {
+ alertError(
+ 'login credentials invalid. It is possible that the email/password combination does not exist.'
+ );
+ }
}
}
diff --git a/packages/auth/src/api/errors.ts b/packages/auth/src/api/errors.ts
index d2f07ca6e27..28f877088ae 100644
--- a/packages/auth/src/api/errors.ts
+++ b/packages/auth/src/api/errors.ts
@@ -44,6 +44,7 @@ export const enum ServerError {
INVALID_ID_TOKEN = 'INVALID_ID_TOKEN',
INVALID_IDP_RESPONSE = 'INVALID_IDP_RESPONSE',
INVALID_IDENTIFIER = 'INVALID_IDENTIFIER',
+ INVALID_LOGIN_CREDENTIALS = 'INVALID_LOGIN_CREDENTIALS',
INVALID_MESSAGE_PAYLOAD = 'INVALID_MESSAGE_PAYLOAD',
INVALID_MFA_PENDING_CREDENTIAL = 'INVALID_MFA_PENDING_CREDENTIAL',
INVALID_OAUTH_CLIENT_ID = 'INVALID_OAUTH_CLIENT_ID',
@@ -144,6 +145,10 @@ export const SERVER_ERROR_MAP: Partial> = {
[ServerError.INVALID_PASSWORD]: AuthErrorCode.INVALID_PASSWORD,
// This can only happen if the SDK sends a bad request.
[ServerError.MISSING_PASSWORD]: AuthErrorCode.MISSING_PASSWORD,
+ // Thrown if Email Enumeration Protection is enabled in the project and the email or password is
+ // invalid.
+ [ServerError.INVALID_LOGIN_CREDENTIALS]:
+ AuthErrorCode.INVALID_LOGIN_CREDENTIALS,
// Sign up with email and password errors.
[ServerError.EMAIL_EXISTS]: AuthErrorCode.EMAIL_EXISTS,
diff --git a/packages/auth/src/core/errors.ts b/packages/auth/src/core/errors.ts
index 586a33d3d34..f2fd27d1624 100644
--- a/packages/auth/src/core/errors.ts
+++ b/packages/auth/src/core/errors.ts
@@ -61,6 +61,7 @@ export const enum AuthErrorCode {
INVALID_EMAIL = 'invalid-email',
INVALID_EMULATOR_SCHEME = 'invalid-emulator-scheme',
INVALID_IDP_RESPONSE = 'invalid-credential',
+ INVALID_LOGIN_CREDENTIALS = 'invalid-login-credentials',
INVALID_MESSAGE_PAYLOAD = 'invalid-message-payload',
INVALID_MFA_SESSION = 'invalid-multi-factor-session',
INVALID_OAUTH_CLIENT_ID = 'invalid-oauth-client-id',
@@ -219,6 +220,8 @@ function _debugErrorMap(): ErrorMap {
'The SHA-1 certificate hash provided is invalid.',
[AuthErrorCode.INVALID_IDP_RESPONSE]:
'The supplied auth credential is malformed or has expired.',
+ [AuthErrorCode.INVALID_LOGIN_CREDENTIALS]:
+ 'The supplied login credentials are invalid.',
[AuthErrorCode.INVALID_MESSAGE_PAYLOAD]:
'The email template corresponding to this action contains invalid characters in its message. ' +
'Please fix by going to the Auth email templates section in the Firebase Console.',
@@ -528,6 +531,7 @@ export const AUTH_ERROR_CODES_MAP_DO_NOT_USE_INTERNALLY = {
INVALID_EMAIL: 'auth/invalid-email',
INVALID_EMULATOR_SCHEME: 'auth/invalid-emulator-scheme',
INVALID_IDP_RESPONSE: 'auth/invalid-credential',
+ INVALID_LOGIN_CREDENTIALS: 'auth/invalid-login-credentials',
INVALID_MESSAGE_PAYLOAD: 'auth/invalid-message-payload',
INVALID_MFA_SESSION: 'auth/invalid-multi-factor-session',
INVALID_OAUTH_CLIENT_ID: 'auth/invalid-oauth-client-id',
diff --git a/packages/auth/src/core/strategies/email.ts b/packages/auth/src/core/strategies/email.ts
index 43d3804eace..27c34124f58 100644
--- a/packages/auth/src/core/strategies/email.ts
+++ b/packages/auth/src/core/strategies/email.ts
@@ -33,7 +33,9 @@ import { _setActionCodeSettingsOnRequest } from './action_code_settings';
import { getModularInstance } from '@firebase/util';
/**
- * Gets the list of possible sign in methods for the given email address.
+ * Gets the list of possible sign in methods for the given email address. This method returns an
+ * empty list when [Email Enumeration Protection](https://cloud.google.com/identity-platform/docs/admin/email-enumeration-protection) is enabled, irrespective of the number of
+ * authentication methods available for the given email.
*
* @remarks
* This is useful to differentiate methods of sign-in for the same provider, eg.
@@ -44,6 +46,7 @@ import { getModularInstance } from '@firebase/util';
* @param auth - The {@link Auth} instance.
* @param email - The user's email address.
*
+ * Deprecated Migrating off of this method is recommended as a security best-practice.
* @public
*/
export async function fetchSignInMethodsForEmail(
diff --git a/packages/auth/src/core/strategies/email_and_password.ts b/packages/auth/src/core/strategies/email_and_password.ts
index 0ff21810a49..8e965d32f7e 100644
--- a/packages/auth/src/core/strategies/email_and_password.ts
+++ b/packages/auth/src/core/strategies/email_and_password.ts
@@ -61,7 +61,8 @@ async function recachePasswordPolicy(auth: Auth): Promise {
}
/**
- * Sends a password reset email to the given email address.
+ * Sends a password reset email to the given email address. This method does not throw an error when
+ * [Email Enumeration Protection](https://cloud.google.com/identity-platform/docs/admin/email-enumeration-protection) is enabled.
*
* @remarks
* To complete the password reset, call {@link confirmPasswordReset} with the code supplied in
@@ -303,6 +304,8 @@ export async function createUserWithEmailAndPassword(
*
* @remarks
* Fails with an error if the email address and password do not match.
+ * When [Email Enumeration Protection](https://cloud.google.com/identity-platform/docs/admin/email-enumeration-protection) is enabled,
+ * this method fails with "auth/invalid-credential" in case of an invalid email/password.
*
* Note: The user's password is NOT the password used to access the user's email account. The
* email address serves as a unique identifier for the user, and the password is used to access
diff --git a/packages/auth/src/core/user/account_info.ts b/packages/auth/src/core/user/account_info.ts
index 460ba7d3ed3..3f061630435 100644
--- a/packages/auth/src/core/user/account_info.ts
+++ b/packages/auth/src/core/user/account_info.ts
@@ -88,6 +88,9 @@ export async function updateProfile(
* @param user - The user.
* @param newEmail - The new email address.
*
+ * Throws "auth/operation-not-allowed" error when [Email Enumeration Protection](https://cloud.google.com/identity-platform/docs/admin/email-enumeration-protection) is enabled.
+ * Deprecated - Use {@link verifyBeforeUpdateEmail} instead.
+ *
* @public
*/
export function updateEmail(user: User, newEmail: string): Promise {