const sessionKey = 'session' ; export interface IProvider < T > { buildAuthorizeUrl ( ) : string ; extractError ( redirectUrl ) : Error | undefined ; extractSession ( redirectUrl ) : T ; validateSession ( session ) : boolean ; getAccessToken ( session , resourceId ) : string ; getSignOutUrl ( redirectUrl ) : string ; } export interface IAuthenticationService { acquireTokenAsync < T > ( provider , storage ? , localWindow ? ) : Promise < T > ; restoreSession < T > ( provider , storage ? ) : T | undefined ; invalidateSession ( storage ? ) : void ; getAccessToken < T > ( provider , resourceId , storage ? ) : string ; } export const service = { acquireTokenAsync < T > ( provider , storage = window . localStorage , localWindow = window ) { const requestKey = `react-simple-auth-request-key-${ guid ( ) }` ; const [ width , height ] = [ 500 , 500 ] ; const windowOptions = { width , height , left : Math . floor ( screen . width / 2 - width / 2 ) + ( ( screen as any ) . availLeft || 0 ) , top : Math . floor ( screen . height / 2 - height / 2 ) } ; const oauthAuthorizeUrl = provider . buildAuthorizeUrl ( ) ; const windowOptionString = Object . entries ( windowOptions ) . map ( ( [ key , value ] ) => `${ key }=${ value }` ) . join ( ',' ) ; const loginWindow = localWindow . open ( oauthAuthorizeUrl , requestKey , windowOptionString ) ; return new Promise < any > ( ( resolve , reject ) => { const checkWindow = ( loginWindow ) => { if ( ! loginWindow . closed ) { setTimeout ( ( ) => checkWindow ( loginWindow ) , 100 ) ; return ; } const redirectUrl = storage . getItem ( requestKey ) ; storage . removeItem ( requestKey ) ; if ( typeof redirectUrl !== 'string' || redirectUrl . length === 0 ) { reject ( new Error ( `React Simple Auth: Login window was closed by the user or authentication was incomplete and never reached final redirect page.` ) ) ; return ; } const error = provider . extractError ( redirectUrl ) ; if ( error ) { reject ( error ) ; return ; } const session = provider . extractSession ( redirectUrl ) ; storage . setItem ( sessionKey , JSON . stringify ( session ) ) ; resolve ( session ) ; } ; checkWindow ( loginWindow ) ; } ) ; } , restoreSession < T > ( provider , storage = window . localStorage ) { const sessionString = storage . getItem ( sessionKey ) ; if ( typeof sessionString !== 'string' || sessionString . length === 0 ) { return undefined ; } const session = JSON . parse ( sessionString ) ; if ( ! provider . validateSession ( session ) ) { storage . removeItem ( sessionKey ) ; return undefined ; } return session ; } , invalidateSession ( storage = window . localStorage ) { storage . removeItem ( sessionKey ) ; } , getAccessToken < T > ( provider , resourceId , storage = window . localStorage ) { const sessionString = storage . getItem ( sessionKey ) ; if ( typeof sessionString !== 'string' || sessionString . length === 0 ) { throw new Error ( `You attempted to get access token for resource id: ${ resourceId } from the session but the session did not exist` ) ; } const session = JSON . parse ( sessionString ) ; return provider . getAccessToken ( session , resourceId ) ; } } ; export default service ; function guid ( ) { let d = new Date ( ) . getTime ( ) ; return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx' . replace ( /[xy]/g , function ( c ) { let r = ( ( d + Math . random ( ) * 16 ) % 16 ) | 0 ; d = Math . floor ( d / 16 ) ; return ( c === 'x' ? r : ( r & 0x3 ) | 0x8 ) . toString ( 16 ) ; } ) ; }