import * as React from 'react' ; import isEqual from 'react-fast-compare' ; import { IAuthContextProps } from './context' ; import { AuthClient , AuthClientError , AuthClientEvent , AuthClientInitOptions , AuthClientTokens , } from './types' ; /**
 * Props that can be passed to AuthProvider
 */ export type AuthProviderProps < T extends AuthClient > = { /**
     * The single AuthClient instance to be used by your application.
     */ authClient : T ; default autoRefreshToken ? : boolean ; /**
     * The config to be used when initializing AuthClient instance.
     */ initOptions ? : AuthClientInitOptions ; param authClient returns { boolean } isLoadingCheck ? : ( authClient : T ) => boolean ; /**
     * An optional component to display while AuthClient instance is being initialized.
     */ LoadingComponent ? : JSX . Element ; /**
     * An optional function to receive AuthClient events as they happen.
     */ onEvent ? : ( eventType : AuthClientEvent , error ? : AuthClientError ) => void ; param { AuthClientTokens } tokens onTokens ? : ( tokens : AuthClientTokens ) => void ; } ; type AuthProviderState = { initialized : boolean ; isAuthenticated : boolean ; isLoading : boolean ; } ; param AuthContext returns export function createAuthProvider < T extends AuthClient > ( AuthContext ) { const defaultInitOptions = { onLoad : 'check-sso' , } ; const initialState = { initialized : false , isAuthenticated : false , isLoading : true , } ; return class KeycloakProvider extends React . PureComponent < AuthProviderProps < T > , AuthProviderState > { state = { ... initialState , } ; componentDidMount ( ) { this . init ( ) ; } componentDidUpdate ( { authClient : prevAuthClient , initOptions : prevInitOptions , } ) { const { initOptions , authClient } = this . props ; if ( authClient !== prevAuthClient || ! isEqual ( initOptions , prevInitOptions ) ) { prevAuthClient . onReady = undefined ; prevAuthClient . onAuthSuccess = undefined ; prevAuthClient . onAuthError = undefined ; prevAuthClient . onAuthRefreshSuccess = undefined ; prevAuthClient . onAuthRefreshError = undefined ; prevAuthClient . onAuthLogout = undefined ; prevAuthClient . onTokenExpired = undefined ; this . setState ( { ... initialState } ) ; this . init ( ) ; } } init ( ) { const { initOptions , authClient } = this . props ; authClient . onReady = this . updateState ( 'onReady' ) ; authClient . onAuthSuccess = this . updateState ( 'onAuthSuccess' ) ; authClient . onAuthError = this . onError ( 'onAuthError' ) ; authClient . onAuthRefreshSuccess = this . updateState ( 'onAuthRefreshSuccess' ) ; authClient . onAuthRefreshError = this . onError ( 'onAuthRefreshError' ) ; authClient . onAuthLogout = this . updateState ( 'onAuthLogout' ) ; authClient . onTokenExpired = this . refreshToken ( 'onTokenExpired' ) ; authClient . init ( { ... defaultInitOptions , ... initOptions } ) . catch ( this . onError ( 'onInitError' ) ) ; } onError = ( event ) => ( error ? ) => { const { onEvent } = this . props ; onEvent && onEvent ( event , error ) ; } ; updateState = ( event ) => ( ) => { const { authClient , onEvent , onTokens , isLoadingCheck } = this . props ; const { initialized : prevInitialized , isAuthenticated : prevAuthenticated , isLoading : prevLoading , } = this . state ; onEvent && onEvent ( event ) ; const isLoading = isLoadingCheck ? isLoadingCheck ( authClient ) : false ; const isAuthenticated = isUserAuthenticated ( authClient ) ; if ( ! prevInitialized || isAuthenticated !== prevAuthenticated || isLoading !== prevLoading ) { this . setState ( { initialized : true , isAuthenticated , isLoading , } ) ; } const { idToken , refreshToken , token } = authClient ; onTokens && onTokens ( { idToken , refreshToken , token , } ) ; } ; refreshToken = ( event ) => ( ) => { const { autoRefreshToken , authClient , onEvent } = this . props ; onEvent && onEvent ( event ) ; if ( autoRefreshToken !== false ) { authClient . updateToken ( 5 ) ; } } ; render ( ) { const { children , authClient , LoadingComponent } = this . props ; const { initialized , isLoading } = this . state ; if ( ! ! LoadingComponent && ( ! initialized || isLoading ) ) { return LoadingComponent ; } return ( < AuthContext . Provider value = { { initialized , authClient } } > { children } < /AuthContext.Provider>); } } ; } function isUserAuthenticated ( authClient ) { return ! ! authClient . idToken && ! ! authClient . token ; } export default createAuthProvider ;