mirror of
				https://github.com/open-metadata/OpenMetadata.git
				synced 2025-10-26 00:04:52 +00:00 
			
		
		
		
	fix: google refresh token silent callback (#10010)
* fix: google refresh token silent callback * refactor: update axios interceptor reference in context * refactor: address review comments
This commit is contained in:
		
							parent
							
								
									c81446e2be
								
							
						
					
					
						commit
						97ea3608bd
					
				| @ -18,7 +18,7 @@ import { MsalProvider } from '@azure/msal-react'; | ||||
| import { LoginCallback } from '@okta/okta-react'; | ||||
| import { AxiosError } from 'axios'; | ||||
| import { CookieStorage } from 'cookie-storage'; | ||||
| import { isEmpty, isNil } from 'lodash'; | ||||
| import { isEmpty, isNil, isNumber } from 'lodash'; | ||||
| import { observer } from 'mobx-react'; | ||||
| import React, { | ||||
|   ComponentType, | ||||
| @ -43,7 +43,6 @@ import { AuthenticationConfiguration } from '../../../generated/configuration/au | ||||
| import { AuthType, User } from '../../../generated/entity/teams/user'; | ||||
| import jsonData from '../../../jsons/en'; | ||||
| import { | ||||
|   EXPIRY_THRESHOLD_MILLES, | ||||
|   extractDetailsFromToken, | ||||
|   getAuthConfig, | ||||
|   getNameFromEmail, | ||||
| @ -87,6 +86,9 @@ const userAPIQueryFields = 'profile,teams,roles'; | ||||
| 
 | ||||
| const isEmailVerifyField = 'isEmailVerified'; | ||||
| 
 | ||||
| let requestInterceptor: number | null = null; | ||||
| let responseInterceptor: number | null = null; | ||||
| 
 | ||||
| export const AuthProvider = ({ | ||||
|   childComponentType, | ||||
|   children, | ||||
| @ -242,26 +244,15 @@ export const AuthProvider = ({ | ||||
|    * Renew Id Token handler for all the SSOs. | ||||
|    * This method will be called when the id token is about to expire. | ||||
|    */ | ||||
|   const renewIdToken = (): Promise<string> => { | ||||
|   const renewIdToken = async () => { | ||||
|     try { | ||||
|       const onRenewIdTokenHandlerPromise = onRenewIdTokenHandler(); | ||||
|       onRenewIdTokenHandlerPromise && (await onRenewIdTokenHandlerPromise); | ||||
|     } catch (error) { | ||||
|       console.error((error as AxiosError).message); | ||||
|     } | ||||
| 
 | ||||
|     return new Promise((resolve, reject) => { | ||||
|       if (onRenewIdTokenHandlerPromise) { | ||||
|         onRenewIdTokenHandlerPromise | ||||
|           .then(() => { | ||||
|             resolve(localState.getOidcToken() || ''); | ||||
|           }) | ||||
|           .catch((error) => { | ||||
|             if (error.message !== 'Frame window timed out') { | ||||
|               reject(error); | ||||
|             } else { | ||||
|               resolve(localState.getOidcToken() || ''); | ||||
|             } | ||||
|           }); | ||||
|       } else { | ||||
|         reject('RenewIdTokenHandler is undefined'); | ||||
|       } | ||||
|     }); | ||||
|     return localState.getOidcToken(); | ||||
|   }; | ||||
| 
 | ||||
|   /** | ||||
| @ -291,28 +282,24 @@ export const AuthProvider = ({ | ||||
|   }; | ||||
| 
 | ||||
|   /** | ||||
|    * It will set an timer for 50 secs before Token will expire | ||||
|    * If time if less then 50 secs then it will try to SilentSignIn | ||||
|    * It will set an timer for 5 mins before Token will expire | ||||
|    * If time if less then 5 mins then it will try to SilentSignIn | ||||
|    * It will also ensure that we have time left for token expiry | ||||
|    * This method will be call upon successful signIn | ||||
|    */ | ||||
|   const startTokenExpiryTimer = () => { | ||||
|     // Extract expiry
 | ||||
|     const { exp, isExpired, diff, timeoutExpiry } = extractDetailsFromToken(); | ||||
|     const { isExpired, timeoutExpiry } = extractDetailsFromToken(); | ||||
| 
 | ||||
|     if (!isExpired && exp && diff && timeoutExpiry) { | ||||
|       // Have 2m buffer before start trying for silent signIn
 | ||||
|     if (!isExpired && isNumber(timeoutExpiry)) { | ||||
|       // Have 5m buffer before start trying for silent signIn
 | ||||
|       // If token is about to expire then start silentSignIn
 | ||||
|       // else just set timer to try for silentSignIn before token expires
 | ||||
|       if (diff > EXPIRY_THRESHOLD_MILLES) { | ||||
|       clearTimeout(timeoutId); | ||||
|       const timerId = setTimeout(() => { | ||||
|         trySilentSignIn(); | ||||
|       }, timeoutExpiry); | ||||
|       setTimeoutId(Number(timerId)); | ||||
|       } else { | ||||
|         trySilentSignIn(); | ||||
|       } | ||||
|     } | ||||
|   }; | ||||
| 
 | ||||
| @ -324,12 +311,6 @@ export const AuthProvider = ({ | ||||
|     clearTimeout(timeoutId); | ||||
|   }, [timeoutId]); | ||||
| 
 | ||||
|   useEffect(() => { | ||||
|     startTokenExpiryTimer(); | ||||
| 
 | ||||
|     return cleanup; | ||||
|   }, []); | ||||
| 
 | ||||
|   const handleFailedLogin = () => { | ||||
|     setIsSigningIn(false); | ||||
|     setIsUserAuthenticated(false); | ||||
| @ -398,7 +379,17 @@ export const AuthProvider = ({ | ||||
|    */ | ||||
|   const initializeAxiosInterceptors = () => { | ||||
|     // Axios Request interceptor to add Bearer tokens in Header
 | ||||
|     axiosClient.interceptors.request.use(async function (config) { | ||||
|     if (requestInterceptor != null) { | ||||
|       axiosClient.interceptors.request.eject(requestInterceptor); | ||||
|     } | ||||
| 
 | ||||
|     if (responseInterceptor != null) { | ||||
|       axiosClient.interceptors.response.eject(responseInterceptor); | ||||
|     } | ||||
| 
 | ||||
|     requestInterceptor = axiosClient.interceptors.request.use(async function ( | ||||
|       config | ||||
|     ) { | ||||
|       const token: string = localState.getOidcToken() || ''; | ||||
|       if (token) { | ||||
|         if (config.headers) { | ||||
| @ -414,7 +405,7 @@ export const AuthProvider = ({ | ||||
|     }); | ||||
| 
 | ||||
|     // Axios response interceptor for statusCode 401,403
 | ||||
|     axiosClient.interceptors.response.use( | ||||
|     responseInterceptor = axiosClient.interceptors.response.use( | ||||
|       (response) => response, | ||||
|       (error) => { | ||||
|         if (error.response) { | ||||
| @ -573,6 +564,9 @@ export const AuthProvider = ({ | ||||
| 
 | ||||
|   useEffect(() => { | ||||
|     fetchAuthConfig(); | ||||
|     startTokenExpiryTimer(); | ||||
| 
 | ||||
|     return cleanup; | ||||
|   }, []); | ||||
| 
 | ||||
|   useEffect(() => { | ||||
| @ -625,6 +619,7 @@ export const AuthProvider = ({ | ||||
|     setLoadingIndicator, | ||||
|     handleSuccessfulLogin, | ||||
|     handleUserCreated, | ||||
|     updateAxiosInterceptors: initializeAxiosInterceptors, | ||||
|     jwtPrincipalClaims, | ||||
|   }; | ||||
| 
 | ||||
|  | ||||
| @ -74,6 +74,7 @@ const OidcAuthenticator = forwardRef<AuthenticatorRef, Props>( | ||||
|       isSigningIn, | ||||
|       setIsSigningIn, | ||||
|       setLoadingIndicator, | ||||
|       updateAxiosInterceptors, | ||||
|     } = useAuthContext(); | ||||
|     const history = useHistory(); | ||||
|     const { userDetails, newUser } = AppState; | ||||
| @ -94,7 +95,10 @@ const OidcAuthenticator = forwardRef<AuthenticatorRef, Props>( | ||||
| 
 | ||||
|     // Performs silent signIn and returns with IDToken
 | ||||
|     const signInSilently = async () => { | ||||
|       return userManager.signinSilent().then((user) => user.id_token); | ||||
|       const user = await userManager.signinSilent(); | ||||
|       localState.setOidcToken(user.id_token); | ||||
| 
 | ||||
|       return user.id_token; | ||||
|     }; | ||||
| 
 | ||||
|     useImperativeHandle(ref, () => ({ | ||||
| @ -158,6 +162,7 @@ const OidcAuthenticator = forwardRef<AuthenticatorRef, Props>( | ||||
|                   }} | ||||
|                   onSuccess={(user) => { | ||||
|                     localState.setOidcToken(user.id_token); | ||||
|                     updateAxiosInterceptors(); | ||||
|                   }} | ||||
|                 /> | ||||
|               </> | ||||
|  | ||||
| @ -30,11 +30,7 @@ import { isDev } from './EnvironmentUtils'; | ||||
| 
 | ||||
| export let msalInstance: IPublicClientApplication; | ||||
| 
 | ||||
| export const EXPIRY_THRESHOLD_MILLES = 2 * 60 * 1000; | ||||
| 
 | ||||
| export const getOidcExpiry = () => { | ||||
|   return new Date(Date.now() + 60 * 60 * 24 * 1000); | ||||
| }; | ||||
| export const EXPIRY_THRESHOLD_MILLES = 5 * 60 * 1000; | ||||
| 
 | ||||
| export const getRedirectUri = (callbackUrl: string) => { | ||||
|   return isDev() | ||||
| @ -279,7 +275,10 @@ export const extractDetailsFromToken = () => { | ||||
|       const dateNow = Date.now(); | ||||
| 
 | ||||
|       const diff = exp && exp * 1000 - dateNow; | ||||
|       const timeoutExpiry = diff && diff - EXPIRY_THRESHOLD_MILLES; | ||||
|       const timeoutExpiry = | ||||
|         diff && diff > EXPIRY_THRESHOLD_MILLES | ||||
|           ? diff - EXPIRY_THRESHOLD_MILLES | ||||
|           : 0; | ||||
| 
 | ||||
|       return { | ||||
|         exp, | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 karanh37
						karanh37