Skip to content

Commit 35c509b

Browse files
vishalshrm539Sharma
andauthored
Add the capability to login in an iframe (#80)
* Add the capability to login in an iframe * Made 'iframeLoginUI an optional parameter Co-authored-by: Sharma <[email protected]>
1 parent 323b4c9 commit 35c509b

File tree

3 files changed

+71
-11
lines changed

3 files changed

+71
-11
lines changed

sdk-config.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"comment_sdk_config": "This is the configuration file for the Angular-SDK",
33
"authConfig": {
44
"authConfig_comment": "Optional Full paths to Infinity server OAuth endpoints (Only needed if using custom OAuth service)",
5-
"authConfig_comment2": "Optional attributes are: authorize, token, revoke, authService, silentTimeout",
5+
"authConfig_comment2": "Optional attributes are: authorize, token, revoke, authService, silentTimeout, iframeLoginUI",
66
"authService": "pega",
77

88
"mashupClient_comment": "Client ID and Client secret from the OAuth 2.0 Client Registration record used for mashup use case",

src/app/_helpers/auth.js

Lines changed: 67 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -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();

src/app/_services/auth.service.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,9 @@ constellationInit = (authConfig:any, tokenInfo:any) => {
346346
authConfig.userIdentifier = sdkConfigAuth.mashupUserIdentifier;
347347
authConfig.password = sdkConfigAuth.mashupPassword;
348348
}
349+
if( 'iframeLoginUI' in sdkConfigAuth ){
350+
authConfig.iframeLoginUI = sdkConfigAuth.iframeLoginUI.toString().toLowerCase() === 'true';
351+
}
349352

350353
// Check if sessionStorage exists (and if so if for same authorize endpoint). Otherwise, assume
351354
// sessionStorage is out of date (user just edited endpoints). Else, logout required to clear

0 commit comments

Comments
 (0)