From 010e0cc2aac13d3eb53f9ab6481ea6b313dc44bb Mon Sep 17 00:00:00 2001 From: mansisampat Date: Wed, 25 Jun 2025 11:39:42 +0530 Subject: [PATCH 1/2] Maintain persistence for firebaseToken in AuthImpl object --- packages/auth/demo/yarn.lock | 101 ++++++++++++++++++----------------- 1 file changed, 51 insertions(+), 50 deletions(-) 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" From 0a551868a1ffff24270d2496f74a2a3d4add34a2 Mon Sep 17 00:00:00 2001 From: mansisampat Date: Wed, 9 Jul 2025 10:38:59 +0530 Subject: [PATCH 2/2] Expose a callback function that is triggered for token refresh --- packages/auth/demo/src/index.js | 10 ++++ packages/auth/src/core/auth/auth_impl.ts | 51 ++++++++++++++++++- .../auth/src/core/auth/firebase_internal.ts | 37 +++++++++++++- packages/auth/src/model/auth.ts | 6 +++ 4 files changed, 101 insertions(+), 3 deletions(-) diff --git a/packages/auth/demo/src/index.js b/packages/auth/demo/src/index.js index b04fafe2a98..3cc0bf1bde2 100644 --- a/packages/auth/demo/src/index.js +++ b/packages/auth/demo/src/index.js @@ -149,6 +149,14 @@ async function getActiveUserBlocking() { } } +class TokenRefreshHandlerImpl { + refreshToken() { + log("inside here"); + console.log("inside handler"); + return; + } +} + /** * Refreshes the current user data in the UI, displaying a user info box if * a user is signed in, or removing it. @@ -2090,6 +2098,8 @@ function initApp() { popupRedirectResolver: browserPopupRedirectResolver, tenantConfig: tenantConfig }); + const tokenRefreshHandler = new TokenRefreshHandlerImpl(); + regionalAuth.setTokenRefreshHandler(tokenRefreshHandler); tempApp = initializeApp( { diff --git a/packages/auth/src/core/auth/auth_impl.ts b/packages/auth/src/core/auth/auth_impl.ts index 96517615cbf..ab6010d0b66 100644 --- a/packages/auth/src/core/auth/auth_impl.ts +++ b/packages/auth/src/core/auth/auth_impl.ts @@ -49,7 +49,7 @@ import { Subscribe } from '@firebase/util'; -import { AuthInternal, ConfigInternal } from '../../model/auth'; +import { AuthInternal, ConfigInternal, TokenRefreshHandler } from '../../model/auth'; import { PopupRedirectResolverInternal } from '../../model/popup_redirect'; import { UserInternal } from '../../model/user'; import { @@ -102,6 +102,7 @@ export class AuthImpl implements AuthInternal, _FirebaseService { currentUser: User | null = null; emulatorConfig: EmulatorConfig | null = null; firebaseToken: FirebaseToken | null = null; + tokenRefreshHandler?: TokenRefreshHandler; private operations = Promise.resolve(); private persistenceManager?: PersistenceUserManager; private redirectPersistenceManager?: PersistenceUserManager; @@ -112,6 +113,7 @@ export class AuthImpl implements AuthInternal, _FirebaseService { private redirectUser: UserInternal | null = null; private isProactiveRefreshEnabled = false; private readonly EXPECTED_PASSWORD_POLICY_SCHEMA_VERSION: number = 1; + private readonly TOKEN_EXPIRATION_BUFFER = 30_000; // Any network calls will set this to true and prevent subsequent emulator // initialization @@ -159,6 +161,10 @@ export class AuthImpl implements AuthInternal, _FirebaseService { this.tenantConfig = tenantConfig; } + setTokenRefreshHandler(tokenRefreshHandler: TokenRefreshHandler): void { + this.tokenRefreshHandler = tokenRefreshHandler; + } + _initializeWithPersistence( persistenceHierarchy: PersistenceInternal[], popupRedirectResolver?: PopupRedirectResolver @@ -196,7 +202,7 @@ export class AuthImpl implements AuthInternal, _FirebaseService { } await this.initializeCurrentUser(popupRedirectResolver); - await this.initializeFirebaseToken(); + this.firebaseToken = await this.getFirebaseAccessToken(false); this.lastNotifiedUid = this.currentUser?.uid || null; @@ -210,6 +216,33 @@ export class AuthImpl implements AuthInternal, _FirebaseService { return this._initializationPromise; } + async getFirebaseAccessToken(forceRefresh?: boolean): + Promise { + const firebaseAccessToken = + (await this.persistenceManager?.getFirebaseToken()) ?? null; + + if ( + firebaseAccessToken && + this.isFirebaseAccessTokenValid(firebaseAccessToken) && + !forceRefresh + ) { + this.firebaseToken = firebaseAccessToken; + this.firebaseTokenSubscription.next(this.firebaseToken); + return firebaseAccessToken; + } + + if (firebaseAccessToken && this.tokenRefreshHandler) { + // Resets the Firebase Access Token to null i.e. logs out the user. + await this._updateFirebaseToken(null); + // Awaits for the callback method to execute. The callback method + // is responsible for performing the exchangeToken(auth, valid3pIdpToken) + await this.tokenRefreshHandler.refreshToken(); + return this.getFirebaseAccessToken(false); + } + + return null; + } + /** * If the persistence is changed in another window, the user manager will let us know */ @@ -240,6 +273,20 @@ export class AuthImpl implements AuthInternal, _FirebaseService { await this._updateCurrentUser(user, /* skipBeforeStateCallbacks */ true); } + private isFirebaseAccessTokenValid( + firebaseToken: FirebaseToken | null + ): boolean { + if( + firebaseToken && + firebaseToken.expirationTime && + (Date.now() > + firebaseToken.expirationTime - this.TOKEN_EXPIRATION_BUFFER) + ) { + return false; + } + return true; + } + private async initializeCurrentUserFromIdToken( idToken: string ): Promise { diff --git a/packages/auth/src/core/auth/firebase_internal.ts b/packages/auth/src/core/auth/firebase_internal.ts index caf06c49f6a..5738d6ae87d 100644 --- a/packages/auth/src/core/auth/firebase_internal.ts +++ b/packages/auth/src/core/auth/firebase_internal.ts @@ -28,10 +28,17 @@ interface TokenListener { (tok: string | null): unknown; } +// interface FirebaseAccessTokenRefreshListener { +// (tok: string | null): unknown; +// } + export class AuthInterop implements FirebaseAuthInternal { private readonly TOKEN_EXPIRATION_BUFFER = 30_000; private readonly internalListeners: Map = new Map(); + // private readonly firebaseAccessTokenRefreshListeners: + // Map = + // new Map(); constructor(private readonly auth: AuthInternal) {} @@ -51,7 +58,11 @@ export class AuthInterop implements FirebaseAuthInternal { 'Refresh token is not a valid operation for Regional Auth instance initialized.' ); } - return this.getTokenForRegionalAuth(); + const firebaseAccessToken = (await this.auth.getFirebaseAccessToken())?.token + if (!firebaseAccessToken) { + return null; + } + return { accessToken: firebaseAccessToken ?? null}; } if (!this.auth.currentUser) { return null; @@ -76,6 +87,23 @@ export class AuthInterop implements FirebaseAuthInternal { this.updateProactiveRefresh(); } + // addFirebaseAccessTokenRefreshListener( + // listener: FirebaseAccessTokenRefreshListener): void { + // this.assertAuthConfigured(); + // this.assertRegionalAuthConfigured(); + // if (this.firebaseAccessTokenRefreshListeners.has(listener)) { + // return; + // } + + // const unsubscribe = this.auth.onFirebaseAccessTokenRefreshTriggered( + // firebaseAccessToken => { + // listener( + // (firebaseAccessToken as FirebaseToken)?.token || null + // ); + // }); + // this.firebaseAccessTokenRefreshListeners.set(listener, unsubscribe); + // } + removeAuthTokenListener(listener: TokenListener): void { this.assertAuthConfigured(); const unsubscribe = this.internalListeners.get(listener); @@ -95,6 +123,13 @@ export class AuthInterop implements FirebaseAuthInternal { ); } + // private assertRegionalAuthConfigured(): void { + // _assert( + // this.auth.tenantConfig, + // AuthErrorCode.DEPENDENT_SDK_INIT_BEFORE_AUTH) + // ; + // } + private updateProactiveRefresh(): void { if (this.internalListeners.size > 0) { this.auth._startProactiveRefresh(); diff --git a/packages/auth/src/model/auth.ts b/packages/auth/src/model/auth.ts index ea9f4b203d2..79baaf4e20a 100644 --- a/packages/auth/src/model/auth.ts +++ b/packages/auth/src/model/auth.ts @@ -58,6 +58,10 @@ export interface ConfigInternal extends Config { clientPlatform: ClientPlatform; } +export interface TokenRefreshHandler { + refreshToken(): void | Promise +} + /** * UserInternal and AuthInternal reference each other, so both of them are included in the public typings. * In order to exclude them, we mark them as internal explicitly. @@ -67,6 +71,7 @@ export interface ConfigInternal extends Config { export interface AuthInternal extends Auth { currentUser: User | null; emulatorConfig: EmulatorConfig | null; + tokenRefreshHandler?: TokenRefreshHandler; _agentRecaptchaConfig: RecaptchaConfig | null; _tenantRecaptchaConfigs: Record; _projectPasswordPolicy: PasswordPolicy | null; @@ -75,6 +80,7 @@ export interface AuthInternal extends Auth { _isInitialized: boolean; _initializationPromise: Promise | null; _persistenceManagerAvailable: Promise; + getFirebaseAccessToken(forceRefresh?: boolean): Promise; _updateCurrentUser(user: UserInternal | null): Promise; _updateFirebaseToken(firebaseToken: FirebaseToken | null): Promise;