@klauswuestefeld/jux-web 2024.11.9 → 2024.11.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -8,4 +8,6 @@ export declare const requestMagicLink: (data: any, onJsonResponse: (response: an
8
8
  export declare const openMagicLink: (magicToken: string, onJsonResponse: (response: any) => any, onHelpMessage: (message: string) => any) => void;
9
9
  export declare const googleLogin: (token: string, onLogin: (response: any) => any, onLoginError: (message: string) => any) => void;
10
10
  export declare const microsoftLogin: (token: string, onLogin: (response: any) => any, onLoginError: (message: string) => any) => void;
11
+ export declare const getSSOAuthorizationEndpoint: (onSuccess: (response: any) => any, onError: (message: string) => any) => void;
12
+ export declare const validateSSOToken: (token: string, redirectUri: string, onLogin: (response: any) => any, onError: (message: string) => any) => void;
11
13
  export declare const getMXData: (domainName: string) => Promise<any>;
package/dist/jux-web.js CHANGED
@@ -61,26 +61,30 @@ var juxWeb = (function (exports) {
61
61
  applyComponentStyle(result);
62
62
  result.tabIndex = 0;
63
63
  result.setAttribute('data-cy', `${loweredCasedType}-button`);
64
- const icon = document.createElement('login-icon');
65
- icon.style.gridColumnStart = '2';
66
- icon.style.width = '28px';
67
- icon.style.height = '28px';
68
- icon.style.padding = '6px';
69
- icon.style.marginLeft = '4px';
70
- icon.style.boxSizing = 'content-box';
71
- icon.className = 'ico';
72
64
  // @ts-ignore
73
- icon.innerHTML = icons[loweredCasedType];
65
+ const iconHTML = icons[loweredCasedType];
66
+ if (iconHTML) {
67
+ const icon = document.createElement('login-icon');
68
+ icon.style.gridColumnStart = '2';
69
+ icon.style.width = '28px';
70
+ icon.style.height = '28px';
71
+ icon.style.padding = '6px';
72
+ icon.style.marginLeft = '4px';
73
+ icon.style.boxSizing = 'content-box';
74
+ icon.className = 'ico';
75
+ icon.innerHTML = iconHTML;
76
+ result.appendChild(icon);
77
+ }
74
78
  const label = document.createElement('login-label');
75
79
  label.textContent = window.innerWidth <= THRESHOLD_WIDTH ? type : getTranslation(`${loweredCasedType}-label`);
76
80
  applyLabelStyle(label);
77
- result.append(icon, label);
81
+ result.appendChild(label);
78
82
  result.addEventListener('click', fn);
79
- result.addEventListener('mouseenter', () => {
83
+ result.addEventListener('mouseenter', (_ev) => {
80
84
  result.style.cursor = 'pointer';
81
85
  result.style.boxShadow = '0 0 6px #808080';
82
86
  });
83
- result.addEventListener('mouseleave', () => {
87
+ result.addEventListener('mouseleave', (_ev) => {
84
88
  result.style.cursor = 'auto';
85
89
  result.style.boxShadow = '1px 1px 1px grey';
86
90
  });
@@ -194,6 +198,7 @@ var juxWeb = (function (exports) {
194
198
  let requestRunning = false;
195
199
  const maxRetries = 20;
196
200
  let timeout = 20000;
201
+ const slowRequestTimeout = 2000;
197
202
  // @ts-ignore
198
203
  window.setRequestTimeout = (newTimeout) => timeout = newTimeout;
199
204
  const backendRequest = (url_1, options_1, onSuccess_1, onError_1, onRedirect_1, ...args_1) => __awaiter$2(void 0, [url_1, options_1, onSuccess_1, onError_1, onRedirect_1, ...args_1], void 0, function* (url, options, onSuccess, onError, onRedirect, requestType = 'query', handleUnauthorized = defaultHandleUnauthorized, retrial = false, retrialNum = 0) {
@@ -215,6 +220,13 @@ var juxWeb = (function (exports) {
215
220
  if (requestType === 'query') {
216
221
  timeoutId = setTimeout(() => controller.abort(), timeout); // abort connections that take longer than the value set on the timeout const
217
222
  }
223
+ let isSlowRequest = false;
224
+ const slowRequestTimeoutId = setTimeout(() => {
225
+ isSlowRequest = true;
226
+ const requestUrl = new URL(url);
227
+ const event = new CustomEvent('slow-request', { detail: requestUrl.pathname, bubbles: true });
228
+ window.dispatchEvent(event);
229
+ }, slowRequestTimeout);
218
230
  const requestInit = Object.assign(Object.assign({}, options), { signal: controller.signal });
219
231
  if (onRedirect)
220
232
  requestInit.redirect = 'manual'; // Treat redirects manually instead of following them automatically.
@@ -252,6 +264,12 @@ var juxWeb = (function (exports) {
252
264
  }
253
265
  finally {
254
266
  clearTimeout(timeoutId);
267
+ clearTimeout(slowRequestTimeoutId);
268
+ if (isSlowRequest) {
269
+ const requestUrl = new URL(url);
270
+ const event = new CustomEvent('slow-request-completed', { detail: requestUrl.pathname, bubbles: true });
271
+ window.dispatchEvent(event);
272
+ }
255
273
  }
256
274
  removeOverlay();
257
275
  if (onRedirect)
@@ -276,7 +294,7 @@ var juxWeb = (function (exports) {
276
294
  }
277
295
  else {
278
296
  // backend exceptions
279
- onError(jsonResponse.error);
297
+ onError(jsonResponse);
280
298
  }
281
299
  }
282
300
  catch (err) {
@@ -342,6 +360,12 @@ var juxWeb = (function (exports) {
342
360
  const url = getBackendUrl() + 'auth-microsoft?access-token=' + token;
343
361
  backendRequest(url, {}, onLogin, onLoginError);
344
362
  };
363
+ const getSSOAuthorizationEndpoint = (onSuccess, onError) => {
364
+ backendGet('openid/authorization-endpoint', null, onSuccess, onError);
365
+ };
366
+ const validateSSOToken = (token, redirectUri, onLogin, onError) => {
367
+ backendGet('openid/callback', { code: token, 'redirect-uri': redirectUri }, onLogin, onError);
368
+ };
345
369
  const getMXData = (domainName) => __awaiter$2(void 0, void 0, void 0, function* () {
346
370
  try {
347
371
  const records = yield fetch(`https://dns.google.com/resolve?name=${domainName}&type=MX`, {
@@ -14316,6 +14340,10 @@ var juxWeb = (function (exports) {
14316
14340
  Array.from(clientApp.children).forEach(el => el.remove());
14317
14341
  clientApp.appendChild(page);
14318
14342
  };
14343
+ const getSSOCallbackURI = () => {
14344
+ const { protocol, host } = window.location;
14345
+ return protocol + '//' + host + '/callback';
14346
+ };
14319
14347
  const initSession = (clientApp, supportedLoginTypes, onUserLogin, backgroundImage, fetchUserBackendUrl, magicLinkRequestEndpoint, magicLinkAuthEndpoint) => {
14320
14348
  // if (startNewDemo()) {
14321
14349
  // initDemo(setBackendToken, onAuthentication);
@@ -14353,16 +14381,12 @@ var juxWeb = (function (exports) {
14353
14381
  backendGet('profile', null, (res) => onAuthentication(onUserLogin, res, 'Token Authentication'), (_err) => onAuthenticationFailure('login-failed'));
14354
14382
  return;
14355
14383
  }
14384
+ const ssoToken = extractTokenFromWindowLocation('code');
14385
+ if (ssoToken) {
14386
+ validateSSOToken(ssoToken, getSSOCallbackURI(), (res) => onAuthentication(onUserLogin, res, 'SSO Authentication'), () => onAuthenticationFailure('login-failed'));
14387
+ return;
14388
+ }
14356
14389
  displayPage(clientApp, loginPage(clientApp, backgroundImage, onUserLogin, supportedLoginTypes));
14357
- // const linkedinToken = extractTokenFromWindowLocation('code', '\&state=9893849343');
14358
- // if (linkedinToken) {
14359
- // openLinkedinSession(
14360
- // linkedinToken,
14361
- // (res) => onAuthentication(res, 'Linkedin Authentication'),
14362
- // () => onAuthenticationFailure('unable-linkedin-login')
14363
- // );
14364
- // return;
14365
- // }
14366
14390
  // validateThirdPartyCookies(initGapi, () => displayPage(Page.LOGIN));
14367
14391
  // checkMixpanel(() => mixpanel.track('View Login Page'));
14368
14392
  };
@@ -14404,6 +14428,14 @@ var juxWeb = (function (exports) {
14404
14428
  authSignIn(onUserLogin);
14405
14429
  }, onCookieError);
14406
14430
  };
14431
+ const handleSSOLogin = () => {
14432
+ const onSuccess = (authEndpoint) => {
14433
+ const authUrl = authEndpoint + `&redirect_uri=${getSSOCallbackURI()}`;
14434
+ window.location.replace(authUrl);
14435
+ };
14436
+ const onError = () => onAuthenticationFailure('login-failed');
14437
+ getSSOAuthorizationEndpoint(onSuccess, onError);
14438
+ };
14407
14439
  const handleMagicLinkRequest = (token, onReturn, backgroundImage, currentPage, clientBody, email = '') => {
14408
14440
  if (!email) {
14409
14441
  const mailMagic = document.querySelector('#mail-magic');
@@ -14597,6 +14629,9 @@ var juxWeb = (function (exports) {
14597
14629
  if (loginTypes.includes('Email')) {
14598
14630
  section.appendChild(loginButton('Email', () => onEmailLoginRequest(clientApp, loginPage, onUserLogin, backgroundImg, loginTypes)));
14599
14631
  }
14632
+ if (loginTypes.includes('SSO')) {
14633
+ section.appendChild(loginButton('SSO', () => handleSSOLogin()));
14634
+ }
14600
14635
  };
14601
14636
  const loginPage = (clientApp, backgroundImg, onUserLogin, loginTypes) => {
14602
14637
  const content = [];
@@ -3,4 +3,5 @@ export declare const onTokenAcquired: (token: string, onUserLogin: any) => void;
3
3
  export declare const initSession: (clientApp: HTMLElement, supportedLoginTypes: string[], onUserLogin: any, backgroundImage: string, fetchUserBackendUrl: any, magicLinkRequestEndpoint: string | null, magicLinkAuthEndpoint: string | null) => void;
4
4
  export declare const onMicrosoftSignIn: (onUserLogin: any) => Promise<void>;
5
5
  export declare const onGoogleSignIn: (onUserLogin: any) => void;
6
+ export declare const handleSSOLogin: () => void;
6
7
  export declare const handleMagicLinkRequest: (token: string | null, onReturn: any, backgroundImage: string, currentPage: HTMLElement, clientBody: HTMLElement, email?: string) => void;
package/dist/main.esm.js CHANGED
@@ -60,26 +60,30 @@ const loginButton = (type, fn) => {
60
60
  applyComponentStyle(result);
61
61
  result.tabIndex = 0;
62
62
  result.setAttribute('data-cy', `${loweredCasedType}-button`);
63
- const icon = document.createElement('login-icon');
64
- icon.style.gridColumnStart = '2';
65
- icon.style.width = '28px';
66
- icon.style.height = '28px';
67
- icon.style.padding = '6px';
68
- icon.style.marginLeft = '4px';
69
- icon.style.boxSizing = 'content-box';
70
- icon.className = 'ico';
71
63
  // @ts-ignore
72
- icon.innerHTML = icons[loweredCasedType];
64
+ const iconHTML = icons[loweredCasedType];
65
+ if (iconHTML) {
66
+ const icon = document.createElement('login-icon');
67
+ icon.style.gridColumnStart = '2';
68
+ icon.style.width = '28px';
69
+ icon.style.height = '28px';
70
+ icon.style.padding = '6px';
71
+ icon.style.marginLeft = '4px';
72
+ icon.style.boxSizing = 'content-box';
73
+ icon.className = 'ico';
74
+ icon.innerHTML = iconHTML;
75
+ result.appendChild(icon);
76
+ }
73
77
  const label = document.createElement('login-label');
74
78
  label.textContent = window.innerWidth <= THRESHOLD_WIDTH ? type : getTranslation(`${loweredCasedType}-label`);
75
79
  applyLabelStyle(label);
76
- result.append(icon, label);
80
+ result.appendChild(label);
77
81
  result.addEventListener('click', fn);
78
- result.addEventListener('mouseenter', () => {
82
+ result.addEventListener('mouseenter', (_ev) => {
79
83
  result.style.cursor = 'pointer';
80
84
  result.style.boxShadow = '0 0 6px #808080';
81
85
  });
82
- result.addEventListener('mouseleave', () => {
86
+ result.addEventListener('mouseleave', (_ev) => {
83
87
  result.style.cursor = 'auto';
84
88
  result.style.boxShadow = '1px 1px 1px grey';
85
89
  });
@@ -193,6 +197,7 @@ const defaultHandleUnauthorized = () => {
193
197
  let requestRunning = false;
194
198
  const maxRetries = 20;
195
199
  let timeout = 20000;
200
+ const slowRequestTimeout = 2000;
196
201
  // @ts-ignore
197
202
  window.setRequestTimeout = (newTimeout) => timeout = newTimeout;
198
203
  const backendRequest = (url_1, options_1, onSuccess_1, onError_1, onRedirect_1, ...args_1) => __awaiter(void 0, [url_1, options_1, onSuccess_1, onError_1, onRedirect_1, ...args_1], void 0, function* (url, options, onSuccess, onError, onRedirect, requestType = 'query', handleUnauthorized = defaultHandleUnauthorized, retrial = false, retrialNum = 0) {
@@ -214,6 +219,13 @@ const backendRequest = (url_1, options_1, onSuccess_1, onError_1, onRedirect_1,
214
219
  if (requestType === 'query') {
215
220
  timeoutId = setTimeout(() => controller.abort(), timeout); // abort connections that take longer than the value set on the timeout const
216
221
  }
222
+ let isSlowRequest = false;
223
+ const slowRequestTimeoutId = setTimeout(() => {
224
+ isSlowRequest = true;
225
+ const requestUrl = new URL(url);
226
+ const event = new CustomEvent('slow-request', { detail: requestUrl.pathname, bubbles: true });
227
+ window.dispatchEvent(event);
228
+ }, slowRequestTimeout);
217
229
  const requestInit = Object.assign(Object.assign({}, options), { signal: controller.signal });
218
230
  if (onRedirect)
219
231
  requestInit.redirect = 'manual'; // Treat redirects manually instead of following them automatically.
@@ -251,6 +263,12 @@ const backendRequest = (url_1, options_1, onSuccess_1, onError_1, onRedirect_1,
251
263
  }
252
264
  finally {
253
265
  clearTimeout(timeoutId);
266
+ clearTimeout(slowRequestTimeoutId);
267
+ if (isSlowRequest) {
268
+ const requestUrl = new URL(url);
269
+ const event = new CustomEvent('slow-request-completed', { detail: requestUrl.pathname, bubbles: true });
270
+ window.dispatchEvent(event);
271
+ }
254
272
  }
255
273
  removeOverlay();
256
274
  if (onRedirect)
@@ -275,7 +293,7 @@ const backendRequest = (url_1, options_1, onSuccess_1, onError_1, onRedirect_1,
275
293
  }
276
294
  else {
277
295
  // backend exceptions
278
- onError(jsonResponse.error);
296
+ onError(jsonResponse);
279
297
  }
280
298
  }
281
299
  catch (err) {
@@ -341,6 +359,12 @@ const microsoftLogin = (token, onLogin, onLoginError) => {
341
359
  const url = getBackendUrl() + 'auth-microsoft?access-token=' + token;
342
360
  backendRequest(url, {}, onLogin, onLoginError);
343
361
  };
362
+ const getSSOAuthorizationEndpoint = (onSuccess, onError) => {
363
+ backendGet('openid/authorization-endpoint', null, onSuccess, onError);
364
+ };
365
+ const validateSSOToken = (token, redirectUri, onLogin, onError) => {
366
+ backendGet('openid/callback', { code: token, 'redirect-uri': redirectUri }, onLogin, onError);
367
+ };
344
368
  const getMXData = (domainName) => __awaiter(void 0, void 0, void 0, function* () {
345
369
  try {
346
370
  const records = yield fetch(`https://dns.google.com/resolve?name=${domainName}&type=MX`, {
@@ -996,6 +1020,10 @@ const displayPage = (clientApp, page) => {
996
1020
  Array.from(clientApp.children).forEach(el => el.remove());
997
1021
  clientApp.appendChild(page);
998
1022
  };
1023
+ const getSSOCallbackURI = () => {
1024
+ const { protocol, host } = window.location;
1025
+ return protocol + '//' + host + '/callback';
1026
+ };
999
1027
  const initSession = (clientApp, supportedLoginTypes, onUserLogin, backgroundImage, fetchUserBackendUrl, magicLinkRequestEndpoint, magicLinkAuthEndpoint) => {
1000
1028
  // if (startNewDemo()) {
1001
1029
  // initDemo(setBackendToken, onAuthentication);
@@ -1033,16 +1061,12 @@ const initSession = (clientApp, supportedLoginTypes, onUserLogin, backgroundImag
1033
1061
  backendGet('profile', null, (res) => onAuthentication(onUserLogin, res, 'Token Authentication'), (_err) => onAuthenticationFailure('login-failed'));
1034
1062
  return;
1035
1063
  }
1064
+ const ssoToken = extractTokenFromWindowLocation('code');
1065
+ if (ssoToken) {
1066
+ validateSSOToken(ssoToken, getSSOCallbackURI(), (res) => onAuthentication(onUserLogin, res, 'SSO Authentication'), () => onAuthenticationFailure('login-failed'));
1067
+ return;
1068
+ }
1036
1069
  displayPage(clientApp, loginPage(clientApp, backgroundImage, onUserLogin, supportedLoginTypes));
1037
- // const linkedinToken = extractTokenFromWindowLocation('code', '\&state=9893849343');
1038
- // if (linkedinToken) {
1039
- // openLinkedinSession(
1040
- // linkedinToken,
1041
- // (res) => onAuthentication(res, 'Linkedin Authentication'),
1042
- // () => onAuthenticationFailure('unable-linkedin-login')
1043
- // );
1044
- // return;
1045
- // }
1046
1070
  // validateThirdPartyCookies(initGapi, () => displayPage(Page.LOGIN));
1047
1071
  // checkMixpanel(() => mixpanel.track('View Login Page'));
1048
1072
  };
@@ -1084,6 +1108,14 @@ const onGoogleSignIn = (onUserLogin) => {
1084
1108
  authSignIn(onUserLogin);
1085
1109
  }, onCookieError);
1086
1110
  };
1111
+ const handleSSOLogin = () => {
1112
+ const onSuccess = (authEndpoint) => {
1113
+ const authUrl = authEndpoint + `&redirect_uri=${getSSOCallbackURI()}`;
1114
+ window.location.replace(authUrl);
1115
+ };
1116
+ const onError = () => onAuthenticationFailure('login-failed');
1117
+ getSSOAuthorizationEndpoint(onSuccess, onError);
1118
+ };
1087
1119
  const handleMagicLinkRequest = (token, onReturn, backgroundImage, currentPage, clientBody, email = '') => {
1088
1120
  if (!email) {
1089
1121
  const mailMagic = document.querySelector('#mail-magic');
@@ -1277,6 +1309,9 @@ const appendLoginTypes = (loginPage, section, clientApp, onUserLogin, loginTypes
1277
1309
  if (loginTypes.includes('Email')) {
1278
1310
  section.appendChild(loginButton('Email', () => onEmailLoginRequest(clientApp, loginPage, onUserLogin, backgroundImg, loginTypes)));
1279
1311
  }
1312
+ if (loginTypes.includes('SSO')) {
1313
+ section.appendChild(loginButton('SSO', () => handleSSOLogin()));
1314
+ }
1280
1315
  };
1281
1316
  const loginPage = (clientApp, backgroundImg, onUserLogin, loginTypes) => {
1282
1317
  const content = [];
package/dist/main.js CHANGED
@@ -84,26 +84,30 @@ const loginButton = (type, fn) => {
84
84
  applyComponentStyle(result);
85
85
  result.tabIndex = 0;
86
86
  result.setAttribute('data-cy', `${loweredCasedType}-button`);
87
- const icon = document.createElement('login-icon');
88
- icon.style.gridColumnStart = '2';
89
- icon.style.width = '28px';
90
- icon.style.height = '28px';
91
- icon.style.padding = '6px';
92
- icon.style.marginLeft = '4px';
93
- icon.style.boxSizing = 'content-box';
94
- icon.className = 'ico';
95
87
  // @ts-ignore
96
- icon.innerHTML = icons[loweredCasedType];
88
+ const iconHTML = icons[loweredCasedType];
89
+ if (iconHTML) {
90
+ const icon = document.createElement('login-icon');
91
+ icon.style.gridColumnStart = '2';
92
+ icon.style.width = '28px';
93
+ icon.style.height = '28px';
94
+ icon.style.padding = '6px';
95
+ icon.style.marginLeft = '4px';
96
+ icon.style.boxSizing = 'content-box';
97
+ icon.className = 'ico';
98
+ icon.innerHTML = iconHTML;
99
+ result.appendChild(icon);
100
+ }
97
101
  const label = document.createElement('login-label');
98
102
  label.textContent = window.innerWidth <= THRESHOLD_WIDTH ? type : getTranslation(`${loweredCasedType}-label`);
99
103
  applyLabelStyle(label);
100
- result.append(icon, label);
104
+ result.appendChild(label);
101
105
  result.addEventListener('click', fn);
102
- result.addEventListener('mouseenter', () => {
106
+ result.addEventListener('mouseenter', (_ev) => {
103
107
  result.style.cursor = 'pointer';
104
108
  result.style.boxShadow = '0 0 6px #808080';
105
109
  });
106
- result.addEventListener('mouseleave', () => {
110
+ result.addEventListener('mouseleave', (_ev) => {
107
111
  result.style.cursor = 'auto';
108
112
  result.style.boxShadow = '1px 1px 1px grey';
109
113
  });
@@ -217,6 +221,7 @@ const defaultHandleUnauthorized = () => {
217
221
  let requestRunning = false;
218
222
  const maxRetries = 20;
219
223
  let timeout = 20000;
224
+ const slowRequestTimeout = 2000;
220
225
  // @ts-ignore
221
226
  window.setRequestTimeout = (newTimeout) => timeout = newTimeout;
222
227
  const backendRequest = (url_1, options_1, onSuccess_1, onError_1, onRedirect_1, ...args_1) => __awaiter(void 0, [url_1, options_1, onSuccess_1, onError_1, onRedirect_1, ...args_1], void 0, function* (url, options, onSuccess, onError, onRedirect, requestType = 'query', handleUnauthorized = defaultHandleUnauthorized, retrial = false, retrialNum = 0) {
@@ -238,6 +243,13 @@ const backendRequest = (url_1, options_1, onSuccess_1, onError_1, onRedirect_1,
238
243
  if (requestType === 'query') {
239
244
  timeoutId = setTimeout(() => controller.abort(), timeout); // abort connections that take longer than the value set on the timeout const
240
245
  }
246
+ let isSlowRequest = false;
247
+ const slowRequestTimeoutId = setTimeout(() => {
248
+ isSlowRequest = true;
249
+ const requestUrl = new URL(url);
250
+ const event = new CustomEvent('slow-request', { detail: requestUrl.pathname, bubbles: true });
251
+ window.dispatchEvent(event);
252
+ }, slowRequestTimeout);
241
253
  const requestInit = Object.assign(Object.assign({}, options), { signal: controller.signal });
242
254
  if (onRedirect)
243
255
  requestInit.redirect = 'manual'; // Treat redirects manually instead of following them automatically.
@@ -275,6 +287,12 @@ const backendRequest = (url_1, options_1, onSuccess_1, onError_1, onRedirect_1,
275
287
  }
276
288
  finally {
277
289
  clearTimeout(timeoutId);
290
+ clearTimeout(slowRequestTimeoutId);
291
+ if (isSlowRequest) {
292
+ const requestUrl = new URL(url);
293
+ const event = new CustomEvent('slow-request-completed', { detail: requestUrl.pathname, bubbles: true });
294
+ window.dispatchEvent(event);
295
+ }
278
296
  }
279
297
  removeOverlay();
280
298
  if (onRedirect)
@@ -299,7 +317,7 @@ const backendRequest = (url_1, options_1, onSuccess_1, onError_1, onRedirect_1,
299
317
  }
300
318
  else {
301
319
  // backend exceptions
302
- onError(jsonResponse.error);
320
+ onError(jsonResponse);
303
321
  }
304
322
  }
305
323
  catch (err) {
@@ -365,6 +383,12 @@ const microsoftLogin = (token, onLogin, onLoginError) => {
365
383
  const url = getBackendUrl() + 'auth-microsoft?access-token=' + token;
366
384
  backendRequest(url, {}, onLogin, onLoginError);
367
385
  };
386
+ const getSSOAuthorizationEndpoint = (onSuccess, onError) => {
387
+ backendGet('openid/authorization-endpoint', null, onSuccess, onError);
388
+ };
389
+ const validateSSOToken = (token, redirectUri, onLogin, onError) => {
390
+ backendGet('openid/callback', { code: token, 'redirect-uri': redirectUri }, onLogin, onError);
391
+ };
368
392
  const getMXData = (domainName) => __awaiter(void 0, void 0, void 0, function* () {
369
393
  try {
370
394
  const records = yield fetch(`https://dns.google.com/resolve?name=${domainName}&type=MX`, {
@@ -1020,6 +1044,10 @@ const displayPage = (clientApp, page) => {
1020
1044
  Array.from(clientApp.children).forEach(el => el.remove());
1021
1045
  clientApp.appendChild(page);
1022
1046
  };
1047
+ const getSSOCallbackURI = () => {
1048
+ const { protocol, host } = window.location;
1049
+ return protocol + '//' + host + '/callback';
1050
+ };
1023
1051
  const initSession = (clientApp, supportedLoginTypes, onUserLogin, backgroundImage, fetchUserBackendUrl, magicLinkRequestEndpoint, magicLinkAuthEndpoint) => {
1024
1052
  // if (startNewDemo()) {
1025
1053
  // initDemo(setBackendToken, onAuthentication);
@@ -1057,16 +1085,12 @@ const initSession = (clientApp, supportedLoginTypes, onUserLogin, backgroundImag
1057
1085
  backendGet('profile', null, (res) => onAuthentication(onUserLogin, res, 'Token Authentication'), (_err) => onAuthenticationFailure('login-failed'));
1058
1086
  return;
1059
1087
  }
1088
+ const ssoToken = extractTokenFromWindowLocation('code');
1089
+ if (ssoToken) {
1090
+ validateSSOToken(ssoToken, getSSOCallbackURI(), (res) => onAuthentication(onUserLogin, res, 'SSO Authentication'), () => onAuthenticationFailure('login-failed'));
1091
+ return;
1092
+ }
1060
1093
  displayPage(clientApp, loginPage(clientApp, backgroundImage, onUserLogin, supportedLoginTypes));
1061
- // const linkedinToken = extractTokenFromWindowLocation('code', '\&state=9893849343');
1062
- // if (linkedinToken) {
1063
- // openLinkedinSession(
1064
- // linkedinToken,
1065
- // (res) => onAuthentication(res, 'Linkedin Authentication'),
1066
- // () => onAuthenticationFailure('unable-linkedin-login')
1067
- // );
1068
- // return;
1069
- // }
1070
1094
  // validateThirdPartyCookies(initGapi, () => displayPage(Page.LOGIN));
1071
1095
  // checkMixpanel(() => mixpanel.track('View Login Page'));
1072
1096
  };
@@ -1108,6 +1132,14 @@ const onGoogleSignIn = (onUserLogin) => {
1108
1132
  authSignIn(onUserLogin);
1109
1133
  }, onCookieError);
1110
1134
  };
1135
+ const handleSSOLogin = () => {
1136
+ const onSuccess = (authEndpoint) => {
1137
+ const authUrl = authEndpoint + `&redirect_uri=${getSSOCallbackURI()}`;
1138
+ window.location.replace(authUrl);
1139
+ };
1140
+ const onError = () => onAuthenticationFailure('login-failed');
1141
+ getSSOAuthorizationEndpoint(onSuccess, onError);
1142
+ };
1111
1143
  const handleMagicLinkRequest = (token, onReturn, backgroundImage, currentPage, clientBody, email = '') => {
1112
1144
  if (!email) {
1113
1145
  const mailMagic = document.querySelector('#mail-magic');
@@ -1301,6 +1333,9 @@ const appendLoginTypes = (loginPage, section, clientApp, onUserLogin, loginTypes
1301
1333
  if (loginTypes.includes('Email')) {
1302
1334
  section.appendChild(loginButton('Email', () => onEmailLoginRequest(clientApp, loginPage, onUserLogin, backgroundImg, loginTypes)));
1303
1335
  }
1336
+ if (loginTypes.includes('SSO')) {
1337
+ section.appendChild(loginButton('SSO', () => handleSSOLogin()));
1338
+ }
1304
1339
  };
1305
1340
  const loginPage = (clientApp, backgroundImg, onUserLogin, loginTypes) => {
1306
1341
  const content = [];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@klauswuestefeld/jux-web",
3
- "version": "2024.11.9",
3
+ "version": "2024.11.12",
4
4
  "author": "Jux.House",
5
5
  "license": "Copyrighted",
6
6
  "description": "",