@axa-fr/react-oidc 6.0.0-beta11 → 6.0.0-beta14

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.
@@ -19,6 +19,7 @@ import timer from './timer';
19
19
  import {CheckSessionIFrame} from "./checkSessionIFrame"
20
20
  import {getParseQueryStringFromLocation} from "./route-utils";
21
21
  import {AuthorizationServiceConfigurationJson} from "@openid/appauth/src/authorization_service_configuration";
22
+ import {computeTimeLeft, isTokensValid, parseOriginalTokens, setTokens} from "./parseTokens";
22
23
 
23
24
  const performTokenRequestAsync= async (url, details, extras) => {
24
25
 
@@ -47,22 +48,9 @@ const performTokenRequestAsync= async (url, details, extras) => {
47
48
  return {success:false, status: response.status}
48
49
  }
49
50
  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
+ console.log(tokens);
56
52
  return { success : true,
57
- data : {
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
65
- }
53
+ data: parseOriginalTokens(tokens)
66
54
  };
67
55
  }
68
56
 
@@ -108,36 +96,6 @@ export class OidcAuthorizationServiceConfiguration extends AuthorizationServiceC
108
96
 
109
97
  }
110
98
 
111
- const idTokenPayload = (token) => {
112
- const base64Url = token.split('.')[1];
113
- const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
114
- const jsonPayload = decodeURIComponent(atob(base64).split('').map(function (c) {
115
- return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
116
- }).join(''));
117
-
118
- return JSON.parse(jsonPayload);
119
- }
120
-
121
- const countLetter = (str, find)=> {
122
- return (str.split(find)).length - 1;
123
- }
124
-
125
- const extractAccessTokenPayload = tokens => {
126
- if(tokens.accessTokenPayload)
127
- {
128
- return tokens.accessTokenPayload;
129
- }
130
- const accessToken = tokens.accessToken;
131
- try{
132
- if (!accessToken || countLetter(accessToken,'.') != 2) {
133
- return null;
134
- }
135
- return JSON.parse(atob(accessToken.split('.')[1]));
136
- } catch (e) {
137
- console.warn(e);
138
- }
139
- return null;
140
- };
141
99
 
142
100
  export interface StringMap {
143
101
  [key: string]: string;
@@ -193,34 +151,41 @@ const loginCallbackWithAutoTokensRenewAsync = async (oidc) => {
193
151
  }
194
152
 
195
153
  const autoRenewTokens = (oidc, refreshToken, expiresAt) => {
196
- const refreshTimeBeforeTokensExpirationInSecond = oidc.configuration.refresh_time_before_tokens_expiration_in_second ?? 60;
154
+ const refreshTimeBeforeTokensExpirationInSecond = oidc.configuration.refresh_time_before_tokens_expiration_in_second;
197
155
  return timer.setTimeout(async () => {
198
- const currentTimeUnixSecond = new Date().getTime() /1000;
199
- const timeInfo = { timeLeft: Math.round(((expiresAt - refreshTimeBeforeTokensExpirationInSecond) - currentTimeUnixSecond))};
156
+ const timeLeft = computeTimeLeft(refreshTimeBeforeTokensExpirationInSecond, expiresAt);
157
+ const timeInfo = { timeLeft };
200
158
  oidc.publishEvent(Oidc.eventNames.token_timer, timeInfo);
201
- if(currentTimeUnixSecond > (expiresAt - refreshTimeBeforeTokensExpirationInSecond)) {
202
- const tokens = await oidc.refreshTokensAsync(refreshToken);
203
- oidc.tokens= await setTokensAsync(oidc.serviceWorker, tokens);
159
+ // if(timeLeft <= 0) {
160
+ const tokens = await oidc.synchroniseTokensAsync(refreshToken);
161
+ oidc.tokens= tokens;
204
162
  if(!oidc.serviceWorker){
205
163
  await oidc.session.setTokens(oidc.tokens);
206
164
  }
207
165
  if(!oidc.tokens){
208
- if(oidc.checkSessionIFrame){
209
- oidc.checkSessionIFrame.stop();
210
- oidc.checkSessionIFrame = null;
211
- }
166
+ await oidc.destroyAsync();
167
+ oidc.publishEvent(eventNames.refreshTokensAsync_error, {message: `refresh token` });
212
168
  return;
213
169
  }
214
- oidc.publishEvent(Oidc.eventNames.token_renewed, {});
170
+
215
171
  if(oidc.timeoutId) {
216
172
  oidc.timeoutId = autoRenewTokens(oidc, tokens.refreshToken, oidc.tokens.expiresAt);
217
173
  }
218
- } else{
174
+ /*} else{
219
175
  const tokens = await oidc.syncTokensAsync();
176
+ oidc.tokens = tokens;
177
+ if(!oidc.serviceWorker){
178
+ await oidc.session.setTokens(oidc.tokens);
179
+ }
180
+ if(!oidc.tokens){
181
+ oidc.publishEvent(eventNames.refreshTokensAsync_error, {message: `sync` });
182
+ await oidc.destroyAsync();
183
+ return;
184
+ }
220
185
  if(tokens && oidc.timeoutId) {
221
186
  oidc.timeoutId = autoRenewTokens(oidc, tokens.refreshToken, tokens.expiresAt);
222
187
  }
223
- }
188
+ }*/
224
189
  }, 1000);
225
190
  }
226
191
 
@@ -238,11 +203,15 @@ const userInfoAsync = async (oidc) => {
238
203
  if(!oidc.tokens){
239
204
  return null;
240
205
  }
241
- if(oidc.syncTokensAsyncPromise){
242
- await oidc.syncTokensAsyncPromise;
243
- }
244
206
  const accessToken = oidc.tokens.accessToken;
245
-
207
+ if(!accessToken){
208
+ return null;
209
+ }
210
+ // We wait the synchronisation before making a request
211
+ while (oidc.tokens && !isTokensValid(oidc.tokens)){
212
+ await sleepAsync(200);
213
+ }
214
+
246
215
  const oidcServerConfiguration = await oidc.initAsync(oidc.configuration.authority, oidc.configuration.authority_configuration);
247
216
  const url = oidcServerConfiguration.userInfoEndpoint;
248
217
  const fetchUserInfo = async (accessToken) => {
@@ -264,28 +233,6 @@ const userInfoAsync = async (oidc) => {
264
233
  return userInfo;
265
234
  }
266
235
 
267
- const setTokensAsync = async (serviceWorker, tokens) =>{
268
- let accessTokenPayload;
269
- if(tokens == null){
270
- if(serviceWorker){
271
- await serviceWorker.clearAsync();
272
- }
273
- return null;
274
- }
275
- if(serviceWorker){
276
- accessTokenPayload = await serviceWorker.getAccessTokenPayloadAsync();
277
- }
278
- else {
279
- accessTokenPayload = extractAccessTokenPayload(tokens);
280
- }
281
- const _idTokenPayload = idTokenPayload(tokens.idToken);
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;
286
- return {...tokens, idTokenPayload: _idTokenPayload, accessTokenPayload, expiresAt};
287
- }
288
-
289
236
  const eventNames = {
290
237
  service_worker_not_supported_by_browser: "service_worker_not_supported_by_browser",
291
238
  token_aquired: "token_aquired",
@@ -383,7 +330,12 @@ export class Oidc {
383
330
  silent_login_uri = `${configuration.silent_redirect_uri.replace("-callback", "").replace("callback", "")}-login`;
384
331
  }
385
332
 
386
- this.configuration = {...configuration, silent_login_uri};
333
+ this.configuration = {...configuration,
334
+ silent_login_uri,
335
+ monitor_session: configuration.monitor_session ?? true,
336
+ refresh_time_before_tokens_expiration_in_second : configuration.refresh_time_before_tokens_expiration_in_second ?? 60,
337
+ silent_login_timeout: configuration.silent_login_timeout ?? 12000,
338
+ };
387
339
  this.configurationName= configurationName;
388
340
  this.tokens = null
389
341
  this.userInfo = null;
@@ -391,7 +343,7 @@ export class Oidc {
391
343
  this.timeoutId = null;
392
344
  this.serviceWorker = null;
393
345
  this.session = null;
394
- this.refreshTokensAsync.bind(this);
346
+ this.synchroniseTokensAsync.bind(this);
395
347
  this.loginCallbackWithAutoTokensRenewAsync.bind(this);
396
348
  this.initAsync.bind(this);
397
349
  this.loginCallbackAsync.bind(this);
@@ -461,17 +413,6 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
461
413
  if (!this.configuration.silent_redirect_uri || !this.configuration.silent_login_uri) {
462
414
  return Promise.resolve(null);
463
415
  }
464
- while (document.hidden) {
465
- await sleepAsync(1000);
466
- this.publishEvent(eventNames.silentLoginAsync, {message:"wait because document is hidden"});
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
- }
475
416
 
476
417
  try {
477
418
  this.publishEvent(eventNames.silentLoginAsync_begin, {});
@@ -542,7 +483,7 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
542
483
  }
543
484
  }
544
485
  };
545
- const silentSigninTimeout = configuration.silent_login_timeout ?? 12000
486
+ const silentSigninTimeout = configuration.silent_login_timeout;
546
487
  setTimeout(() => {
547
488
  if (!isResolved) {
548
489
  self.publishEvent(eventNames.silentLoginAsync_error, {reason: "timeout"});
@@ -576,8 +517,7 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
576
517
 
577
518
  const serviceWorker = await initWorkerAsync(this.configuration.service_worker_relative_url, this.configurationName);
578
519
  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;
520
+ return await fetchFromIssuer(authority, this.configuration.authority_time_cache_wellknowurl_in_second ?? 60 * 60, storage);
581
521
  }
582
522
 
583
523
  tryKeepExistingSessionPromise = null;
@@ -601,16 +541,7 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
601
541
  if (tokens) {
602
542
  serviceWorker.startKeepAliveServiceWorker();
603
543
  // @ts-ignore
604
- const reformattedToken = {
605
- accessToken : tokens.access_token,
606
- refreshToken : tokens.refresh_token,
607
- expiresIn: tokens.expires_in,
608
- idToken: tokens.id_token,
609
- scope: tokens.scope,
610
- tokenType: tokens.token_type,
611
- issuedAt: tokens.issued_at
612
- }
613
- this.tokens = await setTokensAsync(serviceWorker, reformattedToken);
544
+ this.tokens = tokens;
614
545
  this.serviceWorker = serviceWorker;
615
546
  // @ts-ignore
616
547
  this.timeoutId = autoRenewTokens(this, this.tokens.refreshToken, this.tokens.expiresAt);
@@ -637,7 +568,7 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
637
568
  const {tokens} = await session.initAsync();
638
569
  if (tokens) {
639
570
  // @ts-ignore
640
- this.tokens = await setTokensAsync(serviceWorker, tokens);
571
+ this.tokens = setTokens(tokens);
641
572
  //session.setTokens(this.tokens);
642
573
  this.session = session;
643
574
  // @ts-ignore
@@ -675,7 +606,7 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
675
606
  }
676
607
 
677
608
  loginPromise: Promise<any>=null;
678
- async loginAsync(callbackPath:string=undefined, extras:StringMap=null, installServiceWorker=true, state:string=undefined, isSilentSignin:boolean=false, scope:string=undefined) {
609
+ async loginAsync(callbackPath:string=undefined, extras:StringMap=null, state:string=undefined, isSilentSignin:boolean=false, scope:string=undefined) {
679
610
  if(this.loginPromise !== null){
680
611
  return this.loginPromise;
681
612
  }
@@ -765,9 +696,16 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
765
696
  else {
766
697
  console.debug("SessionMonitor._callback: Different subject signed into OP:", iFrameIdTokenPayload.sub);
767
698
  }
768
- }).catch((e) => {
769
- this.publishEvent(eventNames.logout_from_another_tab, {message : "SessionMonitor"});
770
- this.destroyAsync();
699
+ }).catch(async (e) => {
700
+ for (const [key, oidc] of Object.entries(oidcDatabase)) {
701
+ //if(oidc !== this) {
702
+ // @ts-ignore
703
+ await oidc.logoutOtherTabAsync(idTokenPayload.sub);
704
+ //}
705
+ }
706
+ //await this.destroyAsync();
707
+ //this.publishEvent(eventNames.logout_from_another_tab, {message : "SessionMonitor"});
708
+
771
709
  });
772
710
  };
773
711
 
@@ -794,7 +732,7 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
794
732
  const response = await this._loginCallbackAsync(isSilenSignin);
795
733
  // @ts-ignore
796
734
  const tokens = response.tokens;
797
- const parsedTokens = await setTokensAsync(this.serviceWorker, tokens);
735
+ const parsedTokens = setTokens(tokens);
798
736
  this.tokens = parsedTokens;
799
737
  if(!this.serviceWorker){
800
738
  await this.session.setTokens(parsedTokens);
@@ -929,158 +867,140 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
929
867
  }
930
868
  }
931
869
 
932
- async refreshTokensAsync(refreshToken) {
870
+ async synchroniseTokensAsync(refreshToken, index=0) {
933
871
 
872
+ if (document.hidden) {
873
+ await sleepAsync(1000);
874
+ this.publishEvent(eventNames.refreshTokensAsync, {message: "wait because document is hidden"});
875
+ return await this.synchroniseTokensAsync(refreshToken, index);
876
+ }
877
+ let numberTryOnline = 6;
878
+ while (!navigator.onLine && numberTryOnline > 0) {
879
+ await sleepAsync(1000);
880
+ numberTryOnline--;
881
+ this.publishEvent(eventNames.refreshTokensAsync, {message: `wait because navigator is offline try ${numberTryOnline}` });
882
+ }
883
+
884
+ const configuration = this.configuration;
934
885
  const localsilentLoginAsync= async () => {
935
886
  try {
936
887
  const loginParams = getLoginParams(this.configurationName, configuration.redirect_uri);
937
- const silent_token_response = await this.silentLoginAsync(loginParams.extras, loginParams.state);
888
+ const silent_token_response = await this.silentLoginAsync({
889
+ ...loginParams.extras,
890
+ prompt: "none"
891
+ }, loginParams.state);
938
892
  if (silent_token_response) {
893
+ this.publishEvent(Oidc.eventNames.token_renewed, {});
939
894
  return silent_token_response.tokens;
940
895
  }
941
896
  } catch (exceptionSilent) {
942
- console.error(exceptionSilent);
943
- }
944
- if(this.timeoutId){
945
- timer.clearTimeout(this.timeoutId);
946
- this.timeoutId=null;
897
+ if(exceptionSilent && exceptionSilent.message && exceptionSilent.message.startsWith("oidc")){
898
+ return null;
899
+ }
900
+ throw exceptionSilent;
947
901
  }
948
- this.publishEvent(eventNames.refreshTokensAsync_error, {message: "refresh token and silent refresh failed"});
949
902
  return null;
950
903
  }
951
-
952
- const configuration = this.configuration;
953
- const clientId = configuration.client_id;
954
- const redirectUri = configuration.redirect_uri;
955
- const authority = configuration.authority;
956
-
957
- if(!refreshToken)
958
- {
959
- return await localsilentLoginAsync();
960
- }
961
-
962
- let extras = {};
963
- if(configuration.token_request_extras) {
964
- for (let [key, value] of Object.entries(configuration.token_request_extras)) {
965
- extras[key] = value;
966
- }
967
- }
968
- const oidcServerConfiguration = await this.initAsync(authority, configuration.authority_configuration);
969
-
970
- const details = {
971
- client_id: clientId,
972
- redirect_uri: redirectUri,
973
- grant_type: GRANT_TYPE_REFRESH_TOKEN,
974
- refresh_token: refreshToken,
975
- };
976
904
 
977
- let index = 0;
978
- while (index <=4) {
905
+ if (index <=4) {
979
906
  try {
980
- this.publishEvent(eventNames.refreshTokensAsync_begin, {refreshToken:refreshToken, tryNumber: index});
981
- if(index > 1) {
982
- while (document.hidden) {
983
- await sleepAsync(1000);
984
- this.publishEvent(eventNames.refreshTokensAsync, {message: "wait because document is hidden"});
985
- }
986
- let numberTryOnline = 6;
987
- while (!navigator.onLine && numberTryOnline > 0) {
988
- await sleepAsync(1000);
989
- numberTryOnline--;
990
- this.publishEvent(eventNames.refreshTokensAsync, {message: `wait because navigator is offline try ${numberTryOnline}` });
991
- }
992
- }
993
- const tokenResponse = await performTokenRequestAsync(oidcServerConfiguration.tokenEndpoint, details, extras)
994
- if (tokenResponse.success) {
995
- this.publishEvent(eventNames.refreshTokensAsync_end, {success: tokenResponse.success});
996
- return tokenResponse.data;
997
- } else {
998
- this.publishEvent(eventNames.refreshTokensAsync_silent_error, {message: "bad request" , tokenResponse: tokenResponse});
907
+
908
+ if(!refreshToken)
909
+ {
910
+ this.publishEvent(eventNames.refreshTokensAsync_begin, {refreshToken:refreshToken, tryNumber: index});
999
911
  return await localsilentLoginAsync();
1000
912
  }
913
+ const { status, tokens } = await this.syncTokensInfoAsync(configuration, this.configurationName, this.tokens);
914
+ // this.publishEvent(eventNames.refreshTokensAsync, {message: `status ${status}` });
915
+ switch (status) {
916
+ case "NOT_CONNECTED":
917
+ return null;
918
+ case "TOKENS_VALID":
919
+ case "TOKEN_UPDATED_BY_ANOTHER_TAB_TOKENS_VALID":
920
+ return tokens;
921
+ case "LOGOUT_FROM_ANOTHER_TAB":
922
+ this.publishEvent(eventNames.logout_from_another_tab, {"status": "session syncTokensAsync"});
923
+ return null;
924
+ case "REQUIRE_SYNC_TOKENS":
925
+ this.publishEvent(eventNames.refreshTokensAsync_begin, {refreshToken:refreshToken, status, tryNumber: index});
926
+ return await localsilentLoginAsync();
927
+ default:
928
+ this.publishEvent(eventNames.refreshTokensAsync_begin, {refreshToken:refreshToken, status, tryNumber: index});
929
+ const clientId = configuration.client_id;
930
+ const redirectUri = configuration.redirect_uri;
931
+ const authority = configuration.authority;
932
+ let extras = {};
933
+ if(configuration.token_request_extras) {
934
+ for (let [key, value] of Object.entries(configuration.token_request_extras)) {
935
+ extras[key] = value;
936
+ }
937
+ }
938
+ const details = {
939
+ client_id: clientId,
940
+ redirect_uri: redirectUri,
941
+ grant_type: GRANT_TYPE_REFRESH_TOKEN,
942
+ refresh_token: tokens.refreshToken,
943
+ };
944
+ const oidcServerConfiguration = await this.initAsync(authority, configuration.authority_configuration);
945
+ const tokenResponse = await performTokenRequestAsync(oidcServerConfiguration.tokenEndpoint, details, extras)
946
+ if (tokenResponse.success) {
947
+ this.publishEvent(eventNames.refreshTokensAsync_end, {success: tokenResponse.success});
948
+ this.publishEvent(Oidc.eventNames.token_renewed, {});
949
+ return tokenResponse.data;
950
+ } else {
951
+ this.publishEvent(eventNames.refreshTokensAsync_silent_error, {
952
+ message: "bad request",
953
+ tokenResponse: tokenResponse
954
+ });
955
+ return await this.synchroniseTokensAsync(null, index+1);
956
+ }
957
+ }
1001
958
  } catch (exception) {
1002
959
  console.error(exception);
1003
960
  this.publishEvent(eventNames.refreshTokensAsync_silent_error, {message: "exception" ,exception: exception.message});
961
+ return this.synchroniseTokensAsync(refreshToken, index+1);
1004
962
  }
1005
- index++;
1006
963
  }
1007
-
964
+ return null;
1008
965
  }
1009
966
 
1010
- syncTokensAsyncPromise=null;
1011
- async syncTokensAsync() {
1012
-
1013
- const localSyncTokensAsync = async () => {
1014
- // 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)
1015
- const configuration = this.configuration;
1016
- if (!this.tokens) {
1017
- return null;
1018
- }
967
+ async syncTokensInfoAsync(configuration, configurationName, currentTokens) {
968
+ // 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)
969
+ //const configuration = this.configuration;
970
+ if (!currentTokens) {
971
+ return { tokens : null, status: "NOT_CONNECTED"};
972
+ }
1019
973
 
1020
- const oidcServerConfiguration = await this.initAsync(configuration.authority, configuration.authority_configuration);
1021
- const serviceWorker = await initWorkerAsync(configuration.service_worker_relative_url, this.configurationName);
1022
- if (serviceWorker) {
1023
- const {isLogin} = await serviceWorker.initAsync(oidcServerConfiguration, "syncTokensAsync");
1024
- if (isLogin == false) {
1025
- this.publishEvent(eventNames.logout_from_another_tab, {"message": "service worker syncTokensAsync"});
1026
- await this.destroyAsync();
1027
- return null;
1028
- } else if (isLogin == null) {
1029
- try {
1030
- this.publishEvent(eventNames.syncTokensAsync_begin, {});
1031
- const loginParams = getLoginParams(this.configurationName, configuration.redirect_uri);
1032
- const silent_token_response = await this.silentLoginAsync({...loginParams.extras,prompt: "none"}, loginParams.state);
1033
- if (silent_token_response && silent_token_response.tokens) {
1034
- this.tokens = await setTokensAsync(serviceWorker, silent_token_response.tokens);
1035
- this.publishEvent(eventNames.syncTokensAsync_end, {});
1036
- return this.tokens;
1037
- } else {
1038
- this.publishEvent(eventNames.syncTokensAsync_error, {message: "no token found in result"});
1039
- if (this.timeoutId) {
1040
- timer.clearTimeout(this.timeoutId);
1041
- this.timeoutId = null;
1042
- }
1043
- this.publishEvent(eventNames.syncTokensAsync_end, {});
1044
- return null;
1045
- }
1046
- } catch (exceptionSilent) {
1047
- console.error(exceptionSilent);
1048
- this.publishEvent(eventNames.syncTokensAsync_error, exceptionSilent);
1049
- if (this.timeoutId) {
1050
- timer.clearTimeout(this.timeoutId);
1051
- this.timeoutId = null;
1052
- }
1053
- this.publishEvent(eventNames.syncTokensAsync_end, {});
1054
- return null;
1055
- }
1056
- }
1057
- } else {
1058
- const session = initSession(this.configurationName, configuration.redirect_uri, configuration.storage ?? sessionStorage);
1059
- const {tokens} = await session.initAsync();
1060
- if (!tokens) {
1061
- this.publishEvent(eventNames.logout_from_another_tab, {"message": "session syncTokensAsync"});
1062
- await this.destroyAsync();
1063
- return null;
1064
- }
974
+ const oidcServerConfiguration = await this.initAsync(configuration.authority, configuration.authority_configuration);
975
+ const serviceWorker = await initWorkerAsync(configuration.service_worker_relative_url, configurationName);
976
+ if (serviceWorker) {
977
+ const {isLogin, tokens} = await serviceWorker.initAsync(oidcServerConfiguration, "syncTokensAsync");
978
+ if (isLogin == false) {
979
+ return { tokens : null, status: "LOGOUT_FROM_ANOTHER_TAB"};
980
+ } else if (isLogin == null) {
981
+ return { tokens : null, status: "REQUIRE_SYNC_TOKENS"};
982
+ } else if(tokens.issuedAt !== currentTokens.issuedAt) {
983
+ const timeLeft = computeTimeLeft(configuration.refresh_time_before_tokens_expiration_in_second, tokens.expiresAt);
984
+ const status = (timeLeft > 0) ? "TOKEN_UPDATED_BY_ANOTHER_TAB_TOKENS_VALID" : "TOKEN_UPDATED_BY_ANOTHER_TAB_TOKENS_INVALID";
985
+ return { tokens : tokens, status };
986
+ }
987
+ } else {
988
+ const session = initSession(configurationName, configuration.redirect_uri, configuration.storage ?? sessionStorage);
989
+ const {tokens} = await session.initAsync();
990
+ if (!tokens) {
991
+ return { tokens : null, status: "LOGOUT_FROM_ANOTHER_TAB"};
992
+ } else if(tokens.issuedAt !== currentTokens.issuedAt){
993
+ const timeLeft = computeTimeLeft(configuration.refresh_time_before_tokens_expiration_in_second, tokens.expiresAt);
994
+ const status = (timeLeft > 0) ? "TOKEN_UPDATED_BY_ANOTHER_TAB_TOKENS_VALID" : "TOKEN_UPDATED_BY_ANOTHER_TAB_TOKENS_INVALID";
995
+ return { tokens : tokens, status };
1065
996
  }
1066
- return this.tokens;
1067
- }
1068
-
1069
- if(this.syncTokensAsyncPromise){
1070
- return this.syncTokensAsyncPromise;
1071
997
  }
1072
998
 
1073
- this.syncTokensAsyncPromise = localSyncTokensAsync().then(result =>{
1074
- if(this.syncTokensAsyncPromise){
1075
- this.syncTokensAsyncPromise = null;
1076
- }
1077
- return result;
1078
- });
1079
-
1080
- return this.syncTokensAsyncPromise
999
+ const timeLeft = computeTimeLeft(configuration.refresh_time_before_tokens_expiration_in_second, currentTokens.expiresAt);
1000
+ const status = (timeLeft > 0) ? "TOKENS_VALID" : "TOKENS_INVALID";
1001
+ return { tokens:currentTokens, status};
1081
1002
  }
1082
1003
 
1083
-
1084
1004
  loginCallbackWithAutoTokensRenewPromise:Promise<loginCallbackResult> = null;
1085
1005
  loginCallbackWithAutoTokensRenewAsync():Promise<loginCallbackResult>{
1086
1006
  if(this.loginCallbackWithAutoTokensRenewPromise !== null){
@@ -1111,7 +1031,7 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
1111
1031
  }
1112
1032
  this.tokens = null;
1113
1033
  this.userInfo = null;
1114
- this.events = [];
1034
+ // this.events = [];
1115
1035
  }
1116
1036
 
1117
1037
  async logoutSameTabAsync(sub){
@@ -1121,6 +1041,15 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
1121
1041
  await this.destroyAsync();
1122
1042
  }
1123
1043
  }
1044
+
1045
+ async logoutOtherTabAsync(sub){
1046
+ // @ts-ignore
1047
+ if(this.configuration.monitor_session && sub && this.tokens && this.tokens.idTokenPayload && this.tokens.idTokenPayload.sub === sub) {
1048
+ await this.destroyAsync();
1049
+ console.log("logoutOtherTabAsync(sub)" +this.configurationName);
1050
+ this.publishEvent(eventNames.logout_from_another_tab, {message : "SessionMonitor", "sub": sub});
1051
+ }
1052
+ }
1124
1053
 
1125
1054
  async logoutAsync(callbackPathOrUrl: string | undefined = undefined, extras: StringMap = null) {
1126
1055
  const configuration = this.configuration;