Skip to content

Commit eba2de3

Browse files
authored
Merge 89f01c0 into ebc694a
2 parents ebc694a + 89f01c0 commit eba2de3

File tree

12 files changed

+46
-18
lines changed

12 files changed

+46
-18
lines changed

.changeset/silly-islands-join.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@firebase/auth': patch
3+
---
4+
5+
Exposed INVALID_LOGIN_CREDENTIALS as auth/invalid-credential error and updated docs for various auth SDK methods.

common/api-review/auth.api.md

+1
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@ export const AuthErrorCodes: {
165165
readonly INVALID_EMAIL: "auth/invalid-email";
166166
readonly INVALID_EMULATOR_SCHEME: "auth/invalid-emulator-scheme";
167167
readonly INVALID_IDP_RESPONSE: "auth/invalid-credential";
168+
readonly INVALID_LOGIN_CREDENTIALS: "auth/invalid-credential";
168169
readonly INVALID_MESSAGE_PAYLOAD: "auth/invalid-message-payload";
169170
readonly INVALID_MFA_SESSION: "auth/invalid-multi-factor-session";
170171
readonly INVALID_OAUTH_CLIENT_ID: "auth/invalid-oauth-client-id";

docs-devsite/auth.md

+8-7
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,15 @@ Firebase Authentication
2828
| [confirmPasswordReset(auth, oobCode, newPassword)](./auth.md#confirmpasswordreset) | Completes the password reset process, given a confirmation code and new password. |
2929
| [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. |
3030
| [createUserWithEmailAndPassword(auth, email, password)](./auth.md#createuserwithemailandpassword) | Creates a new user account associated with the specified email address and password. |
31-
| [fetchSignInMethodsForEmail(auth, email)](./auth.md#fetchsigninmethodsforemail) | Gets the list of possible sign in methods for the given email address. |
31+
| [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. |
3232
| [getMultiFactorResolver(auth, error)](./auth.md#getmultifactorresolver) | Provides a [MultiFactorResolver](./auth.multifactorresolver.md#multifactorresolver_interface) suitable for completion of a multi-factor flow. |
3333
| [getRedirectResult(auth, resolver)](./auth.md#getredirectresult) | Returns a [UserCredential](./auth.usercredential.md#usercredential_interface) from the redirect-based sign-in flow. |
3434
| [initializeRecaptchaConfig(auth)](./auth.md#initializerecaptchaconfig) | Loads the reCAPTCHA configuration into the <code>Auth</code> instance. |
3535
| [isSignInWithEmailLink(auth, emailLink)](./auth.md#issigninwithemaillink) | Checks if an incoming link is a sign-in with email link suitable for [signInWithEmailLink()](./auth.md#signinwithemaillink)<!-- -->. |
3636
| [onAuthStateChanged(auth, nextOrObserver, error, completed)](./auth.md#onauthstatechanged) | Adds an observer for changes to the user's sign-in state. |
3737
| [onIdTokenChanged(auth, nextOrObserver, error, completed)](./auth.md#onidtokenchanged) | Adds an observer for changes to the signed-in user's ID token. |
3838
| [revokeAccessToken(auth, token)](./auth.md#revokeaccesstoken) | Revokes the given access token. Currently only supports Apple OAuth access tokens. |
39-
| [sendPasswordResetEmail(auth, email, actionCodeSettings)](./auth.md#sendpasswordresetemail) | Sends a password reset email to the given email address. |
39+
| [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 there's no user account with the given email address and \[Email Enumeration Protection\](https://cloud.google.com/identity-platform/docs/admin/email-enumeration-protection) is enabled. |
4040
| [sendSignInLinkToEmail(auth, email, actionCodeSettings)](./auth.md#sendsigninlinktoemail) | Sends a sign-in email link to the user with the specified email. |
4141
| [setPersistence(auth, persistence)](./auth.md#setpersistence) | Changes the type of persistence on the [Auth](./auth.auth.md#auth_interface) instance for the currently saved <code>Auth</code> session and applies this type of persistence for future sign-in requests, including sign-in with redirect requests. |
4242
| [signInAnonymously(auth)](./auth.md#signinanonymously) | Asynchronously signs in as an anonymous user. |
@@ -397,7 +397,7 @@ Promise&lt;[UserCredential](./auth.usercredential.md#usercredential_interface)<!
397397

398398
## fetchSignInMethodsForEmail()
399399

400-
Gets the list of possible sign in methods for the given email address.
400+
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.
401401

402402
This is useful to differentiate methods of sign-in for the same provider, eg. [EmailAuthProvider](./auth.emailauthprovider.md#emailauthprovider_class) which has 2 methods of sign-in, [SignInMethod](./auth.md#signinmethod)<!-- -->.EMAIL\_PASSWORD and [SignInMethod](./auth.md#signinmethod)<!-- -->.EMAIL\_LINK.
403403

@@ -412,7 +412,7 @@ export declare function fetchSignInMethodsForEmail(auth: Auth, email: string): P
412412
| Parameter | Type | Description |
413413
| --- | --- | --- |
414414
| auth | [Auth](./auth.auth.md#auth_interface) | The [Auth](./auth.auth.md#auth_interface) instance. |
415-
| email | string | The user's email address. |
415+
| email | string | The user's email address.<!-- -->Deprecated. Migrating off of this method is recommended as a security best-practice. Learn more in the Identity Platform documentation for \[Email Enumeration Protection\](https://cloud.google.com/identity-platform/docs/admin/email-enumeration-protection). |
416416

417417
<b>Returns:</b>
418418

@@ -622,7 +622,7 @@ Promise&lt;void&gt;
622622

623623
## sendPasswordResetEmail()
624624

625-
Sends a password reset email to the given email address.
625+
Sends a password reset email to the given email address. This method does not throw an error when there's no user account with the given email address and \[Email Enumeration Protection\](https://cloud.google.com/identity-platform/docs/admin/email-enumeration-protection) is enabled.
626626

627627
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.
628628

@@ -825,7 +825,7 @@ Promise&lt;[UserCredential](./auth.usercredential.md#usercredential_interface)<!
825825

826826
Asynchronously signs in using an email and password.
827827

828-
Fails with an error if the email address and password do not match.
828+
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.
829829

830830
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 the user's account in your Firebase project. See also: [createUserWithEmailAndPassword()](./auth.md#createuserwithemailandpassword)<!-- -->.
831831

@@ -1633,7 +1633,7 @@ export declare function updateEmail(user: User, newEmail: string): Promise<void>
16331633
| Parameter | Type | Description |
16341634
| --- | --- | --- |
16351635
| user | [User](./auth.user.md#user_interface) | The user. |
1636-
| newEmail | string | The new email address. |
1636+
| 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. |
16371637

16381638
<b>Returns:</b>
16391639

@@ -1851,6 +1851,7 @@ AUTH_ERROR_CODES_MAP_DO_NOT_USE_INTERNALLY: {
18511851
readonly INVALID_EMAIL: "auth/invalid-email";
18521852
readonly INVALID_EMULATOR_SCHEME: "auth/invalid-emulator-scheme";
18531853
readonly INVALID_IDP_RESPONSE: "auth/invalid-credential";
1854+
readonly INVALID_LOGIN_CREDENTIALS: "auth/invalid-credential";
18541855
readonly INVALID_MESSAGE_PAYLOAD: "auth/invalid-message-payload";
18551856
readonly INVALID_MFA_SESSION: "auth/invalid-multi-factor-session";
18561857
readonly INVALID_OAUTH_CLIENT_ID: "auth/invalid-oauth-client-id";

packages/auth/demo/src/index.js

+5
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,11 @@ function onAuthError(error) {
317317
if (error.code === 'auth/user-token-expired') {
318318
alertError('Token expired, please reauthenticate.');
319319
}
320+
if (error.code === 'auth/invalid-credential') {
321+
alertError(
322+
'Login credentials invalid. It is possible that the email/password combination does not exist.'
323+
);
324+
}
320325
}
321326
}
322327

packages/auth/src/api/authentication/idp.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ describe('api/authentication/signInWithIdp', () => {
8383

8484
await expect(signInWithIdp(auth, request)).to.be.rejectedWith(
8585
FirebaseError,
86-
'Firebase: The supplied auth credential is malformed or has expired. (auth/invalid-credential).'
86+
'Firebase: The supplied auth credential is incorrect, malformed or has expired. (auth/invalid-credential).'
8787
);
8888
expect(mock.calls[0].request).to.eql(request);
8989
});

packages/auth/src/api/authentication/mfa.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ describe('api/authentication/startSignInPhoneMfa', () => {
8585

8686
await expect(startSignInPhoneMfa(auth, request)).to.be.rejectedWith(
8787
FirebaseError,
88-
'Firebase: The supplied auth credential is malformed or has expired. (auth/invalid-credential).'
88+
'Firebase: The supplied auth credential is incorrect, malformed or has expired. (auth/invalid-credential).'
8989
);
9090
expect(mock.calls[0].request).to.eql(request);
9191
});

packages/auth/src/api/authentication/token.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ describe('api/authentication/revokeToken', () => {
199199

200200
await expect(revokeToken(auth, request)).to.be.rejectedWith(
201201
FirebaseError,
202-
'Firebase: The supplied auth credential is malformed or has expired. (auth/invalid-credential).'
202+
'Firebase: The supplied auth credential is incorrect, malformed or has expired. (auth/invalid-credential).'
203203
);
204204
expect(mock.calls[0].request).to.eql(request);
205205
});

packages/auth/src/api/errors.ts

+7-3
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ export const enum ServerError {
4444
INVALID_ID_TOKEN = 'INVALID_ID_TOKEN',
4545
INVALID_IDP_RESPONSE = 'INVALID_IDP_RESPONSE',
4646
INVALID_IDENTIFIER = 'INVALID_IDENTIFIER',
47+
INVALID_LOGIN_CREDENTIALS = 'INVALID_LOGIN_CREDENTIALS',
4748
INVALID_MESSAGE_PAYLOAD = 'INVALID_MESSAGE_PAYLOAD',
4849
INVALID_MFA_PENDING_CREDENTIAL = 'INVALID_MFA_PENDING_CREDENTIAL',
4950
INVALID_OAUTH_CLIENT_ID = 'INVALID_OAUTH_CLIENT_ID',
@@ -144,14 +145,17 @@ export const SERVER_ERROR_MAP: Partial<ServerErrorMap<ServerError>> = {
144145
[ServerError.INVALID_PASSWORD]: AuthErrorCode.INVALID_PASSWORD,
145146
// This can only happen if the SDK sends a bad request.
146147
[ServerError.MISSING_PASSWORD]: AuthErrorCode.MISSING_PASSWORD,
148+
// Thrown if Email Enumeration Protection is enabled in the project and the email or password is
149+
// invalid.
150+
[ServerError.INVALID_LOGIN_CREDENTIALS]: AuthErrorCode.INVALID_CREDENTIAL,
147151

148152
// Sign up with email and password errors.
149153
[ServerError.EMAIL_EXISTS]: AuthErrorCode.EMAIL_EXISTS,
150154
[ServerError.PASSWORD_LOGIN_DISABLED]: AuthErrorCode.OPERATION_NOT_ALLOWED,
151155

152156
// Verify assertion for sign in with credential errors:
153-
[ServerError.INVALID_IDP_RESPONSE]: AuthErrorCode.INVALID_IDP_RESPONSE,
154-
[ServerError.INVALID_PENDING_TOKEN]: AuthErrorCode.INVALID_IDP_RESPONSE,
157+
[ServerError.INVALID_IDP_RESPONSE]: AuthErrorCode.INVALID_CREDENTIAL,
158+
[ServerError.INVALID_PENDING_TOKEN]: AuthErrorCode.INVALID_CREDENTIAL,
155159
[ServerError.FEDERATED_USER_ID_ALREADY_LINKED]:
156160
AuthErrorCode.CREDENTIAL_ALREADY_IN_USE,
157161

@@ -184,7 +188,7 @@ export const SERVER_ERROR_MAP: Partial<ServerErrorMap<ServerError>> = {
184188
// Phone Auth related errors.
185189
[ServerError.INVALID_CODE]: AuthErrorCode.INVALID_CODE,
186190
[ServerError.INVALID_SESSION_INFO]: AuthErrorCode.INVALID_SESSION_INFO,
187-
[ServerError.INVALID_TEMPORARY_PROOF]: AuthErrorCode.INVALID_IDP_RESPONSE,
191+
[ServerError.INVALID_TEMPORARY_PROOF]: AuthErrorCode.INVALID_CREDENTIAL,
188192
[ServerError.MISSING_SESSION_INFO]: AuthErrorCode.MISSING_SESSION_INFO,
189193
[ServerError.SESSION_EXPIRED]: AuthErrorCode.CODE_EXPIRED,
190194

packages/auth/src/core/errors.ts

+4-3
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ export const enum AuthErrorCode {
6060
INVALID_DYNAMIC_LINK_DOMAIN = 'invalid-dynamic-link-domain',
6161
INVALID_EMAIL = 'invalid-email',
6262
INVALID_EMULATOR_SCHEME = 'invalid-emulator-scheme',
63-
INVALID_IDP_RESPONSE = 'invalid-credential',
63+
INVALID_CREDENTIAL = 'invalid-credential',
6464
INVALID_MESSAGE_PAYLOAD = 'invalid-message-payload',
6565
INVALID_MFA_SESSION = 'invalid-multi-factor-session',
6666
INVALID_OAUTH_CLIENT_ID = 'invalid-oauth-client-id',
@@ -217,8 +217,8 @@ function _debugErrorMap(): ErrorMap<AuthErrorCode> {
217217
'Your API key is invalid, please check you have copied it correctly.',
218218
[AuthErrorCode.INVALID_CERT_HASH]:
219219
'The SHA-1 certificate hash provided is invalid.',
220-
[AuthErrorCode.INVALID_IDP_RESPONSE]:
221-
'The supplied auth credential is malformed or has expired.',
220+
[AuthErrorCode.INVALID_CREDENTIAL]:
221+
'The supplied auth credential is incorrect, malformed or has expired.',
222222
[AuthErrorCode.INVALID_MESSAGE_PAYLOAD]:
223223
'The email template corresponding to this action contains invalid characters in its message. ' +
224224
'Please fix by going to the Auth email templates section in the Firebase Console.',
@@ -528,6 +528,7 @@ export const AUTH_ERROR_CODES_MAP_DO_NOT_USE_INTERNALLY = {
528528
INVALID_EMAIL: 'auth/invalid-email',
529529
INVALID_EMULATOR_SCHEME: 'auth/invalid-emulator-scheme',
530530
INVALID_IDP_RESPONSE: 'auth/invalid-credential',
531+
INVALID_LOGIN_CREDENTIALS: 'auth/invalid-credential',
531532
INVALID_MESSAGE_PAYLOAD: 'auth/invalid-message-payload',
532533
INVALID_MFA_SESSION: 'auth/invalid-multi-factor-session',
533534
INVALID_OAUTH_CLIENT_ID: 'auth/invalid-oauth-client-id',

packages/auth/src/core/strategies/email.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,9 @@ import { _setActionCodeSettingsOnRequest } from './action_code_settings';
3333
import { getModularInstance } from '@firebase/util';
3434

3535
/**
36-
* Gets the list of possible sign in methods for the given email address.
36+
* Gets the list of possible sign in methods for the given email address. This method returns an
37+
* empty list when [Email Enumeration Protection](https://cloud.google.com/identity-platform/docs/admin/email-enumeration-protection) is enabled, irrespective of the number of
38+
* authentication methods available for the given email.
3739
*
3840
* @remarks
3941
* This is useful to differentiate methods of sign-in for the same provider, eg.
@@ -44,6 +46,8 @@ import { getModularInstance } from '@firebase/util';
4446
* @param auth - The {@link Auth} instance.
4547
* @param email - The user's email address.
4648
*
49+
* Deprecated. Migrating off of this method is recommended as a security best-practice.
50+
* Learn more in the Identity Platform documentation for [Email Enumeration Protection](https://cloud.google.com/identity-platform/docs/admin/email-enumeration-protection).
4751
* @public
4852
*/
4953
export async function fetchSignInMethodsForEmail(

packages/auth/src/core/strategies/email_and_password.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,9 @@ async function recachePasswordPolicy(auth: Auth): Promise<void> {
6161
}
6262

6363
/**
64-
* Sends a password reset email to the given email address.
64+
* Sends a password reset email to the given email address. This method does not throw an error when
65+
* there's no user account with the given email address and
66+
* [Email Enumeration Protection](https://cloud.google.com/identity-platform/docs/admin/email-enumeration-protection) is enabled.
6567
*
6668
* @remarks
6769
* To complete the password reset, call {@link confirmPasswordReset} with the code supplied in
@@ -303,6 +305,8 @@ export async function createUserWithEmailAndPassword(
303305
*
304306
* @remarks
305307
* Fails with an error if the email address and password do not match.
308+
* When [Email Enumeration Protection](https://cloud.google.com/identity-platform/docs/admin/email-enumeration-protection) is enabled,
309+
* this method fails with "auth/invalid-credential" in case of an invalid email/password.
306310
*
307311
* Note: The user's password is NOT the password used to access the user's email account. The
308312
* email address serves as a unique identifier for the user, and the password is used to access

packages/auth/src/core/user/account_info.ts

+3
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,9 @@ export async function updateProfile(
8888
* @param user - The user.
8989
* @param newEmail - The new email address.
9090
*
91+
* Throws "auth/operation-not-allowed" error when [Email Enumeration Protection](https://cloud.google.com/identity-platform/docs/admin/email-enumeration-protection) is enabled.
92+
* Deprecated - Use {@link verifyBeforeUpdateEmail} instead.
93+
*
9194
* @public
9295
*/
9396
export function updateEmail(user: User, newEmail: string): Promise<void> {

0 commit comments

Comments
 (0)