From 23f46c1cf75d4969c962f115cad8d69fc9ea1934 Mon Sep 17 00:00:00 2001 From: mansisampat Date: Wed, 25 Jun 2025 11:39:42 +0530 Subject: [PATCH 1/5] Maintain persistence for firebaseToken in AuthImpl object --- packages/auth/demo/src/index.js | 4 +- packages/auth/demo/yarn.lock | 101 +++++++++--------- packages/auth/src/core/auth/auth_impl.ts | 10 ++ .../persistence/persistence_user_manager.ts | 36 ++++++- 4 files changed, 98 insertions(+), 53 deletions(-) diff --git a/packages/auth/demo/src/index.js b/packages/auth/demo/src/index.js index 05c3b59d4c4..b04fafe2a98 100644 --- a/packages/auth/demo/src/index.js +++ b/packages/auth/demo/src/index.js @@ -1526,7 +1526,7 @@ function onExchangeToken(event) { exchangeCIAMToken(byoCiamInput.value) .then(response => { - byoCiamResult.textContent = response.accessToken; + byoCiamResult.textContent = response; console.log('Token:', response); }) .catch(error => { @@ -2086,7 +2086,7 @@ function initApp() { const regionalApp = initializeApp(config, `${auth.name}-rgcip`); regionalAuth = initializeAuth(regionalApp, { - persistence: inMemoryPersistence, + persistence: indexedDBLocalPersistence, popupRedirectResolver: browserPopupRedirectResolver, tenantConfig: tenantConfig }); diff --git a/packages/auth/demo/yarn.lock b/packages/auth/demo/yarn.lock index 575e395200b..8e94243b797 100644 --- a/packages/auth/demo/yarn.lock +++ b/packages/auth/demo/yarn.lock @@ -17,9 +17,9 @@ integrity sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow== "@firebase/app@*": - version "0.13.0" - resolved "https://registry.npmjs.org/@firebase/app/-/app-0.13.0.tgz#ef67c7e5dc3f47efb430157f9de969a67abd53a7" - integrity sha512-Vj3MST245nq+V5UmmfEkB3isIgPouyUr8yGJlFeL9Trg/umG5ogAvrjAYvQ8gV7daKDoQSRnJKWI2JFpQqRsuQ== + version "0.13.1" + resolved "https://registry.npmjs.org/@firebase/app/-/app-0.13.1.tgz#f821eee478d03224e70612d2632d7ba351c98a77" + integrity sha512-0O33PKrXLoIWkoOO5ByFaLjZehBctSYWnb+xJkIdx2SKP/K9l1UPFXPwASyrOIqyY3ws+7orF/1j7wI5EKzPYQ== dependencies: "@firebase/component" "0.6.17" "@firebase/logger" "0.4.4" @@ -28,19 +28,11 @@ tslib "^2.1.0" "@firebase/auth@file:..": - version "1.10.4" + version "1.10.7" dependencies: - "@firebase/component" "0.6.16" + "@firebase/component" "0.6.17" "@firebase/logger" "0.4.4" - "@firebase/util" "1.11.3" - tslib "^2.1.0" - -"@firebase/component@0.6.16": - version "0.6.16" - resolved "https://registry.npmjs.org/@firebase/component/-/component-0.6.16.tgz#057b9a1b2998ad9eaf22a96fb95101f7d08e2675" - integrity sha512-whx+e3pgC3J9O6t4LOB8jiLk3tpWtnXaQ+xt/ys/4IGUPRI+nnWooVdtWrEnMga/gT03ug9SdEAEJLl6I1BIlg== - dependencies: - "@firebase/util" "1.11.3" + "@firebase/util" "1.12.0" tslib "^2.1.0" "@firebase/component@0.6.17": @@ -65,13 +57,6 @@ dependencies: tslib "^2.1.0" -"@firebase/util@1.11.3": - version "1.11.3" - resolved "https://registry.npmjs.org/@firebase/util/-/util-1.11.3.tgz#9ace94f5a2020112fed3baaee9a9d1b1f1569b37" - integrity sha512-4wYnOV9FpwdCq3rHQOCrdx4AQBUbfH1p2DhWGQxlQ+D3Xl/wSxc/HttcyPN4NNFiynxoNCFGWQH/zdhRfxP1Zg== - dependencies: - tslib "^2.1.0" - "@gar/promisify@^1.0.1": version "1.1.3" resolved "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz#555193ab2e3bb3b6adc3d551c9c030d9e860daf6" @@ -1039,9 +1024,9 @@ picomatch "^2.2.2" "@rollup/pluginutils@^5.0.1": - version "5.1.4" - resolved "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.4.tgz#bb94f1f9eaaac944da237767cdfee6c5b2262d4a" - integrity sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ== + version "5.2.0" + resolved "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.2.0.tgz#eac25ca5b0bdda4ba735ddaca5fbf26bd435f602" + integrity sha512-qWJ2ZTbmumwiLFomfzTyt5Kng4hwPi9rwCYN4SHb6eaRU1KNO4ccxINHr/VhH4GgPlt1XfSTLX2LBTme8ne4Zw== dependencies: "@types/estree" "^1.0.0" estree-walker "^2.0.2" @@ -1058,9 +1043,9 @@ integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw== "@types/estree@^1.0.0": - version "1.0.7" - resolved "https://registry.npmjs.org/@types/estree/-/estree-1.0.7.tgz#4158d3105276773d5b7695cd4834b1722e4f37a8" - integrity sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ== + version "1.0.8" + resolved "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz#958b91c991b1867ced318bedea0e215ee050726e" + integrity sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w== "@types/minimatch@^3.0.3": version "3.0.5" @@ -1073,11 +1058,11 @@ integrity sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag== "@types/node@*": - version "22.15.23" - resolved "https://registry.npmjs.org/@types/node/-/node-22.15.23.tgz#a0b7c03f951f1ffe381a6a345c68d80e48043dd0" - integrity sha512-7Ec1zaFPF4RJ0eXu1YT/xgiebqwqoJz8rYPDi/O2BcZ++Wpt0Kq9cl0eg6NN6bYbPnR67ZLo7St5Q3UK0SnARw== + version "24.0.4" + resolved "https://registry.npmjs.org/@types/node/-/node-24.0.4.tgz#dbae889912bda33a7f57669fb8587c1a56bc0c1f" + integrity sha512-ulyqAkrhnuNq9pB76DRBTkcS6YsmDALy6Ua63V8OhrOBgbcYt6IOdzpw5P1+dyRIyMerzLkeYWBeOXPpA9GMAA== dependencies: - undici-types "~6.21.0" + undici-types "~7.8.0" "@types/normalize-package-data@^2.4.0": version "2.4.4" @@ -1117,9 +1102,9 @@ abbrev@1: integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== acorn@^8.14.0: - version "8.14.1" - resolved "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz#721d5dc10f7d5b5609a891773d47731796935dfb" - integrity sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg== + version "8.15.0" + resolved "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz#a360898bc415edaac46c8241f6383975b930b816" + integrity sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg== add-stream@^1.0.0: version "1.0.0" @@ -1327,9 +1312,9 @@ before-after-hook@^2.2.0: integrity sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ== brace-expansion@^1.1.7: - version "1.1.11" - resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + version "1.1.12" + resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz#ab9b454466e5a8cc3a187beaad580412a9c5b843" + integrity sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg== dependencies: balanced-match "^1.0.0" concat-map "0.0.1" @@ -1920,9 +1905,9 @@ error-ex@^1.3.1: is-arrayish "^0.2.1" es-abstract@^1.23.2, es-abstract@^1.23.5, es-abstract@^1.23.9: - version "1.23.10" - resolved "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.10.tgz#84792c152ff2898ec73efe33c1c1323a3dfd87f8" - integrity sha512-MtUbM072wlJNyeYAe0mhzrD+M6DIJa96CZAOBBrhDbgKnB4MApIKefcyAB1eOdYn8cUNZgvwBvEzdoAYsxgEIw== + version "1.24.0" + resolved "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.0.tgz#c44732d2beb0acc1ed60df840869e3106e7af328" + integrity sha512-WSzPgsdLtTcQwm4CROfS5ju2Wa1QQcVeT37jFjYzdFz1r9ahadC8B8/a4qxJxM+09F18iumCdRmlr96ZYkQvEg== dependencies: array-buffer-byte-length "^1.0.2" arraybuffer.prototype.slice "^1.0.4" @@ -1951,7 +1936,9 @@ es-abstract@^1.23.2, es-abstract@^1.23.5, es-abstract@^1.23.9: is-array-buffer "^3.0.5" is-callable "^1.2.7" is-data-view "^1.0.2" + is-negative-zero "^2.0.3" is-regex "^1.2.1" + is-set "^2.0.3" is-shared-array-buffer "^1.0.4" is-string "^1.1.1" is-typed-array "^1.1.15" @@ -1966,6 +1953,7 @@ es-abstract@^1.23.2, es-abstract@^1.23.5, es-abstract@^1.23.9: safe-push-apply "^1.0.0" safe-regex-test "^1.1.0" set-proto "^1.0.0" + stop-iteration-iterator "^1.1.0" string.prototype.trim "^1.2.10" string.prototype.trimend "^1.0.9" string.prototype.trimstart "^1.0.8" @@ -2827,6 +2815,11 @@ is-module@^1.0.0: resolved "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz#3258fb69f78c14d5b815d664336b4cffb6441591" integrity sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g== +is-negative-zero@^2.0.3: + version "2.0.3" + resolved "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz#ced903a027aca6381b777a5743069d7376a49747" + integrity sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw== + is-number-object@^1.1.1: version "1.1.1" resolved "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz#144b21e95a1bc148205dcc2814a9134ec41b2541" @@ -4660,9 +4653,9 @@ socks-proxy-agent@^6.0.0: socks "^2.6.2" socks@^2.3.3, socks@^2.6.2: - version "2.8.4" - resolved "https://registry.npmjs.org/socks/-/socks-2.8.4.tgz#07109755cdd4da03269bda4725baa061ab56d5cc" - integrity sha512-D3YaD0aRxR3mEcqnidIs7ReYJFVzWdd6fXJYUM8ixcQcJRGTka/b3saV0KflYhyVJXKhb947GndU35SxYNResQ== + version "2.8.5" + resolved "https://registry.npmjs.org/socks/-/socks-2.8.5.tgz#bfe18f5ead1efc93f5ec90c79fa8bdccbcee2e64" + integrity sha512-iF+tNDQla22geJdTyJB1wM/qrX9DMRwWrciEPwWLPRWAUEM8sQiyxgckLxWT1f7+9VabJS0jTGGr4QgBuvi6Ww== dependencies: ip-address "^9.0.5" smart-buffer "^4.2.0" @@ -4771,6 +4764,14 @@ ssri@^8.0.0, ssri@^8.0.1: dependencies: minipass "^3.1.1" +stop-iteration-iterator@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz#f481ff70a548f6124d0312c3aa14cbfa7aa542ad" + integrity sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ== + dependencies: + es-errors "^1.3.0" + internal-slot "^1.1.0" + strict-uri-encode@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz#b9c7330c7042862f6b142dc274bbcc5866ce3546" @@ -4946,9 +4947,9 @@ temp-write@^4.0.0: uuid "^3.3.2" terser@^5.17.4: - version "5.40.0" - resolved "https://registry.npmjs.org/terser/-/terser-5.40.0.tgz#839a80db42bfee8340085f44ea99b5cba36c55c8" - integrity sha512-cfeKl/jjwSR5ar7d0FGmave9hFGJT8obyo0z+CrQOylLDbk7X81nPU6vq9VORa5jU30SkDnT2FXjLbR8HLP+xA== + version "5.43.1" + resolved "https://registry.npmjs.org/terser/-/terser-5.43.1.tgz#88387f4f9794ff1a29e7ad61fb2932e25b4fdb6d" + integrity sha512-+6erLbBm0+LROX2sPXlUYx/ux5PyE9K/a92Wrt6oA+WDAoFTdpHE5tCYCI5PNzq2y8df4rA+QgHLJuR4jNymsg== dependencies: "@jridgewell/source-map" "^0.3.3" acorn "^8.14.0" @@ -5148,10 +5149,10 @@ unbox-primitive@^1.1.0: has-symbols "^1.1.0" which-boxed-primitive "^1.1.1" -undici-types@~6.21.0: - version "6.21.0" - resolved "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz#691d00af3909be93a7faa13be61b3a5b50ef12cb" - integrity sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ== +undici-types@~7.8.0: + version "7.8.0" + resolved "https://registry.npmjs.org/undici-types/-/undici-types-7.8.0.tgz#de00b85b710c54122e44fbfd911f8d70174cd294" + integrity sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw== unique-filename@^1.1.1: version "1.1.1" diff --git a/packages/auth/src/core/auth/auth_impl.ts b/packages/auth/src/core/auth/auth_impl.ts index 20df2390774..aedb3d8e60e 100644 --- a/packages/auth/src/core/auth/auth_impl.ts +++ b/packages/auth/src/core/auth/auth_impl.ts @@ -195,6 +195,7 @@ export class AuthImpl implements AuthInternal, _FirebaseService { } await this.initializeCurrentUser(popupRedirectResolver); + await this.initializeFirebaseToken(); this.lastNotifiedUid = this.currentUser?.uid || null; @@ -403,6 +404,10 @@ export class AuthImpl implements AuthInternal, _FirebaseService { return this.directlySetCurrentUser(user); } + private async initializeFirebaseToken(): Promise { + this.firebaseToken = await this.persistenceManager?.getFirebaseToken() ?? null; + } + useDeviceLanguage(): void { this.languageCode = _getUserLanguage(); } @@ -461,6 +466,11 @@ export class AuthImpl implements AuthInternal, _FirebaseService { firebaseToken: FirebaseToken | null ): Promise { this.firebaseToken = firebaseToken; + if (firebaseToken) { + await this.assertedPersistence.setFirebaseToken(firebaseToken); + } else { + await this.assertedPersistence.removeFirebaseToken(); + } } async signOut(): Promise { diff --git a/packages/auth/src/core/persistence/persistence_user_manager.ts b/packages/auth/src/core/persistence/persistence_user_manager.ts index 580aaad3b25..3981a60efe1 100644 --- a/packages/auth/src/core/persistence/persistence_user_manager.ts +++ b/packages/auth/src/core/persistence/persistence_user_manager.ts @@ -17,6 +17,7 @@ import { getAccountInfo } from '../../api/account_management/account'; import { ApiKey, AppName, AuthInternal } from '../../model/auth'; +import { FirebaseToken } from '../../model/public_types'; import { UserInternal } from '../../model/user'; import { PersistedBlob, PersistenceInternal } from '../persistence'; import { UserImpl } from '../user/user_impl'; @@ -27,7 +28,8 @@ export const enum KeyName { AUTH_USER = 'authUser', AUTH_EVENT = 'authEvent', REDIRECT_USER = 'redirectUser', - PERSISTENCE_USER = 'persistence' + PERSISTENCE_USER = 'persistence', + PERSISTENCE_TOKEN = 'persistence-token' } export const enum Namespace { PERSISTENCE = 'firebase' @@ -44,6 +46,7 @@ export function _persistenceKeyName( export class PersistenceUserManager { private readonly fullUserKey: string; private readonly fullPersistenceKey: string; + private readonly firebaseTokenPersistenceKey: string; private readonly boundEventHandler: () => void; private constructor( @@ -58,6 +61,11 @@ export class PersistenceUserManager { config.apiKey, name ); + this.firebaseTokenPersistenceKey = _persistenceKeyName( + KeyName.PERSISTENCE_TOKEN, + config.apiKey, + name + ); this.boundEventHandler = auth._onStorageEvent.bind(auth); this.persistence._addListener(this.fullUserKey, this.boundEventHandler); } @@ -66,6 +74,32 @@ export class PersistenceUserManager { return this.persistence._set(this.fullUserKey, user.toJSON()); } + setFirebaseToken(firebaseToken: FirebaseToken): Promise { + return this.persistence._set(this.firebaseTokenPersistenceKey, { + token: firebaseToken.token, + expirationTime: firebaseToken.expirationTime + }); + } + + async getFirebaseToken(): Promise { + const blob = await this.persistence._get( + this.firebaseTokenPersistenceKey + ); + if (!blob) { + return null; + } + const token = blob.token as string; + const expirationTime = blob.expirationTime as number; + return { + token, + expirationTime + }; + } + + removeFirebaseToken(): Promise { + return this.persistence._remove(this.firebaseTokenPersistenceKey); + } + async getCurrentUser(): Promise { const blob = await this.persistence._get( this.fullUserKey From c86cbfe0af85b07cc71b50248cb800680783e134 Mon Sep 17 00:00:00 2001 From: mansisampat Date: Mon, 30 Jun 2025 14:50:14 +0530 Subject: [PATCH 2/5] Change initializeFirebaseToken --- packages/auth/src/core/auth/auth_impl.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/auth/src/core/auth/auth_impl.ts b/packages/auth/src/core/auth/auth_impl.ts index aedb3d8e60e..96517615cbf 100644 --- a/packages/auth/src/core/auth/auth_impl.ts +++ b/packages/auth/src/core/auth/auth_impl.ts @@ -106,6 +106,7 @@ export class AuthImpl implements AuthInternal, _FirebaseService { private persistenceManager?: PersistenceUserManager; private redirectPersistenceManager?: PersistenceUserManager; private authStateSubscription = new Subscription(this); + private firebaseTokenSubscription = new Subscription(this); private idTokenSubscription = new Subscription(this); private readonly beforeStateQueue = new AuthMiddlewareQueue(this); private redirectUser: UserInternal | null = null; @@ -405,7 +406,9 @@ export class AuthImpl implements AuthInternal, _FirebaseService { } private async initializeFirebaseToken(): Promise { - this.firebaseToken = await this.persistenceManager?.getFirebaseToken() ?? null; + this.firebaseToken = + (await this.persistenceManager?.getFirebaseToken()) ?? null; + this.firebaseTokenSubscription.next(this.firebaseToken); } useDeviceLanguage(): void { @@ -466,6 +469,7 @@ export class AuthImpl implements AuthInternal, _FirebaseService { firebaseToken: FirebaseToken | null ): Promise { this.firebaseToken = firebaseToken; + this.firebaseTokenSubscription.next(firebaseToken); if (firebaseToken) { await this.assertedPersistence.setFirebaseToken(firebaseToken); } else { From 22027680b1294adc4061f0837d4772255d5eefb4 Mon Sep 17 00:00:00 2001 From: mansisampat Date: Tue, 1 Jul 2025 13:06:20 +0530 Subject: [PATCH 3/5] Adding Unit Test for auth_impl firebaseToken --- packages/auth/src/core/auth/auth_impl.test.ts | 141 +++++++++++++++++- 1 file changed, 140 insertions(+), 1 deletion(-) diff --git a/packages/auth/src/core/auth/auth_impl.test.ts b/packages/auth/src/core/auth/auth_impl.test.ts index 3aa8623d40e..1611b270047 100644 --- a/packages/auth/src/core/auth/auth_impl.test.ts +++ b/packages/auth/src/core/auth/auth_impl.test.ts @@ -46,8 +46,9 @@ import { mockEndpointWithParams } from '../../../test/helpers/api/helper'; import { Endpoint, RecaptchaClientType, RecaptchaVersion } from '../../api'; import * as mockFetch from '../../../test/helpers/mock_fetch'; import { AuthErrorCode } from '../errors'; -import { PasswordValidationStatus } from '../../model/public_types'; +import { FirebaseToken, PasswordValidationStatus } from '../../model/public_types'; import { PasswordPolicyImpl } from './password_policy_impl'; +import { PersistenceUserManager } from '../persistence/persistence_user_manager'; use(sinonChai); use(chaiAsPromised); @@ -150,6 +151,144 @@ describe('core/auth/auth_impl', () => { }); }); + describe('#updateFirebaseToken', () => { + const token: FirebaseToken = { + token: 'test-token', + expirationTime: 123456789 + }; + + it('sets the field on the auth object', async () => { + await auth._updateFirebaseToken(token); + expect((auth as any).firebaseToken).to.eql(token); + }); + + it('calls persistence._set with correct values', async () => { + await auth._updateFirebaseToken(token); + expect(persistenceStub._set).to.have.been.calledWith( + 'firebase:persistence-token:api-key:test-app', // key + { + token: token.token, + expirationTime: token.expirationTime + } + ); + }); + + it('setting to null triggers persistence._remove', async () => { + await auth._updateFirebaseToken(null); + expect(persistenceStub._remove).to.have.been.calledWith( + 'firebase:persistence-token:api-key:test-app'); + }); + + it('orders async updates correctly', async () => { + const tokens: FirebaseToken[] = Array.from({ length: 5 }, (_, i) => ({ + token: `token-${i}`, + expirationTime: Date.now() + i + })); + + persistenceStub._set.callsFake(() => { + return new Promise(resolve => { + setTimeout(() => resolve(), 1); + }); + }); + + await Promise.all(tokens.map(t => auth._updateFirebaseToken(t))); + + for (let i = 0; i < tokens.length; i++) { + expect(persistenceStub._set.getCall(i)).to.have.been.calledWith( + 'firebase:persistence-token:api-key:test-app', + { + token: tokens[i].token, + expirationTime: tokens[i].expirationTime + } + ); + } + }); + + it('throws if persistence._set fails', async () => { + persistenceStub._set.rejects(new Error('fail')); + await expect(auth._updateFirebaseToken(token)).to.be.rejectedWith('fail'); + }); + + it('throws if persistence._remove fails', async () => { + persistenceStub._remove.rejects(new Error('remove fail')); + await expect(auth._updateFirebaseToken(null)).to.be.rejectedWith('remove fail'); + }); + }); + + describe('#_initializeWithPersistence', () => { + let mockToken: FirebaseToken; + let persistenceManager: any; + let subscription: any; + let authImpl: AuthImpl; + + beforeEach(() => { + mockToken = { + token: 'test-token', + expirationTime: 123456789 + }; + + persistenceManager = { + getFirebaseToken: sinon.stub().resolves(mockToken), + getCurrentUser: sinon.stub().resolves(null), + setCurrentUser: sinon.stub().resolves(), + removeCurrentUser: sinon.stub().resolves(), + getPersistence: sinon.stub().returns('LOCAL') + }; + + subscription = { + next: sinon.spy() + }; + + sinon.stub(PersistenceUserManager, 'create').resolves(persistenceManager); + + authImpl = new AuthImpl( + FAKE_APP, + FAKE_HEARTBEAT_CONTROLLER_PROVIDER, + FAKE_APP_CHECK_CONTROLLER_PROVIDER, + { + apiKey: FAKE_APP.options.apiKey!, + apiHost: DefaultConfig.API_HOST, + apiScheme: DefaultConfig.API_SCHEME, + tokenApiHost: DefaultConfig.TOKEN_API_HOST, + clientPlatform: ClientPlatform.BROWSER, + sdkClientVersion: 'v' + } + ); + + (authImpl as any).firebaseTokenSubscription = subscription; + }); + + afterEach(() => { + sinon.restore(); + }); + + it('should load the firebaseToken from persistence and set it', async () => { + await authImpl._initializeWithPersistence([persistenceStub as PersistenceInternal]); + + expect(persistenceManager.getFirebaseToken).to.have.been.called; + expect((authImpl as any).firebaseToken).to.eql(mockToken); + expect(subscription.next).to.have.been.calledWith(mockToken); + }); + + it('should set firebaseToken to null if getFirebaseToken returns undefined', async () => { + persistenceManager.getFirebaseToken.resolves(undefined); + + await authImpl._initializeWithPersistence([persistenceStub as PersistenceInternal]); + + expect((authImpl as any).firebaseToken).to.be.null; + expect(subscription.next).to.have.been.calledWith(null); + }); + + it('should set firebaseToken to null if getFirebaseToken returns null', async () => { + persistenceManager.getFirebaseToken.resolves(null); + + await authImpl._initializeWithPersistence([persistenceStub as PersistenceInternal]); + + expect((authImpl as any).firebaseToken).to.be.null; + expect(subscription.next).to.have.been.calledWith(null); + }); + }); + describe('#signOut', () => { it('sets currentUser to null, calls remove', async () => { await auth._updateCurrentUser(testUser(auth, 'test')); From b0cdd2599396b4c8883bceaf01b250c27269521e Mon Sep 17 00:00:00 2001 From: mansisampat Date: Tue, 1 Jul 2025 13:11:11 +0530 Subject: [PATCH 4/5] Remove yarn.lock --- packages/auth/demo/yarn.lock | 101 +++++++++++++++++------------------ 1 file changed, 50 insertions(+), 51 deletions(-) diff --git a/packages/auth/demo/yarn.lock b/packages/auth/demo/yarn.lock index 8e94243b797..575e395200b 100644 --- a/packages/auth/demo/yarn.lock +++ b/packages/auth/demo/yarn.lock @@ -17,9 +17,9 @@ integrity sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow== "@firebase/app@*": - version "0.13.1" - resolved "https://registry.npmjs.org/@firebase/app/-/app-0.13.1.tgz#f821eee478d03224e70612d2632d7ba351c98a77" - integrity sha512-0O33PKrXLoIWkoOO5ByFaLjZehBctSYWnb+xJkIdx2SKP/K9l1UPFXPwASyrOIqyY3ws+7orF/1j7wI5EKzPYQ== + version "0.13.0" + resolved "https://registry.npmjs.org/@firebase/app/-/app-0.13.0.tgz#ef67c7e5dc3f47efb430157f9de969a67abd53a7" + integrity sha512-Vj3MST245nq+V5UmmfEkB3isIgPouyUr8yGJlFeL9Trg/umG5ogAvrjAYvQ8gV7daKDoQSRnJKWI2JFpQqRsuQ== dependencies: "@firebase/component" "0.6.17" "@firebase/logger" "0.4.4" @@ -28,11 +28,19 @@ tslib "^2.1.0" "@firebase/auth@file:..": - version "1.10.7" + version "1.10.4" dependencies: - "@firebase/component" "0.6.17" + "@firebase/component" "0.6.16" "@firebase/logger" "0.4.4" - "@firebase/util" "1.12.0" + "@firebase/util" "1.11.3" + tslib "^2.1.0" + +"@firebase/component@0.6.16": + version "0.6.16" + resolved "https://registry.npmjs.org/@firebase/component/-/component-0.6.16.tgz#057b9a1b2998ad9eaf22a96fb95101f7d08e2675" + integrity sha512-whx+e3pgC3J9O6t4LOB8jiLk3tpWtnXaQ+xt/ys/4IGUPRI+nnWooVdtWrEnMga/gT03ug9SdEAEJLl6I1BIlg== + dependencies: + "@firebase/util" "1.11.3" tslib "^2.1.0" "@firebase/component@0.6.17": @@ -57,6 +65,13 @@ dependencies: tslib "^2.1.0" +"@firebase/util@1.11.3": + version "1.11.3" + resolved "https://registry.npmjs.org/@firebase/util/-/util-1.11.3.tgz#9ace94f5a2020112fed3baaee9a9d1b1f1569b37" + integrity sha512-4wYnOV9FpwdCq3rHQOCrdx4AQBUbfH1p2DhWGQxlQ+D3Xl/wSxc/HttcyPN4NNFiynxoNCFGWQH/zdhRfxP1Zg== + dependencies: + tslib "^2.1.0" + "@gar/promisify@^1.0.1": version "1.1.3" resolved "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz#555193ab2e3bb3b6adc3d551c9c030d9e860daf6" @@ -1024,9 +1039,9 @@ picomatch "^2.2.2" "@rollup/pluginutils@^5.0.1": - version "5.2.0" - resolved "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.2.0.tgz#eac25ca5b0bdda4ba735ddaca5fbf26bd435f602" - integrity sha512-qWJ2ZTbmumwiLFomfzTyt5Kng4hwPi9rwCYN4SHb6eaRU1KNO4ccxINHr/VhH4GgPlt1XfSTLX2LBTme8ne4Zw== + version "5.1.4" + resolved "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.4.tgz#bb94f1f9eaaac944da237767cdfee6c5b2262d4a" + integrity sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ== dependencies: "@types/estree" "^1.0.0" estree-walker "^2.0.2" @@ -1043,9 +1058,9 @@ integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw== "@types/estree@^1.0.0": - version "1.0.8" - resolved "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz#958b91c991b1867ced318bedea0e215ee050726e" - integrity sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w== + version "1.0.7" + resolved "https://registry.npmjs.org/@types/estree/-/estree-1.0.7.tgz#4158d3105276773d5b7695cd4834b1722e4f37a8" + integrity sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ== "@types/minimatch@^3.0.3": version "3.0.5" @@ -1058,11 +1073,11 @@ integrity sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag== "@types/node@*": - version "24.0.4" - resolved "https://registry.npmjs.org/@types/node/-/node-24.0.4.tgz#dbae889912bda33a7f57669fb8587c1a56bc0c1f" - integrity sha512-ulyqAkrhnuNq9pB76DRBTkcS6YsmDALy6Ua63V8OhrOBgbcYt6IOdzpw5P1+dyRIyMerzLkeYWBeOXPpA9GMAA== + version "22.15.23" + resolved "https://registry.npmjs.org/@types/node/-/node-22.15.23.tgz#a0b7c03f951f1ffe381a6a345c68d80e48043dd0" + integrity sha512-7Ec1zaFPF4RJ0eXu1YT/xgiebqwqoJz8rYPDi/O2BcZ++Wpt0Kq9cl0eg6NN6bYbPnR67ZLo7St5Q3UK0SnARw== dependencies: - undici-types "~7.8.0" + undici-types "~6.21.0" "@types/normalize-package-data@^2.4.0": version "2.4.4" @@ -1102,9 +1117,9 @@ abbrev@1: integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== acorn@^8.14.0: - version "8.15.0" - resolved "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz#a360898bc415edaac46c8241f6383975b930b816" - integrity sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg== + version "8.14.1" + resolved "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz#721d5dc10f7d5b5609a891773d47731796935dfb" + integrity sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg== add-stream@^1.0.0: version "1.0.0" @@ -1312,9 +1327,9 @@ before-after-hook@^2.2.0: integrity sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ== brace-expansion@^1.1.7: - version "1.1.12" - resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz#ab9b454466e5a8cc3a187beaad580412a9c5b843" - integrity sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg== + version "1.1.11" + resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== dependencies: balanced-match "^1.0.0" concat-map "0.0.1" @@ -1905,9 +1920,9 @@ error-ex@^1.3.1: is-arrayish "^0.2.1" es-abstract@^1.23.2, es-abstract@^1.23.5, es-abstract@^1.23.9: - version "1.24.0" - resolved "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.0.tgz#c44732d2beb0acc1ed60df840869e3106e7af328" - integrity sha512-WSzPgsdLtTcQwm4CROfS5ju2Wa1QQcVeT37jFjYzdFz1r9ahadC8B8/a4qxJxM+09F18iumCdRmlr96ZYkQvEg== + version "1.23.10" + resolved "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.10.tgz#84792c152ff2898ec73efe33c1c1323a3dfd87f8" + integrity sha512-MtUbM072wlJNyeYAe0mhzrD+M6DIJa96CZAOBBrhDbgKnB4MApIKefcyAB1eOdYn8cUNZgvwBvEzdoAYsxgEIw== dependencies: array-buffer-byte-length "^1.0.2" arraybuffer.prototype.slice "^1.0.4" @@ -1936,9 +1951,7 @@ es-abstract@^1.23.2, es-abstract@^1.23.5, es-abstract@^1.23.9: is-array-buffer "^3.0.5" is-callable "^1.2.7" is-data-view "^1.0.2" - is-negative-zero "^2.0.3" is-regex "^1.2.1" - is-set "^2.0.3" is-shared-array-buffer "^1.0.4" is-string "^1.1.1" is-typed-array "^1.1.15" @@ -1953,7 +1966,6 @@ es-abstract@^1.23.2, es-abstract@^1.23.5, es-abstract@^1.23.9: safe-push-apply "^1.0.0" safe-regex-test "^1.1.0" set-proto "^1.0.0" - stop-iteration-iterator "^1.1.0" string.prototype.trim "^1.2.10" string.prototype.trimend "^1.0.9" string.prototype.trimstart "^1.0.8" @@ -2815,11 +2827,6 @@ is-module@^1.0.0: resolved "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz#3258fb69f78c14d5b815d664336b4cffb6441591" integrity sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g== -is-negative-zero@^2.0.3: - version "2.0.3" - resolved "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz#ced903a027aca6381b777a5743069d7376a49747" - integrity sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw== - is-number-object@^1.1.1: version "1.1.1" resolved "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz#144b21e95a1bc148205dcc2814a9134ec41b2541" @@ -4653,9 +4660,9 @@ socks-proxy-agent@^6.0.0: socks "^2.6.2" socks@^2.3.3, socks@^2.6.2: - version "2.8.5" - resolved "https://registry.npmjs.org/socks/-/socks-2.8.5.tgz#bfe18f5ead1efc93f5ec90c79fa8bdccbcee2e64" - integrity sha512-iF+tNDQla22geJdTyJB1wM/qrX9DMRwWrciEPwWLPRWAUEM8sQiyxgckLxWT1f7+9VabJS0jTGGr4QgBuvi6Ww== + version "2.8.4" + resolved "https://registry.npmjs.org/socks/-/socks-2.8.4.tgz#07109755cdd4da03269bda4725baa061ab56d5cc" + integrity sha512-D3YaD0aRxR3mEcqnidIs7ReYJFVzWdd6fXJYUM8ixcQcJRGTka/b3saV0KflYhyVJXKhb947GndU35SxYNResQ== dependencies: ip-address "^9.0.5" smart-buffer "^4.2.0" @@ -4764,14 +4771,6 @@ ssri@^8.0.0, ssri@^8.0.1: dependencies: minipass "^3.1.1" -stop-iteration-iterator@^1.1.0: - version "1.1.0" - resolved "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz#f481ff70a548f6124d0312c3aa14cbfa7aa542ad" - integrity sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ== - dependencies: - es-errors "^1.3.0" - internal-slot "^1.1.0" - strict-uri-encode@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz#b9c7330c7042862f6b142dc274bbcc5866ce3546" @@ -4947,9 +4946,9 @@ temp-write@^4.0.0: uuid "^3.3.2" terser@^5.17.4: - version "5.43.1" - resolved "https://registry.npmjs.org/terser/-/terser-5.43.1.tgz#88387f4f9794ff1a29e7ad61fb2932e25b4fdb6d" - integrity sha512-+6erLbBm0+LROX2sPXlUYx/ux5PyE9K/a92Wrt6oA+WDAoFTdpHE5tCYCI5PNzq2y8df4rA+QgHLJuR4jNymsg== + version "5.40.0" + resolved "https://registry.npmjs.org/terser/-/terser-5.40.0.tgz#839a80db42bfee8340085f44ea99b5cba36c55c8" + integrity sha512-cfeKl/jjwSR5ar7d0FGmave9hFGJT8obyo0z+CrQOylLDbk7X81nPU6vq9VORa5jU30SkDnT2FXjLbR8HLP+xA== dependencies: "@jridgewell/source-map" "^0.3.3" acorn "^8.14.0" @@ -5149,10 +5148,10 @@ unbox-primitive@^1.1.0: has-symbols "^1.1.0" which-boxed-primitive "^1.1.1" -undici-types@~7.8.0: - version "7.8.0" - resolved "https://registry.npmjs.org/undici-types/-/undici-types-7.8.0.tgz#de00b85b710c54122e44fbfd911f8d70174cd294" - integrity sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw== +undici-types@~6.21.0: + version "6.21.0" + resolved "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz#691d00af3909be93a7faa13be61b3a5b50ef12cb" + integrity sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ== unique-filename@^1.1.1: version "1.1.1" From 9e78c4839ad3fd41a009183588410ea57e94104f Mon Sep 17 00:00:00 2001 From: mansisampat Date: Tue, 1 Jul 2025 14:41:19 +0530 Subject: [PATCH 5/5] Lint --- packages/auth/src/core/auth/auth_impl.test.ts | 24 ++++++++++++++----- 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/packages/auth/src/core/auth/auth_impl.test.ts b/packages/auth/src/core/auth/auth_impl.test.ts index 1611b270047..8b85ad01818 100644 --- a/packages/auth/src/core/auth/auth_impl.test.ts +++ b/packages/auth/src/core/auth/auth_impl.test.ts @@ -46,7 +46,10 @@ import { mockEndpointWithParams } from '../../../test/helpers/api/helper'; import { Endpoint, RecaptchaClientType, RecaptchaVersion } from '../../api'; import * as mockFetch from '../../../test/helpers/mock_fetch'; import { AuthErrorCode } from '../errors'; -import { FirebaseToken, PasswordValidationStatus } from '../../model/public_types'; +import { + FirebaseToken, + PasswordValidationStatus +} from '../../model/public_types'; import { PasswordPolicyImpl } from './password_policy_impl'; import { PersistenceUserManager } from '../persistence/persistence_user_manager'; @@ -176,7 +179,8 @@ describe('core/auth/auth_impl', () => { it('setting to null triggers persistence._remove', async () => { await auth._updateFirebaseToken(null); expect(persistenceStub._remove).to.have.been.calledWith( - 'firebase:persistence-token:api-key:test-app'); + 'firebase:persistence-token:api-key:test-app' + ); }); it('orders async updates correctly', async () => { @@ -211,7 +215,9 @@ describe('core/auth/auth_impl', () => { it('throws if persistence._remove fails', async () => { persistenceStub._remove.rejects(new Error('remove fail')); - await expect(auth._updateFirebaseToken(null)).to.be.rejectedWith('remove fail'); + await expect(auth._updateFirebaseToken(null)).to.be.rejectedWith( + 'remove fail' + ); }); }); @@ -263,7 +269,9 @@ describe('core/auth/auth_impl', () => { }); it('should load the firebaseToken from persistence and set it', async () => { - await authImpl._initializeWithPersistence([persistenceStub as PersistenceInternal]); + await authImpl._initializeWithPersistence([ + persistenceStub as PersistenceInternal + ]); expect(persistenceManager.getFirebaseToken).to.have.been.called; expect((authImpl as any).firebaseToken).to.eql(mockToken); @@ -273,7 +281,9 @@ describe('core/auth/auth_impl', () => { it('should set firebaseToken to null if getFirebaseToken returns undefined', async () => { persistenceManager.getFirebaseToken.resolves(undefined); - await authImpl._initializeWithPersistence([persistenceStub as PersistenceInternal]); + await authImpl._initializeWithPersistence([ + persistenceStub as PersistenceInternal + ]); expect((authImpl as any).firebaseToken).to.be.null; expect(subscription.next).to.have.been.calledWith(null); @@ -282,7 +292,9 @@ describe('core/auth/auth_impl', () => { it('should set firebaseToken to null if getFirebaseToken returns null', async () => { persistenceManager.getFirebaseToken.resolves(null); - await authImpl._initializeWithPersistence([persistenceStub as PersistenceInternal]); + await authImpl._initializeWithPersistence([ + persistenceStub as PersistenceInternal + ]); expect((authImpl as any).firebaseToken).to.be.null; expect(subscription.next).to.have.been.calledWith(null);