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

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.
@@ -18,7 +18,7 @@ let database = {
18
18
  default: {
19
19
  configurationName: "default",
20
20
  tokens: null,
21
- isLogin:null,
21
+ status:null,
22
22
  items:[],
23
23
  oidcServerConfiguration: null
24
24
  }
@@ -44,12 +44,12 @@ const extractTokenPayload=(accessToken)=> {
44
44
  return null;
45
45
  }
46
46
 
47
- export const computeTimeLeft = (refreshTimeBeforeTokensExpirationInSecond, expiresAt)=>{
47
+ const computeTimeLeft = (refreshTimeBeforeTokensExpirationInSecond, expiresAt)=>{
48
48
  const currentTimeUnixSecond = new Date().getTime() /1000;
49
49
  return Math.round(((expiresAt - refreshTimeBeforeTokensExpirationInSecond) - currentTimeUnixSecond));
50
50
  }
51
51
 
52
- export const isTokensValid= (tokens) =>{
52
+ const isTokensValid= (tokens) =>{
53
53
  if(!tokens){
54
54
  return false;
55
55
  }
@@ -65,7 +65,7 @@ function hideTokens(currentDatabaseElement) {
65
65
  tokens.issued_at = currentTimeUnixSecond;
66
66
  }
67
67
  currentDatabaseElement.tokens = tokens;
68
- currentDatabaseElement.isLogin = true;
68
+ currentDatabaseElement.status = "LOGGED_IN";
69
69
  const accessTokenPayload = extractTokenPayload(tokens.access_token);
70
70
  const secureTokens = {
71
71
  ...tokens,
@@ -85,8 +85,8 @@ function hideTokens(currentDatabaseElement) {
85
85
  const idTokenExipreAt =(_idTokenPayload && _idTokenPayload.exp) ? _idTokenPayload.exp: Number.MAX_VALUE;
86
86
  const accessTokenExpiresAt = (accessTokenPayload && accessTokenPayload.exp)? accessTokenPayload.exp : tokens.issuedAt + tokens.expiresIn;
87
87
  const expiresAt = idTokenExipreAt < accessTokenExpiresAt ? idTokenExipreAt : accessTokenExpiresAt;
88
- secureTokens.expireAt = expiresAt;
89
-
88
+ secureTokens.expiresAt = expiresAt;
89
+ tokens.expiresAt = expiresAt;
90
90
 
91
91
  const body = JSON.stringify(secureTokens)
92
92
  return new Response(body, response);
@@ -297,7 +297,7 @@ addEventListener('message', event => {
297
297
  tokens: null,
298
298
  items:[],
299
299
  oidcServerConfiguration: null,
300
- isLogin:null,
300
+ status:null,
301
301
  configurationName: configurationName,
302
302
  };
303
303
  currentDatabase = database[configurationName];
@@ -312,7 +312,7 @@ addEventListener('message', event => {
312
312
  case "clear":
313
313
  currentDatabase.tokens = null;
314
314
  currentDatabase.items = null;
315
- currentDatabase.isLogin = false;
315
+ currentDatabase.status = data.data.status;
316
316
  port.postMessage({configurationName});
317
317
  return;
318
318
  case "init":
@@ -333,7 +333,7 @@ addEventListener('message', event => {
333
333
  if(!currentDatabase.tokens){
334
334
  port.postMessage({
335
335
  tokens:null,
336
- isLogin: currentDatabase.isLogin,
336
+ status: currentDatabase.status,
337
337
  configurationName});
338
338
  } else {
339
339
  const tokens = {
@@ -345,16 +345,11 @@ addEventListener('message', event => {
345
345
  }
346
346
  port.postMessage({
347
347
  tokens,
348
- isLogin: currentDatabase.isLogin,
348
+ status: currentDatabase.status,
349
349
  configurationName
350
350
  });
351
351
  }
352
352
  return;
353
-
354
- /*case "getAccessTokenPayload":
355
- const accessTokenPayload = extractAccessTokenPayload(currentDatabase.tokens.access_token);
356
- port.postMessage({configurationName, accessTokenPayload});
357
- return;*/
358
353
 
359
354
  case "setSessionState":
360
355
  currentDatabase.sessionState = data.data.sessionState;
@@ -9,22 +9,21 @@
9
9
  return Promise.resolve(JSON.parse(storage[`oidc_items.${configurationName}:${redirectUri}`]));
10
10
  }
11
11
 
12
- const clearAsync=() =>{
13
- storage[`oidc.${configurationName}:${redirectUri}`] = JSON.stringify({tokens:null});
12
+ const clearAsync=(status) =>{
13
+ storage[`oidc.${configurationName}:${redirectUri}`] = JSON.stringify({tokens:null, status});
14
14
  return Promise.resolve();
15
15
  }
16
16
 
17
17
  const initAsync=async () => {
18
18
  if(!storage[`oidc.${configurationName}:${redirectUri}`]){
19
- storage[`oidc.${configurationName}:${redirectUri}`] = JSON.stringify({tokens:null});
20
- return {tokens:null};
19
+ storage[`oidc.${configurationName}:${redirectUri}`] = JSON.stringify({tokens:null, status:null});
20
+ return {tokens:null, status:null};
21
21
  }
22
- return Promise.resolve({ tokens : JSON.parse(storage[`oidc.${configurationName}:${redirectUri}`]).tokens });
22
+ const data = JSON.parse(storage[`oidc.${configurationName}:${redirectUri}`]);
23
+ return Promise.resolve({ tokens : data.tokens, status: data.status });
23
24
  }
24
25
 
25
26
  const setTokens = (tokens) => {
26
- //console.log("setTokens");
27
- //console.log(tokens);
28
27
  storage[`oidc.${configurationName}:${redirectUri}`] = JSON.stringify({tokens});
29
28
  }
30
29
 
@@ -107,19 +107,9 @@ export const initWorkerAsync = async(serviceWorkerRelativeUrl, configurationName
107
107
  const unregisterAsync = async () => {
108
108
  return await registration.unregister();
109
109
  }
110
-
111
- /* const getAccessTokenPayloadAsync=async () => {
112
- const result = await sendMessageAsync(registration)({
113
- type: "getAccessTokenPayload",
114
- data: null,
115
- configurationName
116
- });
117
- // @ts-ignore
118
- return result.accessTokenPayload;
119
- }*/
120
-
121
- const clearAsync=() =>{
122
- return sendMessageAsync(registration)({type: "clear", data: null, configurationName});
110
+
111
+ const clearAsync=(status) =>{
112
+ return sendMessageAsync(registration)({type: "clear", data: {status}, configurationName});
123
113
  }
124
114
  const initAsync= async (oidcServerConfiguration, where) => {
125
115
  const result = await sendMessageAsync(registration)({
@@ -128,7 +118,7 @@ export const initWorkerAsync = async(serviceWorkerRelativeUrl, configurationName
128
118
  configurationName
129
119
  });
130
120
  // @ts-ignore
131
- return { tokens : parseOriginalTokens(result.tokens), isLogin: result.isLogin};
121
+ return { tokens : parseOriginalTokens(result.tokens), status: result.status};
132
122
  }
133
123
 
134
124
  const startKeepAliveServiceWorker = () => {
@@ -48,8 +48,8 @@ const performTokenRequestAsync= async (url, details, extras) => {
48
48
  return {success:false, status: response.status}
49
49
  }
50
50
  const tokens = await response.json();
51
- console.log(tokens);
52
- return { success : true,
51
+ return {
52
+ success : true,
53
53
  data: parseOriginalTokens(tokens)
54
54
  };
55
55
  }
@@ -70,7 +70,6 @@ const internalFetch = async (url, headers, numberRetry=0) => {
70
70
  throw e;
71
71
  }
72
72
  } else {
73
-
74
73
  console.error(e.message);
75
74
  throw e; // rethrow other unexpected errors
76
75
  }
@@ -156,44 +155,40 @@ const autoRenewTokens = (oidc, refreshToken, expiresAt) => {
156
155
  const timeLeft = computeTimeLeft(refreshTimeBeforeTokensExpirationInSecond, expiresAt);
157
156
  const timeInfo = { timeLeft };
158
157
  oidc.publishEvent(Oidc.eventNames.token_timer, timeInfo);
159
- // if(timeLeft <= 0) {
160
- const tokens = await oidc.synchroniseTokensAsync(refreshToken);
158
+ const {tokens, status} = await oidc.synchroniseTokensAsync(refreshToken);
161
159
  oidc.tokens= tokens;
162
160
  if(!oidc.serviceWorker){
163
161
  await oidc.session.setTokens(oidc.tokens);
164
162
  }
165
163
  if(!oidc.tokens){
166
- await oidc.destroyAsync();
167
- oidc.publishEvent(eventNames.refreshTokensAsync_error, {message: `refresh token` });
164
+ await oidc.destroyAsync(status);
168
165
  return;
169
166
  }
170
167
 
171
168
  if(oidc.timeoutId) {
172
169
  oidc.timeoutId = autoRenewTokens(oidc, tokens.refreshToken, oidc.tokens.expiresAt);
173
170
  }
174
- /*} else{
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
- }
185
- if(tokens && oidc.timeoutId) {
186
- oidc.timeoutId = autoRenewTokens(oidc, tokens.refreshToken, tokens.expiresAt);
187
- }
188
- }*/
171
+
189
172
  }, 1000);
190
173
  }
191
174
 
192
175
  const getLoginSessionKey = (configurationName:string, redirectUri:string) => {
193
176
  return `oidc_login.${configurationName}:${redirectUri}`;
194
177
  }
178
+
179
+ const setLoginParams = (configurationName:string, redirectUri:string, data) =>{
180
+ const sessionKey = getLoginSessionKey(configurationName, redirectUri);
181
+ getLoginParamsCache = data
182
+ sessionStorage[sessionKey] = JSON.stringify(data);
183
+ }
184
+
185
+ let getLoginParamsCache = null;
195
186
  const getLoginParams = (configurationName, redirectUri) => {
196
- return JSON.parse(sessionStorage[getLoginSessionKey(configurationName, redirectUri)]);
187
+ const dataString = sessionStorage[getLoginSessionKey(configurationName, redirectUri)];
188
+ if(!getLoginParamsCache){
189
+ getLoginParamsCache = JSON.parse(dataString);
190
+ }
191
+ return getLoginParamsCache;
197
192
  }
198
193
 
199
194
  const userInfoAsync = async (oidc) => {
@@ -623,9 +618,8 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
623
618
  scope = configuration.scope;
624
619
  }
625
620
 
626
- const sessionKey = getLoginSessionKey(this.configurationName, redirectUri);
627
- sessionStorage[sessionKey] = JSON.stringify({callbackPath: url, extras, state});
628
-
621
+ setLoginParams(this.configurationName, redirectUri, {callbackPath: url, extras, state});
622
+
629
623
  let serviceWorker = await initWorkerAsync(configuration.service_worker_relative_url, this.configurationName);
630
624
  const oidcServerConfiguration = await this.initAsync(configuration.authority, configuration.authority_configuration);
631
625
  let storage;
@@ -700,7 +694,7 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
700
694
  for (const [key, oidc] of Object.entries(oidcDatabase)) {
701
695
  //if(oidc !== this) {
702
696
  // @ts-ignore
703
- await oidc.logoutOtherTabAsync(idTokenPayload.sub);
697
+ await oidc.logoutOtherTabAsync(this.configuration.client_id, idTokenPayload.sub);
704
698
  //}
705
699
  }
706
700
  //await this.destroyAsync();
@@ -891,15 +885,20 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
891
885
  }, loginParams.state);
892
886
  if (silent_token_response) {
893
887
  this.publishEvent(Oidc.eventNames.token_renewed, {});
894
- return silent_token_response.tokens;
888
+ return {tokens:silent_token_response.tokens, status:"LOGGED"};
895
889
  }
896
890
  } catch (exceptionSilent) {
891
+ console.error(exceptionSilent);
892
+ this.publishEvent(eventNames.refreshTokensAsync_silent_error, {message: "exceptionSilent" ,exception: exceptionSilent.message});
897
893
  if(exceptionSilent && exceptionSilent.message && exceptionSilent.message.startsWith("oidc")){
898
- return null;
899
- }
894
+ this.publishEvent(eventNames.refreshTokensAsync_error, {message: `refresh token silent` });
895
+ return {tokens:null, status:"SESSION_LOST"};
896
+ }
897
+ await sleepAsync(1000);
900
898
  throw exceptionSilent;
901
899
  }
902
- return null;
900
+ this.publishEvent(eventNames.refreshTokensAsync_error, {message: `refresh token silent return` });
901
+ return {tokens:null, status:"SESSION_LOST"};
903
902
  }
904
903
 
905
904
  if (index <=4) {
@@ -911,16 +910,18 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
911
910
  return await localsilentLoginAsync();
912
911
  }
913
912
  const { status, tokens } = await this.syncTokensInfoAsync(configuration, this.configurationName, this.tokens);
914
- // this.publishEvent(eventNames.refreshTokensAsync, {message: `status ${status}` });
915
913
  switch (status) {
914
+ case "SESSION_LOST":
915
+ this.publishEvent(eventNames.refreshTokensAsync_error, {message: `refresh token session lost` });
916
+ return {tokens:null, status:"SESSION_LOST"};
916
917
  case "NOT_CONNECTED":
917
- return null;
918
+ return {tokens:null, status:null};
918
919
  case "TOKENS_VALID":
919
920
  case "TOKEN_UPDATED_BY_ANOTHER_TAB_TOKENS_VALID":
920
- return tokens;
921
+ return {tokens, status:"LOGGED_IN"};
921
922
  case "LOGOUT_FROM_ANOTHER_TAB":
922
923
  this.publishEvent(eventNames.logout_from_another_tab, {"status": "session syncTokensAsync"});
923
- return null;
924
+ return {tokens:null, status:"LOGGED_OUT"};
924
925
  case "REQUIRE_SYNC_TOKENS":
925
926
  this.publishEvent(eventNames.refreshTokensAsync_begin, {refreshToken:refreshToken, status, tryNumber: index});
926
927
  return await localsilentLoginAsync();
@@ -946,7 +947,7 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
946
947
  if (tokenResponse.success) {
947
948
  this.publishEvent(eventNames.refreshTokensAsync_end, {success: tokenResponse.success});
948
949
  this.publishEvent(Oidc.eventNames.token_renewed, {});
949
- return tokenResponse.data;
950
+ return {tokens: tokenResponse.data, status:"LOGGED_IN"};
950
951
  } else {
951
952
  this.publishEvent(eventNames.refreshTokensAsync_silent_error, {
952
953
  message: "bad request",
@@ -961,7 +962,9 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
961
962
  return this.synchroniseTokensAsync(refreshToken, index+1);
962
963
  }
963
964
  }
964
- return null;
965
+
966
+ this.publishEvent(eventNames.refreshTokensAsync_error, {message: `refresh token` });
967
+ return {tokens:null, status:"SESSION_LOST"};
965
968
  }
966
969
 
967
970
  async syncTokensInfoAsync(configuration, configurationName, currentTokens) {
@@ -974,10 +977,12 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
974
977
  const oidcServerConfiguration = await this.initAsync(configuration.authority, configuration.authority_configuration);
975
978
  const serviceWorker = await initWorkerAsync(configuration.service_worker_relative_url, configurationName);
976
979
  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) {
980
+ const {status, tokens} = await serviceWorker.initAsync(oidcServerConfiguration, "syncTokensAsync");
981
+ if (status == "LOGGED_OUT") {
982
+ return {tokens: null, status: "LOGOUT_FROM_ANOTHER_TAB"};
983
+ }else if (status == "SESSIONS_LOST") {
984
+ return { tokens : null, status: "SESSIONS_LOST"};
985
+ } else if (!status || !tokens) {
981
986
  return { tokens : null, status: "REQUIRE_SYNC_TOKENS"};
982
987
  } else if(tokens.issuedAt !== currentTokens.issuedAt) {
983
988
  const timeLeft = computeTimeLeft(configuration.refresh_time_before_tokens_expiration_in_second, tokens.expiresAt);
@@ -986,10 +991,13 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
986
991
  }
987
992
  } else {
988
993
  const session = initSession(configurationName, configuration.redirect_uri, configuration.storage ?? sessionStorage);
989
- const {tokens} = await session.initAsync();
994
+ const {tokens, status } = await session.initAsync();
990
995
  if (!tokens) {
991
- return { tokens : null, status: "LOGOUT_FROM_ANOTHER_TAB"};
992
- } else if(tokens.issuedAt !== currentTokens.issuedAt){
996
+ return {tokens: null, status: "LOGOUT_FROM_ANOTHER_TAB"};
997
+ } else if (status == "SESSIONS_LOST") {
998
+ return { tokens : null, status: "SESSIONS_LOST"};
999
+ }
1000
+ else if(tokens.issuedAt !== currentTokens.issuedAt){
993
1001
  const timeLeft = computeTimeLeft(configuration.refresh_time_before_tokens_expiration_in_second, tokens.expiresAt);
994
1002
  const status = (timeLeft > 0) ? "TOKEN_UPDATED_BY_ANOTHER_TAB_TOKENS_VALID" : "TOKEN_UPDATED_BY_ANOTHER_TAB_TOKENS_INVALID";
995
1003
  return { tokens : tokens, status };
@@ -1017,36 +1025,35 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
1017
1025
  return userInfoAsync(this);
1018
1026
  }
1019
1027
 
1020
- async destroyAsync() {
1028
+ async destroyAsync(status) {
1021
1029
  timer.clearTimeout(this.timeoutId);
1022
1030
  this.timeoutId=null;
1023
1031
  if(this.checkSessionIFrame){
1024
1032
  this.checkSessionIFrame.stop();
1025
1033
  }
1026
1034
  if(this.serviceWorker){
1027
- await this.serviceWorker.clearAsync();
1035
+ await this.serviceWorker.clearAsync(status);
1028
1036
  }
1029
1037
  if(this.session){
1030
- await this.session.clearAsync();
1038
+ await this.session.clearAsync(status);
1031
1039
  }
1032
1040
  this.tokens = null;
1033
1041
  this.userInfo = null;
1034
1042
  // this.events = [];
1035
1043
  }
1036
1044
 
1037
- async logoutSameTabAsync(sub){
1045
+ async logoutSameTabAsync(clientId, sub){
1038
1046
  // @ts-ignore
1039
- if(this.configuration.monitor_session && sub && this.tokens && this.tokens.idTokenPayload && this.tokens.idTokenPayload.sub === sub) {
1047
+ if(this.configuration.monitor_session&& this.configuration.client_id === clientId && sub && this.tokens && this.tokens.idTokenPayload && this.tokens.idTokenPayload.sub === sub) {
1040
1048
  this.publishEvent(eventNames.logout_from_same_tab, {"message": sub});
1041
- await this.destroyAsync();
1049
+ await this.destroyAsync("LOGGED_OUT");
1042
1050
  }
1043
1051
  }
1044
1052
 
1045
- async logoutOtherTabAsync(sub){
1053
+ async logoutOtherTabAsync(clientId, sub){
1046
1054
  // @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);
1055
+ if(this.configuration.monitor_session && this.configuration.client_id === clientId && sub && this.tokens && this.tokens.idTokenPayload && this.tokens.idTokenPayload.sub === sub) {
1056
+ await this.destroyAsync("LOGGED_OUT");
1050
1057
  this.publishEvent(eventNames.logout_from_another_tab, {message : "SessionMonitor", "sub": sub});
1051
1058
  }
1052
1059
  }
@@ -1069,11 +1076,11 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
1069
1076
  const idToken = this.tokens ? this.tokens.idToken : "";
1070
1077
  // @ts-ignore
1071
1078
  const sub = this.tokens && this.tokens.idTokenPayload ? this.tokens.idTokenPayload.sub : null;
1072
- await this.destroyAsync();
1079
+ await this.destroyAsync("LOGGED_OUT");
1073
1080
  for (const [key, oidc] of Object.entries(oidcDatabase)) {
1074
1081
  if(oidc !== this) {
1075
1082
  // @ts-ignore
1076
- await oidc.logoutSameTabAsync(sub);
1083
+ await oidc.logoutSameTabAsync(this.configuration.client_id, sub);
1077
1084
  }
1078
1085
  }
1079
1086
 
@@ -1,4 +1,7 @@
1
1
  const idTokenPayload = (token) => {
2
+ if(!token){
3
+ return null;
4
+ }
2
5
  const base64Url = token.split('.')[1];
3
6
  const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
4
7
  const jsonPayload = decodeURIComponent(atob(base64).split('').map(function (c) {