@@ -7,7 +7,7 @@ import { useCallback, useEffect, useState } from "react";
77import { getSecondsUntilExpiration } from "@/lib/time" ;
88import { User } from "@/lib/types" ;
99import { mockedRefreshToken , refreshToken } from "./refreshUtils" ;
10- import { CUSTOM_REFRESH_URL } from "@/lib/constants" ;
10+ import { NEXT_PUBLIC_CUSTOM_REFRESH_URL } from "@/lib/constants" ;
1111
1212export const HealthCheckBanner = ( ) => {
1313 const { error } = useSWR ( "/api/health" , errorHandlingFetcher ) ;
@@ -35,57 +35,89 @@ export const HealthCheckBanner = () => {
3535 } , [ user , updateExpirationTime ] ) ;
3636
3737 useEffect ( ( ) => {
38- if ( CUSTOM_REFRESH_URL ) {
39- const refreshUrl = CUSTOM_REFRESH_URL ;
40- let refreshTimeoutId : NodeJS . Timeout ;
38+ if ( NEXT_PUBLIC_CUSTOM_REFRESH_URL ) {
39+ const refreshUrl = NEXT_PUBLIC_CUSTOM_REFRESH_URL ;
40+ let refreshIntervalId : NodeJS . Timer ;
4141 let expireTimeoutId : NodeJS . Timeout ;
4242
4343 const attemptTokenRefresh = async ( ) => {
44- try {
45- // NOTE: This is a mocked refresh token for testing purposes.
46- // const refreshTokenData = mockedRefreshToken();
47-
48- const refreshTokenData = await refreshToken ( refreshUrl ) ;
49-
50- const response = await fetch (
51- "/api/enterprise-settings/refresh-token" ,
52- {
53- method : "POST" ,
54- headers : {
55- "Content-Type" : "application/json" ,
56- } ,
57- body : JSON . stringify ( refreshTokenData ) ,
44+ let retryCount = 0 ;
45+ const maxRetries = 3 ;
46+
47+ while ( retryCount < maxRetries ) {
48+ try {
49+ // NOTE: This is a mocked refresh token for testing purposes.
50+ // const refreshTokenData = mockedRefreshToken();
51+
52+ const refreshTokenData = await refreshToken ( refreshUrl ) ;
53+ if ( ! refreshTokenData ) {
54+ throw new Error ( "Failed to refresh token" ) ;
5855 }
59- ) ;
60- if ( ! response . ok ) {
61- throw new Error ( `HTTP error! status: ${ response . status } ` ) ;
62- }
63- await new Promise ( ( resolve ) => setTimeout ( resolve , 4000 ) ) ;
6456
65- await mutateUser ( undefined , { revalidate : true } ) ;
66- updateExpirationTime ( ) ;
67- } catch ( error ) {
68- console . error ( "Error refreshing token:" , error ) ;
57+ const response = await fetch (
58+ "/api/enterprise-settings/refresh-token" ,
59+ {
60+ method : "POST" ,
61+ headers : {
62+ "Content-Type" : "application/json" ,
63+ } ,
64+ body : JSON . stringify ( refreshTokenData ) ,
65+ }
66+ ) ;
67+ if ( ! response . ok ) {
68+ throw new Error ( `HTTP error! status: ${ response . status } ` ) ;
69+ }
70+ await new Promise ( ( resolve ) => setTimeout ( resolve , 4000 ) ) ;
71+
72+ await mutateUser ( undefined , { revalidate : true } ) ;
73+ updateExpirationTime ( ) ;
74+ break ; // Success - exit the retry loop
75+ } catch ( error ) {
76+ console . error (
77+ `Error refreshing token (attempt ${
78+ retryCount + 1
79+ } /${ maxRetries } ):`,
80+ error
81+ ) ;
82+ retryCount ++ ;
83+
84+ if ( retryCount === maxRetries ) {
85+ console . error ( "Max retry attempts reached" ) ;
86+ } else {
87+ // Wait before retrying (exponential backoff)
88+ await new Promise ( ( resolve ) =>
89+ setTimeout ( resolve , Math . pow ( 2 , retryCount ) * 1000 )
90+ ) ;
91+ }
92+ }
6993 }
7094 } ;
7195
7296 const scheduleRefreshAndExpire = ( ) => {
7397 if ( secondsUntilExpiration !== null ) {
74- const timeUntilRefresh = ( secondsUntilExpiration + 0.5 ) * 1000 ;
75- refreshTimeoutId = setTimeout ( attemptTokenRefresh , timeUntilRefresh ) ;
98+ const refreshInterval = 60 * 15 ; // 15 mins
99+ refreshIntervalId = setInterval (
100+ attemptTokenRefresh ,
101+ refreshInterval * 1000
102+ ) ;
76103
77104 const timeUntilExpire = ( secondsUntilExpiration + 10 ) * 1000 ;
78105 expireTimeoutId = setTimeout ( ( ) => {
79106 console . debug ( "Session expired. Setting expired state to true." ) ;
80107 setExpired ( true ) ;
81108 } , timeUntilExpire ) ;
109+
110+ // if we're going to timeout before the next refresh, kick off a refresh now!
111+ if ( secondsUntilExpiration < refreshInterval ) {
112+ attemptTokenRefresh ( ) ;
113+ }
82114 }
83115 } ;
84116
85117 scheduleRefreshAndExpire ( ) ;
86118
87119 return ( ) => {
88- clearTimeout ( refreshTimeoutId ) ;
120+ clearInterval ( refreshIntervalId ) ;
89121 clearTimeout ( expireTimeoutId ) ;
90122 } ;
91123 }
0 commit comments