@@ -21,8 +21,12 @@ import {
2121 AppCheckTokenResult ,
2222 AppCheckTokenListener
2323} from '@firebase/app-check-interop-types' ;
24- import { AppCheckToken } from '@firebase/app-check-types' ;
25- import { getDebugState , getState , setState } from './state' ;
24+ import {
25+ AppCheckTokenInternal ,
26+ getDebugState ,
27+ getState ,
28+ setState
29+ } from './state' ;
2630import { TOKEN_REFRESH_TIME } from './constants' ;
2731import { Refresher } from './proactive-refresh' ;
2832import { ensureActivated } from './util' ;
@@ -70,15 +74,15 @@ export async function getToken(
7074 * return the debug token directly
7175 */
7276 if ( isDebugMode ( ) ) {
73- const tokenFromDebugExchange : AppCheckToken = await exchangeToken (
77+ const tokenFromDebugExchange : AppCheckTokenInternal = await exchangeToken (
7478 getExchangeDebugTokenRequest ( app , await getDebugToken ( ) )
7579 ) ;
7680 return { token : tokenFromDebugExchange . token } ;
7781 }
7882
7983 const state = getState ( app ) ;
8084
81- let token : AppCheckToken | undefined = state . token ;
85+ let token : AppCheckTokenInternal | undefined = state . token ;
8286 let error : Error | undefined = undefined ;
8387
8488 /**
@@ -108,7 +112,8 @@ export async function getToken(
108112 */
109113 try {
110114 if ( state . customProvider ) {
111- token = await state . customProvider . getToken ( ) ;
115+ const customToken = await state . customProvider . getToken ( ) ;
116+ token = { ...customToken , issuedAtTimeMillis : Date . now ( ) } ;
112117 } else {
113118 const attestedClaimsToken = await getReCAPTCHAToken ( app ) . catch ( _e => {
114119 // reCaptcha.execute() throws null which is not very descriptive.
@@ -178,7 +183,12 @@ export function addTokenListener(
178183 newState . tokenRefresher = tokenRefresher ;
179184 }
180185
181- if ( ! newState . tokenRefresher . isRunning ( ) ) {
186+ // Create the refresher but don't start it if `isTokenAutoRefreshEnabled`
187+ // is not true.
188+ if (
189+ ! newState . tokenRefresher . isRunning ( ) &&
190+ state . isTokenAutoRefreshEnabled === true
191+ ) {
182192 newState . tokenRefresher . start ( ) ;
183193 }
184194
@@ -245,12 +255,20 @@ function createTokenRefresher(app: FirebaseApp): Refresher {
245255 const state = getState ( app ) ;
246256
247257 if ( state . token ) {
248- return Math . max (
249- 0 ,
250- state . token . expireTimeMillis -
251- Date . now ( ) -
252- TOKEN_REFRESH_TIME . OFFSET_DURATION
258+ // issuedAtTime + (50% * total TTL) + 5 minutes
259+ let nextRefreshTimeMillis =
260+ state . token . issuedAtTimeMillis +
261+ ( state . token . expireTimeMillis - state . token . issuedAtTimeMillis ) *
262+ 0.5 +
263+ 5 * 60 * 1000 ;
264+ // Do not allow refresh time to be past (expireTime - 5 minutes)
265+ const latestAllowableRefresh =
266+ state . token . expireTimeMillis - 5 * 60 * 1000 ;
267+ nextRefreshTimeMillis = Math . min (
268+ nextRefreshTimeMillis ,
269+ latestAllowableRefresh
253270 ) ;
271+ return Math . max ( 0 , nextRefreshTimeMillis - Date . now ( ) ) ;
254272 } else {
255273 return 0 ;
256274 }
@@ -275,7 +293,7 @@ function notifyTokenListeners(
275293 }
276294}
277295
278- function isValid ( token : AppCheckToken ) : boolean {
296+ function isValid ( token : AppCheckTokenInternal ) : boolean {
279297 return token . expireTimeMillis - Date . now ( ) > 0 ;
280298}
281299
0 commit comments