@@ -38,7 +38,9 @@ import {
3838 Unsubscribe ,
3939 PasswordValidationStatus ,
4040 TenantConfig ,
41- FirebaseToken
41+ FirebaseToken ,
42+ RefreshIdpTokenResult ,
43+ TokenRefreshHandler
4244} from '../../model/public_types' ;
4345import {
4446 createSubscribe ,
@@ -85,6 +87,7 @@ import { PasswordPolicyInternal } from '../../model/password_policy';
8587import { PasswordPolicyImpl } from './password_policy_impl' ;
8688import { getAccountInfo } from '../../api/account_management/account' ;
8789import { UserImpl } from '../user/user_impl' ;
90+ import { exchangeToken } from '../strategies/exhange_token' ;
8891
8992interface AsyncAction {
9093 ( ) : Promise < void > ;
@@ -102,6 +105,7 @@ export class AuthImpl implements AuthInternal, _FirebaseService {
102105 currentUser : User | null = null ;
103106 emulatorConfig : EmulatorConfig | null = null ;
104107 firebaseToken : FirebaseToken | null = null ;
108+ private tokenRefreshHandler ?: TokenRefreshHandler ;
105109 private operations = Promise . resolve ( ) ;
106110 private persistenceManager ?: PersistenceUserManager ;
107111 private redirectPersistenceManager ?: PersistenceUserManager ;
@@ -112,6 +116,7 @@ export class AuthImpl implements AuthInternal, _FirebaseService {
112116 private redirectUser : UserInternal | null = null ;
113117 private isProactiveRefreshEnabled = false ;
114118 private readonly EXPECTED_PASSWORD_POLICY_SCHEMA_VERSION : number = 1 ;
119+ private readonly TOKEN_EXPIRATION_BUFFER = 30_000 ;
115120
116121 // Any network calls will set this to true and prevent subsequent emulator
117122 // initialization
@@ -210,6 +215,10 @@ export class AuthImpl implements AuthInternal, _FirebaseService {
210215 return this . _initializationPromise ;
211216 }
212217
218+ setTokenRefreshHandler ( tokenRefreshHandler : TokenRefreshHandler ) : void {
219+ this . tokenRefreshHandler = tokenRefreshHandler ;
220+ }
221+
213222 /**
214223 * If the persistence is changed in another window, the user manager will let us know
215224 */
@@ -240,6 +249,35 @@ export class AuthImpl implements AuthInternal, _FirebaseService {
240249 await this . _updateCurrentUser ( user , /* skipBeforeStateCallbacks */ true ) ;
241250 }
242251
252+ async getFirebaseAccessToken ( forceRefresh ?: boolean ) :
253+ Promise < FirebaseToken | null > {
254+ const firebaseAccessToken =
255+ ( await this . persistenceManager ?. getFirebaseToken ( ) ) ?? null ;
256+
257+ if (
258+ firebaseAccessToken &&
259+ this . isFirebaseAccessTokenValid ( firebaseAccessToken ) &&
260+ ! forceRefresh
261+ ) {
262+ this . firebaseToken = firebaseAccessToken ;
263+ this . firebaseTokenSubscription . next ( this . firebaseToken ) ;
264+ return firebaseAccessToken ;
265+ }
266+
267+ if ( firebaseAccessToken && this . tokenRefreshHandler ) {
268+ // Resets the Firebase Access Token to null i.e. logs out the user.
269+ await this . _updateFirebaseToken ( null ) ;
270+ // Awaits for the callback method to execute. The callback method
271+ // is responsible for performing the exchangeToken(auth, valid3pIdpToken)
272+ const result : RefreshIdpTokenResult = await this . tokenRefreshHandler . refreshIdpToken ( ) ;
273+ _assert ( result . idToken && result . idpConfigId , AuthErrorCode . INVALID_CREDENTIAL ) ;
274+ await exchangeToken ( this , result . idpConfigId , result . idToken ) ;
275+ return this . getFirebaseAccessToken ( false ) ;
276+ }
277+
278+ return null ;
279+ }
280+
243281 private async initializeCurrentUserFromIdToken (
244282 idToken : string
245283 ) : Promise < void > {
@@ -405,6 +443,20 @@ export class AuthImpl implements AuthInternal, _FirebaseService {
405443 return this . directlySetCurrentUser ( user ) ;
406444 }
407445
446+ private isFirebaseAccessTokenValid (
447+ firebaseToken : FirebaseToken | null
448+ ) : boolean {
449+ if (
450+ firebaseToken &&
451+ firebaseToken . expirationTime &&
452+ ( Date . now ( ) >
453+ firebaseToken . expirationTime - this . TOKEN_EXPIRATION_BUFFER )
454+ ) {
455+ return false ;
456+ }
457+ return true ;
458+ }
459+
408460 private async initializeFirebaseToken ( ) : Promise < void > {
409461 this . firebaseToken =
410462 ( await this . persistenceManager ?. getFirebaseToken ( ) ) ?? null ;
0 commit comments