@react-native-firebase/auth 23.6.0 → 23.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -3,6 +3,16 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [23.8.0](https://github.com/invertase/react-native-firebase/compare/v23.7.0...v23.8.0) (2026-01-13)
7
+
8
+ **Note:** Version bump only for package @react-native-firebase/auth
9
+
10
+ ## [23.7.0](https://github.com/invertase/react-native-firebase/compare/v23.6.0...v23.7.0) (2025-12-08)
11
+
12
+ ### Features
13
+
14
+ - **auth:** cache password policy per-app in validatePassword ([cc29117](https://github.com/invertase/react-native-firebase/commit/cc291171e076d00dfde1fef9d03242379e567af4))
15
+
6
16
  ## [23.6.0](https://github.com/invertase/react-native-firebase/compare/v23.5.0...v23.6.0) (2025-12-08)
7
17
 
8
18
  ### Bug Fixes
package/lib/index.d.ts CHANGED
@@ -468,6 +468,7 @@ export namespace FirebaseAuthTypes {
468
468
  * A PhoneMultiFactorGenerator interface.
469
469
  */
470
470
  PhoneMultiFactorGenerator: PhoneMultiFactorGenerator;
471
+ SDK_VERSION: string;
471
472
  }
472
473
 
473
474
  /**
@@ -1647,6 +1648,11 @@ export namespace FirebaseAuthTypes {
1647
1648
  * TODO @salakar missing updateCurrentUser
1648
1649
  */
1649
1650
  export class Module extends FirebaseModule {
1651
+ /**
1652
+ * The current `FirebaseApp` instance for this Firebase service.
1653
+ */
1654
+ app: ReactNativeFirebase.FirebaseApp;
1655
+
1650
1656
  /**
1651
1657
  * Returns the current tenant Id or null if it has never been set
1652
1658
  *
@@ -2295,10 +2301,19 @@ export namespace FirebaseAuthTypes {
2295
2301
 
2296
2302
  export type CallbackOrObserver<T extends (...args: any[]) => any> = T | { next: T };
2297
2303
 
2298
- declare const defaultExport: ReactNativeFirebase.FirebaseModuleWithStaticsAndApp<
2304
+ type AuthNamespace = ReactNativeFirebase.FirebaseModuleWithStaticsAndApp<
2299
2305
  FirebaseAuthTypes.Module,
2300
2306
  FirebaseAuthTypes.Statics
2301
- >;
2307
+ > & {
2308
+ auth: ReactNativeFirebase.FirebaseModuleWithStaticsAndApp<
2309
+ FirebaseAuthTypes.Module,
2310
+ FirebaseAuthTypes.Statics
2311
+ >;
2312
+ firebase: ReactNativeFirebase.Module;
2313
+ app(name?: string): ReactNativeFirebase.FirebaseApp;
2314
+ };
2315
+
2316
+ declare const defaultExport: AuthNamespace;
2302
2317
 
2303
2318
  export const firebase: ReactNativeFirebase.Module & {
2304
2319
  auth: typeof defaultExport;
package/lib/index.js CHANGED
@@ -51,6 +51,7 @@ import TwitterAuthProvider from './providers/TwitterAuthProvider';
51
51
  import { TotpSecret } from './TotpSecret';
52
52
  import version from './version';
53
53
  import fallBackModule from './web/RNFBAuthModule';
54
+ import { PasswordPolicyMixin } from './password-policy/PasswordPolicyMixin';
54
55
 
55
56
  const PhoneAuthState = {
56
57
  CODE_SENT: 'sent',
@@ -103,6 +104,8 @@ class FirebaseAuthModule extends FirebaseModule {
103
104
  this._authResult = false;
104
105
  this._languageCode = this.native.APP_LANGUAGE[this.app._name];
105
106
  this._tenantId = null;
107
+ this._projectPasswordPolicy = null;
108
+ this._tenantPasswordPolicies = {};
106
109
 
107
110
  if (!this.languageCode) {
108
111
  this._languageCode = this.native.APP_LANGUAGE['[DEFAULT]'];
@@ -336,15 +339,45 @@ class FirebaseAuthModule extends FirebaseModule {
336
339
  }
337
340
 
338
341
  createUserWithEmailAndPassword(email, password) {
339
- return this.native
340
- .createUserWithEmailAndPassword(email, password)
341
- .then(userCredential => this._setUserCredential(userCredential));
342
+ return (
343
+ this.native
344
+ .createUserWithEmailAndPassword(email, password)
345
+ .then(userCredential => this._setUserCredential(userCredential))
346
+ /* istanbul ignore next - native error handling cannot be unit tested */
347
+ .catch(error => {
348
+ if (error.code === 'auth/password-does-not-meet-requirements') {
349
+ return this._recachePasswordPolicy()
350
+ .catch(() => {
351
+ // Silently ignore recache failures - the original error matters more
352
+ })
353
+ .then(() => {
354
+ throw error;
355
+ });
356
+ }
357
+ throw error;
358
+ })
359
+ );
342
360
  }
343
361
 
344
362
  signInWithEmailAndPassword(email, password) {
345
- return this.native
346
- .signInWithEmailAndPassword(email, password)
347
- .then(userCredential => this._setUserCredential(userCredential));
363
+ return (
364
+ this.native
365
+ .signInWithEmailAndPassword(email, password)
366
+ .then(userCredential => this._setUserCredential(userCredential))
367
+ /* istanbul ignore next - native error handling cannot be unit tested */
368
+ .catch(error => {
369
+ if (error.code === 'auth/password-does-not-meet-requirements') {
370
+ return this._recachePasswordPolicy()
371
+ .catch(() => {
372
+ // Silently ignore recache failures - the original error matters more
373
+ })
374
+ .then(() => {
375
+ throw error;
376
+ });
377
+ }
378
+ throw error;
379
+ })
380
+ );
348
381
  }
349
382
 
350
383
  signInWithCustomToken(customToken) {
@@ -382,7 +415,23 @@ class FirebaseAuthModule extends FirebaseModule {
382
415
  }
383
416
 
384
417
  confirmPasswordReset(code, newPassword) {
385
- return this.native.confirmPasswordReset(code, newPassword);
418
+ return (
419
+ this.native
420
+ .confirmPasswordReset(code, newPassword)
421
+ /* istanbul ignore next - native error handling cannot be unit tested */
422
+ .catch(error => {
423
+ if (error.code === 'auth/password-does-not-meet-requirements') {
424
+ return this._recachePasswordPolicy()
425
+ .catch(() => {
426
+ // Silently ignore recache failures - the original error matters more
427
+ })
428
+ .then(() => {
429
+ throw error;
430
+ });
431
+ }
432
+ throw error;
433
+ })
434
+ );
386
435
  }
387
436
 
388
437
  applyActionCode(code) {
@@ -493,6 +542,9 @@ class FirebaseAuthModule extends FirebaseModule {
493
542
  }
494
543
  }
495
544
 
545
+ // Apply password policy mixin to FirebaseAuthModule
546
+ Object.assign(FirebaseAuthModule.prototype, PasswordPolicyMixin);
547
+
496
548
  // import { SDK_VERSION } from '@react-native-firebase/auth';
497
549
  export const SDK_VERSION = version;
498
550
 
@@ -16,8 +16,6 @@
16
16
  */
17
17
 
18
18
  import { getApp } from '@react-native-firebase/app';
19
- import { fetchPasswordPolicy } from '../password-policy/passwordPolicyApi';
20
- import { PasswordPolicyImpl } from '../password-policy/PasswordPolicyImpl';
21
19
  import { MultiFactorUser } from '../multiFactor';
22
20
  import { MODULAR_DEPRECATION_ARG } from '@react-native-firebase/app/lib/common';
23
21
 
@@ -637,15 +635,17 @@ export function getCustomAuthDomain(auth) {
637
635
  * @returns {Promise<PasswordValidationStatus>}
638
636
  */
639
637
  export async function validatePassword(auth, password) {
638
+ if (!auth || !auth.app) {
639
+ throw new Error(
640
+ "firebase.auth().validatePassword(*) 'auth' must be a valid Auth instance with an 'app' property. Received: undefined",
641
+ );
642
+ }
643
+
640
644
  if (password === null || password === undefined) {
641
645
  throw new Error(
642
646
  "firebase.auth().validatePassword(*) expected 'password' to be a non-null or a defined value.",
643
647
  );
644
648
  }
645
- let passwordPolicy = await fetchPasswordPolicy(auth);
646
-
647
- const passwordPolicyImpl = await new PasswordPolicyImpl(passwordPolicy);
648
- let status = passwordPolicyImpl.validatePassword(password);
649
649
 
650
- return status;
650
+ return auth.validatePassword.call(auth, password, MODULAR_DEPRECATION_ARG);
651
651
  }
@@ -0,0 +1,66 @@
1
+ /*
2
+ * Copyright (c) 2016-present Invertase Limited & Contributors
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this library except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ *
16
+ */
17
+
18
+ import { fetchPasswordPolicy } from './passwordPolicyApi';
19
+ import { PasswordPolicyImpl } from './PasswordPolicyImpl';
20
+
21
+ const EXPECTED_PASSWORD_POLICY_SCHEMA_VERSION = 1;
22
+
23
+ /**
24
+ * Password policy mixin - provides password policy caching and validation.
25
+ * Expects the target object to have: _tenantId, _projectPasswordPolicy,
26
+ * _tenantPasswordPolicies, and app.options.apiKey
27
+ */
28
+ export const PasswordPolicyMixin = {
29
+ _getPasswordPolicyInternal() {
30
+ if (this._tenantId === null) {
31
+ return this._projectPasswordPolicy;
32
+ }
33
+ return this._tenantPasswordPolicies[this._tenantId];
34
+ },
35
+
36
+ async _updatePasswordPolicy() {
37
+ const response = await fetchPasswordPolicy(this);
38
+ const passwordPolicy = new PasswordPolicyImpl(response);
39
+ if (this._tenantId === null) {
40
+ this._projectPasswordPolicy = passwordPolicy;
41
+ } else {
42
+ this._tenantPasswordPolicies[this._tenantId] = passwordPolicy;
43
+ }
44
+ },
45
+
46
+ async _recachePasswordPolicy() {
47
+ if (this._getPasswordPolicyInternal()) {
48
+ await this._updatePasswordPolicy();
49
+ }
50
+ },
51
+
52
+ async validatePassword(password) {
53
+ if (!this._getPasswordPolicyInternal()) {
54
+ await this._updatePasswordPolicy();
55
+ }
56
+ const passwordPolicy = this._getPasswordPolicyInternal();
57
+
58
+ if (passwordPolicy.schemaVersion !== EXPECTED_PASSWORD_POLICY_SCHEMA_VERSION) {
59
+ throw new Error(
60
+ 'auth/unsupported-password-policy-schema-version: The password policy received from the backend uses a schema version that is not supported by this version of the SDK.',
61
+ );
62
+ }
63
+
64
+ return passwordPolicy.validatePassword(password);
65
+ },
66
+ };
@@ -23,8 +23,6 @@
23
23
  * @throws {Error} Throws an error if the request fails or encounters an issue.
24
24
  */
25
25
  export async function fetchPasswordPolicy(auth) {
26
- let schemaVersion = 1;
27
-
28
26
  try {
29
27
  // Identity toolkit API endpoint for password policy. Ensure this is enabled on Google cloud.
30
28
  const baseURL = 'https://identitytoolkit.googleapis.com/v2/passwordPolicy?key=';
@@ -37,19 +35,10 @@ export async function fetchPasswordPolicy(auth) {
37
35
  `firebase.auth().validatePassword(*) failed to fetch password policy from Firebase Console: ${response.statusText}. Details: ${errorDetails}`,
38
36
  );
39
37
  }
40
- const passwordPolicy = await response.json();
41
-
42
- if (passwordPolicy.schemaVersion !== schemaVersion) {
43
- throw new Error(
44
- `Password policy schema version mismatch. Expected: ${schemaVersion}, received: ${passwordPolicy.schemaVersion}`,
45
- );
46
- }
47
- return passwordPolicy;
38
+ return await response.json();
48
39
  } catch (error) {
49
40
  throw new Error(
50
41
  `firebase.auth().validatePassword(*) Failed to fetch password policy: ${error.message}`,
51
42
  );
52
43
  }
53
44
  }
54
-
55
- module.exports = { fetchPasswordPolicy };
package/lib/version.js CHANGED
@@ -1,2 +1,2 @@
1
1
  // Generated by genversion.
2
- module.exports = '23.6.0';
2
+ module.exports = '23.8.0';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@react-native-firebase/auth",
3
- "version": "23.6.0",
3
+ "version": "23.8.0",
4
4
  "author": "Invertase <oss@invertase.io> (http://invertase.io)",
5
5
  "description": "React Native Firebase - The authentication module provides an easy-to-use API to integrate an authentication workflow into new and existing applications. React Native Firebase provides access to all Firebase authentication methods and identity providers.",
6
6
  "main": "lib/index.js",
@@ -27,7 +27,7 @@
27
27
  "plist": "^3.1.0"
28
28
  },
29
29
  "peerDependencies": {
30
- "@react-native-firebase/app": "23.6.0",
30
+ "@react-native-firebase/app": "23.8.0",
31
31
  "expo": ">=47.0.0"
32
32
  },
33
33
  "devDependencies": {
@@ -43,5 +43,5 @@
43
43
  "access": "public",
44
44
  "provenance": true
45
45
  },
46
- "gitHead": "748e89f9bfcdfbee971c627cd8a698963ba09f33"
46
+ "gitHead": "724ddcfea6ebe93875e5a54ff38ca57ab5990822"
47
47
  }