@@ -82,8 +82,9 @@ class PegaAuth {
8282 this . #buildAuthorizeUrl( state ) . then ( ( url ) => {
8383 let myWindow = null ; // popup or iframe
8484 let elIframe = null ;
85+ let elCloseBtn = null ;
8586 const iframeTimeout = this . config . silentTimeout !== undefined ? this . config . silentTimeout : 5000 ;
86- let bWinIframe = iframeTimeout > 0 && ( ( ! ! this . config . userIdentifier && ! ! this . config . password ) || this . config . authService !== "pega" ) ;
87+ let bWinIframe = iframeTimeout > 0 && ( ( ! ! this . config . userIdentifier && ! ! this . config . password ) || this . config . iframeLoginUI || this . config . authService !== "pega" ) ;
8788 let tmrAuthComplete = null ;
8889 let checkWindowClosed = null ;
8990 const myWinOnLoad = ( ) => {
@@ -121,16 +122,71 @@ class PegaAuth {
121122 console . log ( "authjs(login): Exception trying to add onload handler to opened window;" )
122123 }
123124 } ;
125+ const fnCloseIframe = ( ) => {
126+ elIframe . parentNode . removeChild ( elIframe ) ;
127+ elCloseBtn . parentNode . removeChild ( elCloseBtn ) ;
128+ // eslint-disable-next-line no-multi-assign
129+ elIframe = elCloseBtn = null ;
130+ bWinIframe = false ;
131+ }
132+ // eslint-disable-next-line prefer-const
133+ const fnCloseAndReject = ( ) => {
134+ fnCloseIframe ( ) ;
135+ // eslint-disable-next-line prefer-promise-reject-errors
136+ reject ( "closed" ) ;
137+ }
124138 // If there is a userIdentifier and password specified or an external SSO auth service,
125139 // we can try to use this silently in an iFrame first
126140 if ( bWinIframe ) {
141+ const nFrameZLevel = 99999 ;
127142 elIframe = document . createElement ( 'iframe' ) ;
128- elIframe . setAttribute ( 'id' , `pe${ this . config . clientId } ` ) ;
129- elIframe . setAttribute ( 'style' , 'position:absolute;display:none' ) ;
143+ elIframe . id = 'pe' + this . config . clientId ;
144+ const loginBoxWidth = 500 ;
145+ const loginBoxHeight = 700 ;
146+ const oStyle = elIframe . style ;
147+ oStyle . position = 'absolute' ;
148+ oStyle . display = 'none' ;
149+ oStyle . zIndex = nFrameZLevel ;
150+ oStyle . top = `${ Math . round ( Math . max ( window . innerHeight - loginBoxHeight , 0 ) / 2 ) } px` ;
151+ oStyle . left = `${ Math . round ( Math . max ( window . innerWidth - loginBoxWidth , 0 ) / 2 ) } px` ;
152+ oStyle . width = '500px' ;
153+ oStyle . height = '700px' ;
154+ // Add Iframe to top of document DOM to have it load
155+ document . body . insertBefore ( elIframe , document . body . firstChild ) ;
130156 // Add Iframe to DOM to have it load
131157 document . getElementsByTagName ( 'body' ) [ 0 ] . appendChild ( elIframe ) ;
132158 elIframe . addEventListener ( "load" , myWinOnLoad , true ) ;
133159 elIframe . setAttribute ( 'src' , url ) ;
160+ const svgCloseBtn =
161+ `<?xml version="1.0" encoding="UTF-8"?>
162+ <svg width="34px" height="34px" viewBox="0 0 34 34" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
163+ <title>Dismiss - Black</title>
164+ <g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
165+ <g transform="translate(1.000000, 1.000000)">
166+ <circle fill="#252C32" cx="16" cy="16" r="16"></circle>
167+ <g transform="translate(9.109375, 9.214844)" fill="#FFFFFF" fill-rule="nonzero">
168+ <path d="M12.7265625,0 L0,12.6210938 L1.0546875,13.5703125 L13.78125,1.0546875 L12.7265625,0 Z M13.7460938,12.5507812 L1.01953125,0 L0,1.01953125 L12.7617188,13.6054688 L13.7460938,12.5507812 Z"></path>
169+ </g>
170+ </g>
171+ </g>
172+ </svg>` ;
173+ const bCloseWithinFrame = false ;
174+ elCloseBtn = document . createElement ( 'img' ) ;
175+ elCloseBtn . onclick = fnCloseAndReject ;
176+ // eslint-disable-next-line prefer-template
177+ elCloseBtn . src = 'data:image/svg+xml;base64,' + window . btoa ( svgCloseBtn ) ;
178+ const oBtnStyle = elCloseBtn . style ;
179+ oBtnStyle . cursor = 'pointer' ;
180+ // If svg doesn't set width and height might want to set oBtStyle width and height to something like '2em'
181+ oBtnStyle . position = 'absolute' ;
182+ oBtnStyle . display = 'none' ;
183+ oBtnStyle . zIndex = nFrameZLevel + 1 ;
184+ const nTopOffset = bCloseWithinFrame ? 5 : - 10 ;
185+ const nRightOffset = bCloseWithinFrame ? - 34 : - 20 ;
186+ oBtnStyle . top = `${ Math . round ( Math . max ( window . innerHeight - loginBoxHeight , 0 ) / 2 ) + nTopOffset } px` ;
187+ oBtnStyle . left = `${ Math . round ( Math . max ( window . innerWidth - loginBoxWidth , 0 ) / 2 ) + loginBoxWidth + nRightOffset } px` ;
188+ document . body . insertBefore ( elCloseBtn , document . body . firstChild ) ;
189+
134190 // If the password was wrong, then the login screen will be in the iframe
135191 // ..and with Pega without realization of US-372314 it may replace the top (main portal) window
136192 // For now set a timer and if the timer expires, remove the iFrame and use same url within
@@ -142,11 +198,13 @@ class PegaAuth {
142198 delete this . config . password ;
143199 this . #updateConfig( ) ;
144200 }
145- elIframe . parentNode . removeChild ( elIframe ) ;
146- elIframe = null ;
147- // Now try to do regular popup open
148- bWinIframe = false ;
149- fnOpenPopup ( ) ;
201+ if ( this . config . iframeLoginUI ) {
202+ elIframe . style . display = "block" ;
203+ elCloseBtn . style . display = "block" ;
204+ } else {
205+ fnCloseIframe ( ) ;
206+ fnOpenPopup ( ) ;
207+ }
150208 } , iframeTimeout ) ;
151209 } else {
152210 fnOpenPopup ( ) ;
@@ -159,8 +217,7 @@ class PegaAuth {
159217 this . getToken ( code ) . then ( token => {
160218 if ( bWinIframe ) {
161219 clearTimeout ( tmrAuthComplete ) ;
162- elIframe . parentNode . removeChild ( elIframe ) ;
163- elIframe = null ;
220+ fnCloseIframe ( ) ;
164221 } else {
165222 clearInterval ( checkWindowClosed ) ;
166223 myWindow . close ( ) ;
0 commit comments