@axa-fr/react-oidc 6.0.0-beta1 → 6.0.0-beta12

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.
Files changed (33) hide show
  1. package/README.md +11 -8
  2. package/dist/OidcProvider.d.ts +2 -1
  3. package/dist/OidcProvider.d.ts.map +1 -1
  4. package/dist/OidcProvider.js +15 -7
  5. package/dist/OidcProvider.js.map +1 -1
  6. package/dist/OidcServiceWorker.js +21 -4
  7. package/dist/OidcTrustedDomains.js +7 -2
  8. package/dist/ReactOidc.d.ts.map +1 -1
  9. package/dist/ReactOidc.js +3 -2
  10. package/dist/ReactOidc.js.map +1 -1
  11. package/dist/core/default-component/SilentCallback.component.d.ts.map +1 -1
  12. package/dist/core/default-component/SilentCallback.component.js +5 -19
  13. package/dist/core/default-component/SilentCallback.component.js.map +1 -1
  14. package/dist/core/routes/OidcRoutes.d.ts.map +1 -1
  15. package/dist/core/routes/OidcRoutes.js +1 -4
  16. package/dist/core/routes/OidcRoutes.js.map +1 -1
  17. package/dist/vanilla/oidc.d.ts +8 -5
  18. package/dist/vanilla/oidc.d.ts.map +1 -1
  19. package/dist/vanilla/oidc.js +301 -144
  20. package/dist/vanilla/oidc.js.map +1 -1
  21. package/package.json +1 -1
  22. package/src/oidc/OidcProvider.tsx +17 -8
  23. package/src/oidc/ReactOidc.tsx +3 -2
  24. package/src/oidc/core/default-component/SilentCallback.component.tsx +1 -6
  25. package/src/oidc/core/routes/OidcRoutes.tsx +0 -4
  26. package/src/oidc/vanilla/OidcServiceWorker.js +21 -4
  27. package/src/oidc/vanilla/OidcTrustedDomains.js +7 -2
  28. package/src/oidc/vanilla/oidc.ts +192 -110
  29. package/dist/core/default-component/ServiceWorkerInstall.component.d.ts +0 -4
  30. package/dist/core/default-component/ServiceWorkerInstall.component.d.ts.map +0 -1
  31. package/dist/core/default-component/ServiceWorkerInstall.component.js +0 -131
  32. package/dist/core/default-component/ServiceWorkerInstall.component.js.map +0 -1
  33. package/src/oidc/core/default-component/ServiceWorkerInstall.component.tsx +0 -60
@@ -21,8 +21,7 @@ import {getParseQueryStringFromLocation} from "./route-utils";
21
21
  import {AuthorizationServiceConfigurationJson} from "@openid/appauth/src/authorization_service_configuration";
22
22
 
23
23
  const performTokenRequestAsync= async (url, details, extras) => {
24
-
25
-
24
+
26
25
  for (let [key, value] of Object.entries(extras)) {
27
26
  if (details[key] === undefined) {
28
27
  details[key] = value;
@@ -47,15 +46,22 @@ const performTokenRequestAsync= async (url, details, extras) => {
47
46
  if(response.status !== 200){
48
47
  return {success:false, status: response.status}
49
48
  }
50
- const result = await response.json();
49
+ const tokens = await response.json();
50
+
51
+ if(!tokens.issued_at) {
52
+ const currentTimeUnixSecond = new Date().getTime() /1000;
53
+ tokens.issued_at = currentTimeUnixSecond;
54
+ }
55
+
51
56
  return { success : true,
52
57
  data : {
53
- accessToken: result.access_token,
54
- expiresIn: result.expires_in,
55
- idToken: result.id_token,
56
- refreshToken: result.refresh_token,
57
- scope: result.scope,
58
- tokenType: result.token_type,
58
+ accessToken: tokens.access_token,
59
+ expiresIn: tokens.expires_in,
60
+ idToken: tokens.id_token,
61
+ refreshToken: tokens.refresh_token,
62
+ scope: tokens.scope,
63
+ tokenType: tokens.token_type,
64
+ issuedAt: tokens.issued_at
59
65
  }
60
66
  };
61
67
  }
@@ -210,9 +216,9 @@ const autoRenewTokens = (oidc, refreshToken, expiresAt) => {
210
216
  oidc.timeoutId = autoRenewTokens(oidc, tokens.refreshToken, oidc.tokens.expiresAt);
211
217
  }
212
218
  } else{
213
- await oidc.syncTokensAsync();
214
- if(oidc.timeoutId) {
215
- oidc.timeoutId = autoRenewTokens(oidc, refreshToken, expiresAt);
219
+ const tokens = await oidc.syncTokensAsync();
220
+ if(tokens && oidc.timeoutId) {
221
+ oidc.timeoutId = autoRenewTokens(oidc, tokens.refreshToken, tokens.expiresAt);
216
222
  }
217
223
  }
218
224
  }, 1000);
@@ -225,7 +231,6 @@ const getLoginParams = (configurationName, redirectUri) => {
225
231
  return JSON.parse(sessionStorage[getLoginSessionKey(configurationName, redirectUri)]);
226
232
  }
227
233
 
228
-
229
234
  const userInfoAsync = async (oidc) => {
230
235
  if(oidc.userInfo != null){
231
236
  return oidc.userInfo;
@@ -244,7 +249,7 @@ const userInfoAsync = async (oidc) => {
244
249
  const res = await fetch(url, {
245
250
  headers: {
246
251
  authorization: `Bearer ${accessToken}`,
247
- credentials: 'same-origin'
252
+ credentials: 'include'
248
253
  }
249
254
  });
250
255
 
@@ -274,7 +279,10 @@ const setTokensAsync = async (serviceWorker, tokens) =>{
274
279
  accessTokenPayload = extractAccessTokenPayload(tokens);
275
280
  }
276
281
  const _idTokenPayload = idTokenPayload(tokens.idToken);
277
- const expiresAt = (_idTokenPayload && _idTokenPayload.exp) ? _idTokenPayload.exp : tokens.issuedAt + tokens.expiresIn;
282
+
283
+ const idTokenExipreAt =(_idTokenPayload && _idTokenPayload.exp) ? _idTokenPayload.exp: Number.MAX_VALUE;
284
+ const accessTokenExpiresAt = (accessTokenPayload && accessTokenPayload.exp)? accessTokenPayload.exp : tokens.issuedAt + tokens.expiresIn;
285
+ const expiresAt = idTokenExipreAt < accessTokenExpiresAt ? idTokenExipreAt : accessTokenExpiresAt;
278
286
  return {...tokens, idTokenPayload: _idTokenPayload, accessTokenPayload, expiresAt};
279
287
  }
280
288
 
@@ -282,6 +290,7 @@ const eventNames = {
282
290
  service_worker_not_supported_by_browser: "service_worker_not_supported_by_browser",
283
291
  token_aquired: "token_aquired",
284
292
  logout_from_another_tab: "logout_from_another_tab",
293
+ logout_from_same_tab: "logout_from_same_tab",
285
294
  token_renewed: "token_renewed",
286
295
  token_timer: "token_timer",
287
296
  loginAsync_begin:"loginAsync_begin",
@@ -304,31 +313,30 @@ const eventNames = {
304
313
  syncTokensAsync_begin: "syncTokensAsync_begin",
305
314
  syncTokensAsync_end: "syncTokensAsync_end",
306
315
  syncTokensAsync_error: "syncTokensAsync_error"
307
-
308
316
  }
309
317
 
310
318
  const getRandomInt = (max) => {
311
319
  return Math.floor(Math.random() * max);
312
320
  }
313
321
 
314
- const WELL_KNOWN_PATH = '.well-known';
315
- const OPENID_CONFIGURATION = 'openid-configuration';
316
-
317
-
318
322
  const oneHourSecond = 60 * 60;
319
- const fetchFromIssuer = async (openIdIssuerUrl: string, timeCacheSecond = oneHourSecond):
323
+ let fetchFromIssuerCache = null;
324
+ const fetchFromIssuer = async (openIdIssuerUrl: string, timeCacheSecond = oneHourSecond, storage= window.sessionStorage):
320
325
  Promise<OidcAuthorizationServiceConfiguration> => {
321
- const fullUrl = `${openIdIssuerUrl}/${WELL_KNOWN_PATH}/${OPENID_CONFIGURATION}`;
326
+ const fullUrl = `${openIdIssuerUrl}/.well-known/openid-configuration`;
322
327
 
323
328
  const localStorageKey = `oidc.server:${openIdIssuerUrl}`;
324
- const cacheJson = window.sessionStorage.getItem(localStorageKey);
325
-
329
+ if(!fetchFromIssuerCache && storage) {
330
+ const cacheJson = storage.getItem(localStorageKey);
331
+ if(cacheJson){
332
+ fetchFromIssuerCache = JSON.parse(cacheJson);
333
+ }
334
+ }
326
335
  const oneHourMinisecond = 1000 * timeCacheSecond;
327
336
  // @ts-ignore
328
- if(cacheJson && (cacheJson.timestamp + oneHourMinisecond) > Date.now()){
329
- return new OidcAuthorizationServiceConfiguration(JSON.parse(cacheJson));
337
+ if(fetchFromIssuerCache && (fetchFromIssuerCache.timestamp + oneHourMinisecond) > Date.now()){
338
+ return new OidcAuthorizationServiceConfiguration(fetchFromIssuerCache.result);
330
339
  }
331
-
332
340
  const response = await fetch(fullUrl);
333
341
 
334
342
  if (response.status != 200) {
@@ -336,8 +344,12 @@ const fetchFromIssuer = async (openIdIssuerUrl: string, timeCacheSecond = oneHou
336
344
  }
337
345
 
338
346
  const result = await response.json();
339
- window.sessionStorage.setItem(localStorageKey, JSON.stringify({result, timestamp:Date.now()}));
340
347
 
348
+ const timestamp = Date.now();
349
+ fetchFromIssuerCache = {result, timestamp};
350
+ if(storage) {
351
+ storage.setItem(localStorageKey, JSON.stringify({result, timestamp}));
352
+ }
341
353
  return new OidcAuthorizationServiceConfiguration(result);
342
354
  }
343
355
 
@@ -366,7 +378,12 @@ export class Oidc {
366
378
  private session?: any;
367
379
  private checkSessionIFrame: CheckSessionIFrame;
368
380
  constructor(configuration:OidcConfiguration, configurationName="default") {
369
- this.configuration = configuration
381
+ let silent_login_uri = configuration.silent_login_uri;
382
+ if(configuration.silent_redirect_uri && !configuration.silent_login_uri){
383
+ silent_login_uri = `${configuration.silent_redirect_uri.replace("-callback", "").replace("callback", "")}-login`;
384
+ }
385
+
386
+ this.configuration = {...configuration, silent_login_uri};
370
387
  this.configurationName= configurationName;
371
388
  this.tokens = null
372
389
  this.userInfo = null;
@@ -384,6 +401,8 @@ export class Oidc {
384
401
  this.publishEvent.bind(this);
385
402
  this.destroyAsync.bind(this);
386
403
  this.logoutAsync.bind(this);
404
+
405
+ this.initAsync(this.configuration.authority, this.configuration.authority_configuration);
387
406
  }
388
407
 
389
408
  subscriveEvents(func){
@@ -415,18 +434,29 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
415
434
  }
416
435
  static eventNames = eventNames;
417
436
 
418
- silentLoginCallbackFromIFrame(){
437
+ _silentLoginCallbackFromIFrame(){
419
438
  if (this.configuration.silent_redirect_uri && this.configuration.silent_login_uri) {
420
439
  const queryParams = getParseQueryStringFromLocation(window.location.href);
421
440
  window.top.postMessage(`${this.configurationName}_oidc_tokens:${JSON.stringify({tokens:this.tokens, sessionState:queryParams.session_state})}`, window.location.origin);
422
441
  }
423
442
  }
424
- silentLoginErrorCallbackFromIFrame(){
443
+ _silentLoginErrorCallbackFromIFrame() {
425
444
  if (this.configuration.silent_redirect_uri && this.configuration.silent_login_uri) {
426
445
  const queryParams = getParseQueryStringFromLocation(window.location.href);
427
- window.top.postMessage(`${this.configurationName}_oidc_error:${JSON.stringify({error:queryParams.error})}`, window.location.origin);
446
+ window.top.postMessage(`${this.configurationName}_oidc_error:${JSON.stringify({error: queryParams.error})}`, window.location.origin);
447
+ }
448
+ }
449
+
450
+ async silentLoginCallBackAsync() {
451
+ try {
452
+ await this.loginCallbackAsync(true);
453
+ this._silentLoginCallbackFromIFrame();
454
+ } catch (error) {
455
+ console.error(error)
456
+ this._silentLoginErrorCallbackFromIFrame();
428
457
  }
429
458
  }
459
+
430
460
  async silentLoginAsync(extras:StringMap=null, state:string=null, scope:string=null) {
431
461
  if (!this.configuration.silent_redirect_uri || !this.configuration.silent_login_uri) {
432
462
  return Promise.resolve(null);
@@ -435,6 +465,13 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
435
465
  await sleepAsync(1000);
436
466
  this.publishEvent(eventNames.silentLoginAsync, {message:"wait because document is hidden"});
437
467
  }
468
+
469
+ let numberTryOnline = 6;
470
+ while (!navigator.onLine && numberTryOnline > 0) {
471
+ await sleepAsync(1000);
472
+ numberTryOnline--;
473
+ this.publishEvent(eventNames.refreshTokensAsync, {message: `wait because navigator is offline try ${numberTryOnline}` });
474
+ }
438
475
 
439
476
  try {
440
477
  this.publishEvent(eventNames.silentLoginAsync_begin, {});
@@ -499,7 +536,7 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
499
536
  self.publishEvent(eventNames.silentLoginAsync_error, result);
500
537
  iframe.remove();
501
538
  isResolved = true;
502
- reject(result);
539
+ reject(new Error("oidc_"+result.error));
503
540
  }
504
541
  }
505
542
  }
@@ -508,10 +545,10 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
508
545
  const silentSigninTimeout = configuration.silent_login_timeout ?? 12000
509
546
  setTimeout(() => {
510
547
  if (!isResolved) {
511
- self.publishEvent(eventNames.silentLoginAsync_error, "timeout");
548
+ self.publishEvent(eventNames.silentLoginAsync_error, {reason: "timeout"});
512
549
  iframe.remove();
513
550
  isResolved = true;
514
- reject("timeout");
551
+ reject(new Error("timeout"));
515
552
  }
516
553
  }, silentSigninTimeout);
517
554
  } catch (e) {
@@ -525,7 +562,6 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
525
562
  throw e;
526
563
  }
527
564
  }
528
- initAsyncPromise = null;
529
565
  async initAsync(authority:string, authorityConfiguration:AuthorityConfiguration) {
530
566
  if (authorityConfiguration != null) {
531
567
  return new OidcAuthorizationServiceConfiguration( {
@@ -537,12 +573,11 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
537
573
  check_session_iframe:authorityConfiguration.check_session_iframe,
538
574
  });
539
575
  }
540
- if(this.initAsyncPromise){
541
- return this.initAsyncPromise;
542
- }
543
-
544
- this.initAsyncPromise = await fetchFromIssuer(authority, this.configuration.authority_time_cache_wellknowurl_in_second ?? 60 * 60);
545
- return this.initAsyncPromise;
576
+
577
+ const serviceWorker = await initWorkerAsync(this.configuration.service_worker_relative_url, this.configurationName);
578
+ const storage = serviceWorker ? window.localStorage : null;
579
+ const initAsyncPromise = await fetchFromIssuer(authority, this.configuration.authority_time_cache_wellknowurl_in_second ?? 60 * 60, storage);
580
+ return initAsyncPromise;
546
581
  }
547
582
 
548
583
  tryKeepExistingSessionPromise = null;
@@ -572,13 +607,15 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
572
607
  expiresIn: tokens.expires_in,
573
608
  idToken: tokens.id_token,
574
609
  scope: tokens.scope,
575
- tokenType: tokens.token_type
610
+ tokenType: tokens.token_type,
611
+ issuedAt: tokens.issued_at
576
612
  }
577
613
  this.tokens = await setTokensAsync(serviceWorker, reformattedToken);
578
614
  this.serviceWorker = serviceWorker;
579
615
  // @ts-ignore
580
616
  this.timeoutId = autoRenewTokens(this, this.tokens.refreshToken, this.tokens.expiresAt);
581
617
  const sessionState = await serviceWorker.getSessionStateAsync();
618
+ // @ts-ignore
582
619
  await this.startCheckSessionAsync(oidcServerConfiguration.check_session_iframe, configuration.client_id, sessionState);
583
620
  this.publishEvent(eventNames.tryKeepExistingSessionAsync_end, {
584
621
  success: true,
@@ -606,6 +643,7 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
606
643
  // @ts-ignore
607
644
  this.timeoutId = autoRenewTokens(this, tokens.refreshToken, this.tokens.expiresAt);
608
645
  const sessionState = session.getSessionState();
646
+ // @ts-ignore
609
647
  await this.startCheckSessionAsync(oidcServerConfiguration.check_session_iframe, configuration.client_id, sessionState);
610
648
  this.publishEvent(eventNames.tryKeepExistingSessionAsync_end, {
611
649
  success: true,
@@ -659,23 +697,6 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
659
697
 
660
698
  let serviceWorker = await initWorkerAsync(configuration.service_worker_relative_url, this.configurationName);
661
699
  const oidcServerConfiguration = await this.initAsync(configuration.authority, configuration.authority_configuration);
662
- /*if (serviceWorker && installServiceWorker) {
663
- const isServiceWorkerProxyActive = await serviceWorker.isServiceWorkerProxyActiveAsync();
664
- if (!isServiceWorkerProxyActive) {
665
- const isUnregistered = await serviceWorker.unregisterAsync();
666
- console.log("isUnregistered")
667
- console.log(isUnregistered)
668
- if(isUnregistered){
669
- serviceWorker = await initWorkerAsync(configuration.service_worker_relative_url, this.configurationName);
670
- }
671
- const extrasQueries = extras != null ? {...extras}: {};
672
- extrasQueries.callbackPath = url;
673
- extrasQueries.state = state;
674
- const queryString = buildQueries(extrasQueries);
675
- window.location.href = `${redirectUri}/service-worker-install${queryString}`;
676
- //return;
677
- }
678
- }*/
679
700
  let storage;
680
701
  if (serviceWorker) {
681
702
  serviceWorker.startKeepAliveServiceWorker();
@@ -744,9 +765,16 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
744
765
  else {
745
766
  console.debug("SessionMonitor._callback: Different subject signed into OP:", iFrameIdTokenPayload.sub);
746
767
  }
747
- }).catch((e) => {
748
- this.publishEvent(eventNames.logout_from_another_tab, {});
749
- this.destroyAsync();
768
+ }).catch(async (e) => {
769
+ for (const [key, oidc] of Object.entries(oidcDatabase)) {
770
+ //if(oidc !== this) {
771
+ // @ts-ignore
772
+ await oidc.logoutOtherTabAsync(idTokenPayload.sub);
773
+ //}
774
+ }
775
+ //await this.destroyAsync();
776
+ //this.publishEvent(eventNames.logout_from_another_tab, {message : "SessionMonitor"});
777
+
750
778
  });
751
779
  };
752
780
 
@@ -878,6 +906,7 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
878
906
  clearTimeout(timeoutId);
879
907
  this.timeoutId=null;
880
908
  const loginParams = getLoginParams(this.configurationName, redirectUri);
909
+ // @ts-ignore
881
910
  this.startCheckSessionAsync(oidcServerConfiguration.check_session_iframe, clientId, sessionState, isSilentSignin).then(() =>{
882
911
  this.publishEvent(eventNames.loginCallbackAsync_end, {});
883
912
  resolve({
@@ -911,7 +940,8 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
911
940
 
912
941
  const localsilentLoginAsync= async () => {
913
942
  try {
914
- const silent_token_response = await this.silentLoginAsync();
943
+ const loginParams = getLoginParams(this.configurationName, configuration.redirect_uri);
944
+ const silent_token_response = await this.silentLoginAsync(loginParams.extras, loginParams.state);
915
945
  if (silent_token_response) {
916
946
  return silent_token_response.tokens;
917
947
  }
@@ -952,7 +982,7 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
952
982
  };
953
983
 
954
984
  let index = 0;
955
- while (index <=2) {
985
+ while (index <=4) {
956
986
  try {
957
987
  this.publishEvent(eventNames.refreshTokensAsync_begin, {refreshToken:refreshToken, tryNumber: index});
958
988
  if(index > 1) {
@@ -960,6 +990,12 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
960
990
  await sleepAsync(1000);
961
991
  this.publishEvent(eventNames.refreshTokensAsync, {message: "wait because document is hidden"});
962
992
  }
993
+ let numberTryOnline = 6;
994
+ while (!navigator.onLine && numberTryOnline > 0) {
995
+ await sleepAsync(1000);
996
+ numberTryOnline--;
997
+ this.publishEvent(eventNames.refreshTokensAsync, {message: `wait because navigator is offline try ${numberTryOnline}` });
998
+ }
963
999
  }
964
1000
  const tokenResponse = await performTokenRequestAsync(oidcServerConfiguration.tokenEndpoint, details, extras)
965
1001
  if (tokenResponse.success) {
@@ -980,55 +1016,75 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
980
1016
 
981
1017
  syncTokensAsyncPromise=null;
982
1018
  async syncTokensAsync() {
983
- // Service Worker can be killed by the browser (when it wants,for example after 10 seconds of inactivity, so we retreieve the session if it happen)
984
- const configuration = this.configuration;
985
- if(!this.tokens){
986
- return;
987
- }
988
-
989
- const oidcServerConfiguration = await this.initAsync(configuration.authority, configuration.authority_configuration);
990
- const serviceWorker = await initWorkerAsync(configuration.service_worker_relative_url, this.configurationName);
991
- if (serviceWorker) {
992
- const { isLogin } = await serviceWorker.initAsync(oidcServerConfiguration, "syncTokensAsync");
993
- if(isLogin == false){
994
- this.publishEvent(eventNames.logout_from_another_tab, {});
995
- await this.destroyAsync();
1019
+
1020
+ const localSyncTokensAsync = async () => {
1021
+ // Service Worker can be killed by the browser (when it wants,for example after 10 seconds of inactivity, so we retreieve the session if it happen)
1022
+ const configuration = this.configuration;
1023
+ if (!this.tokens) {
1024
+ return null;
996
1025
  }
997
- else if (isLogin == null){
998
- try {
999
- this.publishEvent(eventNames.syncTokensAsync_begin, {});
1000
- this.syncTokensAsyncPromise = this.silentLoginAsync({prompt:"none"});
1001
- const silent_token_response = await this.syncTokensAsyncPromise;
1002
- if (silent_token_response && silent_token_response.tokens) {
1003
- this.tokens = await setTokensAsync(serviceWorker, silent_token_response.tokens);
1004
- } else{
1005
- this.publishEvent(eventNames.syncTokensAsync_error, {message:"no token found in result"});
1006
- if(this.timeoutId){
1026
+
1027
+ const oidcServerConfiguration = await this.initAsync(configuration.authority, configuration.authority_configuration);
1028
+ const serviceWorker = await initWorkerAsync(configuration.service_worker_relative_url, this.configurationName);
1029
+ if (serviceWorker) {
1030
+ const {isLogin} = await serviceWorker.initAsync(oidcServerConfiguration, "syncTokensAsync");
1031
+ if (isLogin == false) {
1032
+ this.publishEvent(eventNames.logout_from_another_tab, {"message": "service worker syncTokensAsync"});
1033
+ await this.destroyAsync();
1034
+ return null;
1035
+ } else if (isLogin == null) {
1036
+ try {
1037
+ this.publishEvent(eventNames.syncTokensAsync_begin, {});
1038
+ const loginParams = getLoginParams(this.configurationName, configuration.redirect_uri);
1039
+ const silent_token_response = await this.silentLoginAsync({...loginParams.extras,prompt: "none"}, loginParams.state);
1040
+ if (silent_token_response && silent_token_response.tokens) {
1041
+ this.tokens = await setTokensAsync(serviceWorker, silent_token_response.tokens);
1042
+ this.publishEvent(eventNames.syncTokensAsync_end, {});
1043
+ return this.tokens;
1044
+ } else {
1045
+ this.publishEvent(eventNames.syncTokensAsync_error, {message: "no token found in result"});
1046
+ if (this.timeoutId) {
1047
+ timer.clearTimeout(this.timeoutId);
1048
+ this.timeoutId = null;
1049
+ }
1050
+ this.publishEvent(eventNames.syncTokensAsync_end, {});
1051
+ return null;
1052
+ }
1053
+ } catch (exceptionSilent) {
1054
+ console.error(exceptionSilent);
1055
+ this.publishEvent(eventNames.syncTokensAsync_error, exceptionSilent);
1056
+ if (this.timeoutId) {
1007
1057
  timer.clearTimeout(this.timeoutId);
1008
- this.timeoutId=null;
1058
+ this.timeoutId = null;
1009
1059
  }
1010
- return;
1060
+ this.publishEvent(eventNames.syncTokensAsync_end, {});
1061
+ return null;
1011
1062
  }
1012
- } catch (exceptionSilent) {
1013
- console.error(exceptionSilent);
1014
- this.publishEvent(eventNames.syncTokensAsync_error, exceptionSilent);
1015
- if(this.timeoutId){
1016
- timer.clearTimeout(this.timeoutId);
1017
- this.timeoutId=null;
1018
- }
1019
- return;
1020
1063
  }
1021
- this.syncTokensAsyncPromise = null;
1022
- this.publishEvent(eventNames.syncTokensAsync_end, {});
1023
- }
1024
- } else {
1025
- const session = initSession(this.configurationName, configuration.redirect_uri, configuration.storage ?? sessionStorage);
1026
- const {tokens} = await session.initAsync();
1027
- if(!tokens){
1028
- this.publishEvent(eventNames.logout_from_another_tab, {});
1029
- await this.destroyAsync();
1064
+ } else {
1065
+ const session = initSession(this.configurationName, configuration.redirect_uri, configuration.storage ?? sessionStorage);
1066
+ const {tokens} = await session.initAsync();
1067
+ if (!tokens) {
1068
+ this.publishEvent(eventNames.logout_from_another_tab, {"message": "session syncTokensAsync"});
1069
+ await this.destroyAsync();
1070
+ return null;
1071
+ }
1030
1072
  }
1073
+ return this.tokens;
1074
+ }
1075
+
1076
+ if(this.syncTokensAsyncPromise){
1077
+ return this.syncTokensAsyncPromise;
1031
1078
  }
1079
+
1080
+ this.syncTokensAsyncPromise = localSyncTokensAsync().then(result =>{
1081
+ if(this.syncTokensAsyncPromise){
1082
+ this.syncTokensAsyncPromise = null;
1083
+ }
1084
+ return result;
1085
+ });
1086
+
1087
+ return this.syncTokensAsyncPromise
1032
1088
  }
1033
1089
 
1034
1090
 
@@ -1062,9 +1118,26 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
1062
1118
  }
1063
1119
  this.tokens = null;
1064
1120
  this.userInfo = null;
1065
- this.events = [];
1066
-
1121
+ // this.events = [];
1122
+ }
1123
+
1124
+ async logoutSameTabAsync(sub){
1125
+ // @ts-ignore
1126
+ if(this.configuration.monitor_session && sub && this.tokens && this.tokens.idTokenPayload && this.tokens.idTokenPayload.sub === sub) {
1127
+ this.publishEvent(eventNames.logout_from_same_tab, {"message": sub});
1128
+ await this.destroyAsync();
1129
+ }
1067
1130
  }
1131
+
1132
+ async logoutOtherTabAsync(sub){
1133
+ // @ts-ignore
1134
+
1135
+ if(this.configuration.monitor_session && sub && this.tokens && this.tokens.idTokenPayload && this.tokens.idTokenPayload.sub === sub) {
1136
+ await this.destroyAsync();
1137
+ console.log("logoutOtherTabAsync(sub)" +this.configurationName);
1138
+ this.publishEvent(eventNames.logout_from_another_tab, {message : "SessionMonitor", "sub": sub});
1139
+ }
1140
+ }
1068
1141
 
1069
1142
  async logoutAsync(callbackPathOrUrl: string | undefined = undefined, extras: StringMap = null) {
1070
1143
  const configuration = this.configuration;
@@ -1082,7 +1155,16 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
1082
1155
  const url = isUri ? callbackPathOrUrl : window.location.origin + path;
1083
1156
  // @ts-ignore
1084
1157
  const idToken = this.tokens ? this.tokens.idToken : "";
1085
- await this.destroyAsync();
1158
+ // @ts-ignore
1159
+ const sub = this.tokens && this.tokens.idTokenPayload ? this.tokens.idTokenPayload.sub : null;
1160
+ await this.destroyAsync();
1161
+ for (const [key, oidc] of Object.entries(oidcDatabase)) {
1162
+ if(oidc !== this) {
1163
+ // @ts-ignore
1164
+ await oidc.logoutSameTabAsync(sub);
1165
+ }
1166
+ }
1167
+
1086
1168
  if(oidcServerConfiguration.endSessionEndpoint) {
1087
1169
  let extraQueryString = "";
1088
1170
  if(extras){
@@ -1,4 +0,0 @@
1
- import { ComponentType } from 'react';
2
- declare const ServiceWorkerInstall: ComponentType<any>;
3
- export default ServiceWorkerInstall;
4
- //# sourceMappingURL=ServiceWorkerInstall.component.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ServiceWorkerInstall.component.d.ts","sourceRoot":"","sources":["../../../src/oidc/core/default-component/ServiceWorkerInstall.component.tsx"],"names":[],"mappings":"AAAA,OAAc,EAAsB,aAAa,EAAC,MAAM,OAAO,CAAC;AAMhE,QAAA,MAAM,oBAAoB,EAAE,aAAa,CAAC,GAAG,CAmD5C,CAAC;AAEF,eAAe,oBAAoB,CAAC"}