11import axios from 'axios' ;
22import { setErrorMessage } from 'common/notification' ;
33
4- import { RENEW_TOKEN , VITE_GLIFIC_AUTHENTICATION_API } from 'config' ;
4+ import { VITE_GLIFIC_AUTHENTICATION_API } from 'config' ;
55import setLogs from 'config/logs' ;
6+ import { tokenRenewalManager } from './TokenRenewalService' ;
67
78interface RegisterRequest {
89 phone : string ;
@@ -51,40 +52,34 @@ export const getAuthSession = (element?: string) => {
5152} ;
5253
5354// service to auto renew the auth token based on valid refresh token
54- export const renewAuthToken = ( ) => {
55- const renewalToken = getAuthSession ( 'renewal_token' ) ;
56- if ( ! renewalToken ) {
57- setLogs ( 'Token renewal failed: not found' , 'error' ) ;
58- return new Error ( 'Error' ) ;
59- }
60- // get the renewal token from session
61- axios . defaults . headers . common . authorization = renewalToken ;
62-
63- return axios
64- . post ( RENEW_TOKEN )
65- . then ( ( response : any ) => response )
66- . catch ( ( error : any ) => {
67- // if we are not able to renew the token for some weird reason or if refresh token
68- throw error ;
69- } ) ;
70- } ;
55+ // delegates this to TokenRenewalManager to prevent race conditions
56+ export const renewAuthToken = ( ) => tokenRenewalManager . renewToken ( ) ;
7157
7258// service to check the validity of the auth / token status
59+ // uses a 30sec buffer to proactively renew tokens before they expire
60+ // this prevents mid request token expirations
7361export const checkAuthStatusService = ( ) => {
7462 let authStatus = false ;
7563 const tokenExpiryTimeFromSession = getAuthSession ( 'token_expiry_time' ) ;
64+
7665 // return false if there is no session on local
7766 if ( ! tokenExpiryTimeFromSession ) {
7867 authStatus = false ;
7968 } else {
8069 const tokenExpiryTime = new Date ( tokenExpiryTimeFromSession ) ;
81- // compare the session token with the current time
82- if ( tokenExpiryTime > new Date ( ) ) {
83- // token is still valid return true
70+ const now = new Date ( ) ;
71+ const bufferMs = 30 * 1000 ; // 30 seconds buffer
72+
73+ // consider token invalid if it expires within the next 30 seconds
74+ // this ensures we renew tokens proactively before they actually expire
75+ if ( tokenExpiryTime . getTime ( ) - now . getTime ( ) > bufferMs ) {
76+ // token is still valid (with buffer) return true
8477 authStatus = true ;
78+ setLogs ( `Token valid. Expires in ${ Math . floor ( ( tokenExpiryTime . getTime ( ) - now . getTime ( ) ) / 1000 ) } s` , 'info' ) ;
8579 } else {
86- // this means token has expired and let's return false
80+ // this means token has expired or is about to expire
8781 authStatus = false ;
82+ setLogs ( 'Token expired or expiring soon (within 30s), renewal required' , 'info' ) ;
8883 }
8984 }
9085 return authStatus ;
@@ -192,37 +187,24 @@ export const getOrganizationServices = (service: ServiceType) => {
192187
193188export const setAuthHeaders = ( ) => {
194189 // add authorization header in all calls
195- let renewTokenCalled = false ;
196- let renewCallInProgress = false ;
197-
198190 const { fetch } = window ;
199191 window . fetch = ( ...args ) =>
200192 ( async ( parameters ) => {
201193 const parametersCopy = parameters ;
202- if ( checkAuthStatusService ( ) ) {
203- if ( parametersCopy [ 1 ] ) {
204- parametersCopy [ 1 ] . headers = {
205- ...parametersCopy [ 1 ] . headers ,
206- authorization : getAuthSession ( 'access_token' ) ,
207- } ;
208- }
209- // @ts -ignore
210- const result = await fetch ( ...parametersCopy ) ;
211- return result ;
212- }
213- renewTokenCalled = true ;
214- const authToken = await renewAuthToken ( ) ;
215- if ( authToken . data ) {
216- // update localstore
217- setAuthSession ( authToken . data . data ) ;
218- renewTokenCalled = false ;
194+
195+ // check if token is valid (or renew if needed)
196+ if ( ! checkAuthStatusService ( ) ) {
197+ setLogs ( 'Fetch: Token invalid, triggering renewal' , 'info' ) ;
198+ await renewAuthToken ( ) ;
219199 }
200+
220201 if ( parametersCopy [ 1 ] ) {
221202 parametersCopy [ 1 ] . headers = {
222203 ...parametersCopy [ 1 ] . headers ,
223204 authorization : getAuthSession ( 'access_token' ) ,
224205 } ;
225206 }
207+
226208 // @ts -ignore
227209 const result = await fetch ( ...parametersCopy ) ;
228210 return result ;
@@ -240,6 +222,7 @@ export const setAuthHeaders = () => {
240222 username ?: string | null ,
241223 password ?: string | null
242224 ) {
225+ // mark renewal endpoint calls to prevent infinite loops
243226 if ( url . toString ( ) . endsWith ( 'renew' ) ) {
244227 // @ts -ignore
245228 this . renewGlificCall = true ;
@@ -251,35 +234,26 @@ export const setAuthHeaders = () => {
251234 ( ( send ) => {
252235 XMLHttpRequest . prototype . send = async function authCheck ( body ) {
253236 this . addEventListener ( 'loadend' , ( ) => {
237+ // handle 401 errors by logging out
254238 // @ts -ignore
255- if ( this . renewGlificCall ) {
256- renewCallInProgress = false ;
257- } else if ( this . status === 401 ) {
239+ if ( ! this . renewGlificCall && this . status === 401 ) {
240+ setLogs ( 'XMLHttpRequest: Received 401, logging out' , 'error' ) ;
258241 window . location . href = '/logout/user' ;
259242 }
260243 } ) ;
261244
262245 // @ts -ignore
263- if ( this . renewGlificCall && ! renewCallInProgress ) {
264- renewCallInProgress = true ;
246+ if ( this . renewGlificCall ) {
247+ // this is the renewal endpoint itself - don't add auth or trigger renewal
248+ // to prevent infinite loops
265249 send . call ( this , body ) ;
266- }
267- // @ts -ignore
268- else if ( this . renewGlificCall ) {
269- this . abort ( ) ;
270- }
271- // @ts -ignore
272- else if ( checkAuthStatusService ( ) ) {
273- this . setRequestHeader ( 'authorization' , getAuthSession ( 'access_token' ) ) ;
274- send . call ( this , body ) ;
275- } else if ( ! renewTokenCalled ) {
276- renewTokenCalled = true ;
277- const authToken = await renewAuthToken ( ) ;
278- if ( authToken . data ) {
279- // update localstore
280- setAuthSession ( authToken . data . data ) ;
281- renewTokenCalled = false ;
250+ } else {
251+ // regular request - check token and renew if needed
252+ if ( ! checkAuthStatusService ( ) ) {
253+ setLogs ( 'XMLHttpRequest: Token invalid, triggering renewal' , 'info' ) ;
254+ await renewAuthToken ( ) ;
282255 }
256+
283257 this . setRequestHeader ( 'authorization' , getAuthSession ( 'access_token' ) ) ;
284258 send . call ( this , body ) ;
285259 }
0 commit comments