@@ -49,7 +49,7 @@ import {
49
49
Subscribe
50
50
} from '@firebase/util' ;
51
51
52
- import { AuthInternal , ConfigInternal } from '../../model/auth' ;
52
+ import { AuthInternal , ConfigInternal , TokenRefreshHandler } from '../../model/auth' ;
53
53
import { PopupRedirectResolverInternal } from '../../model/popup_redirect' ;
54
54
import { UserInternal } from '../../model/user' ;
55
55
import {
@@ -102,6 +102,7 @@ export class AuthImpl implements AuthInternal, _FirebaseService {
102
102
currentUser : User | null = null ;
103
103
emulatorConfig : EmulatorConfig | null = null ;
104
104
firebaseToken : FirebaseToken | null = null ;
105
+ tokenRefreshHandler ?: TokenRefreshHandler ;
105
106
private operations = Promise . resolve ( ) ;
106
107
private persistenceManager ?: PersistenceUserManager ;
107
108
private redirectPersistenceManager ?: PersistenceUserManager ;
@@ -112,6 +113,7 @@ export class AuthImpl implements AuthInternal, _FirebaseService {
112
113
private redirectUser : UserInternal | null = null ;
113
114
private isProactiveRefreshEnabled = false ;
114
115
private readonly EXPECTED_PASSWORD_POLICY_SCHEMA_VERSION : number = 1 ;
116
+ private readonly TOKEN_EXPIRATION_BUFFER = 30_000 ;
115
117
116
118
// Any network calls will set this to true and prevent subsequent emulator
117
119
// initialization
@@ -159,6 +161,10 @@ export class AuthImpl implements AuthInternal, _FirebaseService {
159
161
this . tenantConfig = tenantConfig ;
160
162
}
161
163
164
+ setTokenRefreshHandler ( tokenRefreshHandler : TokenRefreshHandler ) : void {
165
+ this . tokenRefreshHandler = tokenRefreshHandler ;
166
+ }
167
+
162
168
_initializeWithPersistence (
163
169
persistenceHierarchy : PersistenceInternal [ ] ,
164
170
popupRedirectResolver ?: PopupRedirectResolver
@@ -196,7 +202,7 @@ export class AuthImpl implements AuthInternal, _FirebaseService {
196
202
}
197
203
198
204
await this . initializeCurrentUser ( popupRedirectResolver ) ;
199
- await this . initializeFirebaseToken ( ) ;
205
+ this . firebaseToken = await this . getFirebaseAccessToken ( false ) ;
200
206
201
207
this . lastNotifiedUid = this . currentUser ?. uid || null ;
202
208
@@ -210,6 +216,33 @@ export class AuthImpl implements AuthInternal, _FirebaseService {
210
216
return this . _initializationPromise ;
211
217
}
212
218
219
+ async getFirebaseAccessToken ( forceRefresh ?: boolean ) :
220
+ Promise < FirebaseToken | null > {
221
+ const firebaseAccessToken =
222
+ ( await this . persistenceManager ?. getFirebaseToken ( ) ) ?? null ;
223
+
224
+ if (
225
+ firebaseAccessToken &&
226
+ this . isFirebaseAccessTokenValid ( firebaseAccessToken ) &&
227
+ ! forceRefresh
228
+ ) {
229
+ this . firebaseToken = firebaseAccessToken ;
230
+ this . firebaseTokenSubscription . next ( this . firebaseToken ) ;
231
+ return firebaseAccessToken ;
232
+ }
233
+
234
+ if ( firebaseAccessToken && this . tokenRefreshHandler ) {
235
+ // Resets the Firebase Access Token to null i.e. logs out the user.
236
+ await this . _updateFirebaseToken ( null ) ;
237
+ // Awaits for the callback method to execute. The callback method
238
+ // is responsible for performing the exchangeToken(auth, valid3pIdpToken)
239
+ await this . tokenRefreshHandler . refreshToken ( ) ;
240
+ return this . getFirebaseAccessToken ( false ) ;
241
+ }
242
+
243
+ return null ;
244
+ }
245
+
213
246
/**
214
247
* If the persistence is changed in another window, the user manager will let us know
215
248
*/
@@ -240,6 +273,20 @@ export class AuthImpl implements AuthInternal, _FirebaseService {
240
273
await this . _updateCurrentUser ( user , /* skipBeforeStateCallbacks */ true ) ;
241
274
}
242
275
276
+ private isFirebaseAccessTokenValid (
277
+ firebaseToken : FirebaseToken | null
278
+ ) : boolean {
279
+ if (
280
+ firebaseToken &&
281
+ firebaseToken . expirationTime &&
282
+ ( Date . now ( ) >
283
+ firebaseToken . expirationTime - this . TOKEN_EXPIRATION_BUFFER )
284
+ ) {
285
+ return false ;
286
+ }
287
+ return true ;
288
+ }
289
+
243
290
private async initializeCurrentUserFromIdToken (
244
291
idToken : string
245
292
) : Promise < void > {
0 commit comments