import { Config } from './config' ; import { OktaAuth , TokenResponse , Tokens } from '@okta/okta-auth-js' ; const BundledOktaSignIn = require ( '@okta/okta-signin-widget' ) ; declare global { interface Window { OktaSignIn : any ; getWidgetConfig : ( ) => any ; } } declare class OktaSignIn { constructor ( options ) ; renderEl ( options , successFn , errorFn ) ; showSignInToGetTokens ( options ) ; remove ( ) ; on ( event , fn ) ; } let widgetInstance ; export function buildIdpsConfig ( config ) { const idps = config . idps || '' ; return idps . split ( /\s+/ ) . map ( idpToken => { const [ type , id ] = idpToken . split ( /:/ ) ; if ( ! type || ! id ) { return null ; } return { type , id } ; } ) . filter ( idpToken => idpToken ) ; } export function buildWidgetConfig ( config , options ? ) { return Object . assign ( { } , config , { baseUrl : config . issuer . split ( '/oauth2' ) [ 0 ] , el : '#widget' , authParams : Object . assign ( config , { display : 'page' } ) , idps : buildIdpsConfig ( config ) } , options ) ; } export async function injectWidgetCSS ( widgetVersion = '' ) { const useBundled = widgetVersion === '' ; const baseUrl = useBundled ? `${ window . location . origin }/siw` : 'https://global.oktacdn.com/okta-signin-widget' ; return new Promise ( ( resolve , reject ) => { const link = document . createElement ( 'link' ) ; link . type = 'text/css' ; link . rel = 'stylesheet' ; document . getElementsByTagName ( 'head' ) [ 0 ] . appendChild ( link ) ; link . onload = ( ) : void => { resolve ( ) ; } ; link . onerror = ( e ) : void => { reject ( e ) ; } ; link . href = `${ baseUrl }/${ widgetVersion }/css/okta-sign-in.min.css` ; } ) ; } export async function injectWidgetScript ( widgetVersion ) { return new Promise ( ( resolve , reject ) => { const script = document . createElement ( 'script' ) ; script . type = 'text/javascript' ; document . getElementsByTagName ( 'head' ) [ 0 ] . appendChild ( script ) ; script . onload = ( ) : void => { resolve ( ) ; } ; script . onerror = ( e ) : void => { reject ( e ) ; } ; script . src = `https://global.oktacdn.com/okta-signin-widget/${ widgetVersion }/js/okta-sign-in.min.js` ; } ) ; } export async function injectWidgetFromCDN ( widgetVersion ) { await injectWidgetCSS ( widgetVersion ) ; await injectWidgetScript ( widgetVersion ) ; } function getTokensFromResponse ( res ) { let tokens ; if ( Array . isArray ( res ) ) { tokens = { } ; for ( let i = 0 ; i < res . length ; i ++ ) { const token = res [ i ] ; if ( token . idToken ) { tokens . idToken = token ; } else if ( token . accessToken ) { tokens . accessToken = token ; } } return tokens ; } tokens = res . tokens ; return tokens ; } function hideModal ( ) { const modal = document . getElementById ( 'modal' ) ; modal . style . display = 'none' ; widgetInstance . remove ( ) ; } function showModal ( ) { let modal = document . getElementById ( 'modal' ) ; if ( ! modal ) { modal = document . createElement ( 'div' ) ; modal . id = 'modal' ; modal . innerHTML = `
      <div>
        <div id="widget-container">
          <div id="widget"></div>
        </div>
      </div>
    ` ; document . body . insertBefore ( modal , document . body . firstChild ) ; } modal . style . display = 'block' ; modal . onclick = function ( ) : void { hideModal ( ) ; } ; const widgetEl = document . getElementById ( 'widget' ) ; widgetEl . onclick = function ( event ) : void { event . stopPropagation ( ) ; } ; } export async function renderWidget ( config , authClient ? , options ? ) { if ( ! window . OktaSignIn ) { const siwVersion = config . siwVersion ; if ( siwVersion ) { await injectWidgetFromCDN ( siwVersion ) ; } else { await injectWidgetCSS ( ) ; window . OktaSignIn = BundledOktaSignIn ; } } showModal ( ) ; const widgetConfig = buildWidgetConfig ( config , options ) ; const { issuer , clientId , clientSecret , redirectUri , forceRedirect , scopes } = config ; const state = widgetConfig . state || JSON . stringify ( { issuer , clientId , clientSecret , redirectUri , rand : Math . round ( Math . random ( ) * 1000 ) } ) ; const renderOptions = { clientId , redirectUri , scopes , state , getAccessToken : true , getIdToken : true , getRefreshToken : true } ; widgetConfig . authParams . state = state ; if ( forceRedirect ) { renderOptions . redirect = 'always' ; widgetConfig . authParams . display = 'page' ; } else { widgetConfig . authParams . display = 'none' ; } if ( config . siwAuthClient ) { widgetConfig . authParams = undefined ; widgetConfig . authClient = authClient ; } const signIn = new OktaSignIn ( widgetConfig ) ; widgetInstance = signIn ; signIn . on ( 'afterError' , function ( context , error ) { console . log ( 'Sign-in Widget afterError: ' , context . controller , error ) ; } ) ; return new Promise ( ( resolve , reject ) => { signIn . renderEl ( renderOptions , ( res ) => { console . log ( `signin.renderEl: success callback fired: ` , res ) ; if ( res . status === 'SUCCESS' ) { signIn . remove ( ) ; document . getElementById ( 'modal' ) . style . display = 'none' ; const tokens = getTokensFromResponse ( res ) ; resolve ( tokens ) ; } else { console . error ( `signin.renderEl: result status was ${ res . status }` , res ) ; } } , ( err ) => { console . error ( `signin.renderEl: error callback fired` , err ) ; reject ( err ) ; } ) ; } ) ; }