@axa-fr/oidc-client 7.13.16 → 7.14.1

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.
package/src/jwt.ts CHANGED
@@ -4,6 +4,8 @@
4
4
  //
5
5
  // because... JavaScript, Strings, and Buffers
6
6
  // @ts-ignore
7
+ import {DemonstratingProofOfPossessionConfiguration} from "./types";
8
+
7
9
  function strToUint8(str) {
8
10
  return new TextEncoder().encode(str);
9
11
  }
@@ -56,19 +58,42 @@ function strToUrlBase64(str) {
56
58
  return binToUrlBase64(utf8ToBinaryString(str));
57
59
  }
58
60
 
59
- export var JWT = {};
61
+ export const defaultDemonstratingProofOfPossessionConfiguration: DemonstratingProofOfPossessionConfiguration ={
62
+ importKeyAlgorithm: {
63
+ name: 'ECDSA',
64
+ namedCurve: 'P-256',
65
+ hash: {name: 'ES256'}
66
+ },
67
+ signAlgorithm: {name: 'ECDSA', hash: {name: 'SHA-256'}},
68
+ generateKeyAlgorithm: {
69
+ name: 'ECDSA',
70
+ namedCurve: 'P-256'
71
+ },
72
+ digestAlgorithm: { name: 'SHA-256' },
73
+ jwtHeaderAlgorithm : 'ES256'
74
+ }
75
+
76
+
60
77
  // @ts-ignore
61
- JWT.sign = (jwk, headers, claims, jwtHeaderType= 'dpop+jwt') => {
78
+ const sign = async (jwk, headers, claims, demonstratingProofOfPossessionConfiguration: DemonstratingProofOfPossessionConfiguration, jwtHeaderType= 'dpop+jwt') => {
62
79
  // Make a shallow copy of the key
63
80
  // (to set ext if it wasn't already set)
64
81
  jwk = Object.assign({}, jwk);
65
82
 
66
83
  // The headers should probably be empty
67
84
  headers.typ = jwtHeaderType;
68
- headers.alg = 'ES256';
69
- if (!headers.kid) {
70
- // alternate: see thumbprint function below
71
- headers.jwk = { kty: jwk.kty, crv: jwk.crv, x: jwk.x, y: jwk.y };
85
+ headers.alg = demonstratingProofOfPossessionConfiguration.jwtHeaderAlgorithm;
86
+ switch (headers.alg) {
87
+ case 'ES256': //if (!headers.kid) {
88
+ // alternate: see thumbprint function below
89
+ headers.jwk = {kty: jwk.kty, crv: jwk.crv, x: jwk.x, y: jwk.y};
90
+ //}
91
+ break;
92
+ case 'RS256':
93
+ headers.jwk = {kty: jwk.kty, n: jwk.n, e: jwk.e, kid: headers.kid};
94
+ break;
95
+ default:
96
+ throw new Error('Unknown or not implemented JWS algorithm');
72
97
  }
73
98
 
74
99
  const jws = {
@@ -81,11 +106,7 @@ JWT.sign = (jwk, headers, claims, jwtHeaderType= 'dpop+jwt') => {
81
106
  };
82
107
 
83
108
  // To import as EC (ECDSA, P-256, SHA-256, ES256)
84
- const keyType = {
85
- name: 'ECDSA',
86
- namedCurve: 'P-256',
87
- hash: {name: 'ES256'}
88
- };
109
+ const keyType = demonstratingProofOfPossessionConfiguration.importKeyAlgorithm;
89
110
 
90
111
  // To make re-exportable as JSON (or DER/PEM)
91
112
  const exportable = true;
@@ -95,80 +116,110 @@ JWT.sign = (jwk, headers, claims, jwtHeaderType= 'dpop+jwt') => {
95
116
 
96
117
  // Actually do the import, which comes out as an abstract key type
97
118
  // @ts-ignore
98
- return window.crypto.subtle
99
- // @ts-ignore
100
- .importKey('jwk', jwk, keyType, exportable, privileges)
101
- .then(function(privateKey) {
102
- // Convert UTF-8 to Uint8Array ArrayBuffer
103
- // @ts-ignore
104
- const data = strToUint8(jws.protected + '.' + jws.payload);
105
-
106
- // The signature and hash should match the bit-entropy of the key
107
- // https://tools.ietf.org/html/rfc7518#section-3
108
- const signatureType = {name: 'ECDSA', hash: {name: 'SHA-256'}};
109
-
110
- return window.crypto.subtle.sign(signatureType, privateKey, data).then(function(signature) {
111
- // returns an ArrayBuffer containing a JOSE (not X509) signature,
112
- // which must be converted to Uint8 to be useful
113
- // @ts-ignore
114
- jws.signature = uint8ToUrlBase64(new Uint8Array(signature));
115
-
116
- // JWT is just a "compressed", "protected" JWS
117
- // @ts-ignore
118
- return jws.protected + '.' + jws.payload + '.' + jws.signature;
119
- });
120
- });
119
+ const privateKey = await window.crypto.subtle.importKey('jwk', jwk, keyType, exportable, privileges);
120
+ // Convert UTF-8 to Uint8Array ArrayBuffer
121
+ // @ts-ignore
122
+ const data = strToUint8(`${jws.protected}.${jws.payload}`);
123
+
124
+ // The signature and hash should match the bit-entropy of the key
125
+ // https://tools.ietf.org/html/rfc7518#section-3
126
+ const signatureType = demonstratingProofOfPossessionConfiguration.signAlgorithm;
127
+
128
+ const signature = await window.crypto.subtle.sign(signatureType, privateKey, data);
129
+ // returns an ArrayBuffer containing a JOSE (not X509) signature,
130
+ // which must be converted to Uint8 to be useful
131
+ // @ts-ignore
132
+ jws.signature = uint8ToUrlBase64(new Uint8Array(signature));
133
+ // JWT is just a "compressed", "protected" JWS
134
+ // @ts-ignore
135
+ return `${jws.protected}.${jws.payload}.${jws.signature}`;
121
136
  };
122
137
 
138
+ export var JWT = {sign};
139
+
123
140
 
124
- const EC = {};
125
141
  // @ts-ignore
126
- EC.generate = function() {
127
- const keyType = {
128
- name: 'ECDSA',
129
- namedCurve: 'P-256'
130
- };
142
+ const generate = async (generateKeyAlgorithm: RsaHashedKeyGenParams | EcKeyGenParams) => {
143
+ const keyType = generateKeyAlgorithm;
131
144
  const exportable = true;
132
145
  const privileges = ['sign', 'verify'];
133
146
  // @ts-ignore
134
- return window.crypto.subtle.generateKey(keyType, exportable, privileges).then(function(key) {
135
- // returns an abstract and opaque WebCrypto object,
136
- // which in most cases you'll want to export as JSON to be able to save
137
- return window.crypto.subtle.exportKey('jwk', key.privateKey);
138
- });
147
+ const key = await window.crypto.subtle.generateKey(keyType, exportable, privileges);
148
+ // returns an abstract and opaque WebCrypto object,
149
+ // which in most cases you'll want to export as JSON to be able to save
150
+ return await window.crypto.subtle.exportKey('jwk', key.privateKey);
139
151
  };
140
152
 
141
153
  // Create a Public Key from a Private Key
142
154
  //
143
155
  // chops off the private parts
144
156
  // @ts-ignore
145
- EC.neuter = function(jwk) {
157
+ const neuter = jwk => {
146
158
  const copy = Object.assign({}, jwk);
147
159
  delete copy.d;
148
160
  copy.key_ops = ['verify'];
149
161
  return copy;
150
162
  };
151
163
 
152
- export var JWK = {};
164
+ const EC = {
165
+ generate,
166
+ neuter
167
+ };
153
168
  // @ts-ignore
154
- JWK.thumbprint = function(jwk) {
169
+ const thumbprint = async (jwk, digestAlgorithm: AlgorithmIdentifier) => {
170
+ let sortedPub;
155
171
  // lexigraphically sorted, no spaces
156
- const sortedPub = '{"crv":"CRV","kty":"EC","x":"X","y":"Y"}'
157
- .replace('CRV', jwk.crv)
158
- .replace('X', jwk.x)
159
- .replace('Y', jwk.y);
160
-
172
+ switch (jwk.kty) {
173
+ case 'EC':
174
+ sortedPub = '{"crv":"CRV","kty":"EC","x":"X","y":"Y"}'
175
+ .replace('CRV', jwk.crv)
176
+ .replace('X', jwk.x)
177
+ .replace('Y', jwk.y);
178
+ break;
179
+ case 'RSA':
180
+ sortedPub = '{"e":"E","kty":"RSA","n":"N"}'
181
+ .replace('E', jwk.e)
182
+ .replace('N', jwk.n);
183
+ break;
184
+ default:
185
+ throw new Error('Unknown or not implemented JWK type');
186
+ }
161
187
  // The hash should match the size of the key,
162
188
  // but we're only dealing with P-256
163
- return window.crypto.subtle
164
- .digest({ name: 'SHA-256' }, strToUint8(sortedPub))
165
- .then(function(hash) {
166
- return uint8ToUrlBase64(new Uint8Array(hash));
167
- });
168
- };
189
+ const hash = await window.crypto.subtle.digest(digestAlgorithm, strToUint8(sortedPub));
190
+ return uint8ToUrlBase64(new Uint8Array(hash));
191
+ }
192
+
193
+ export var JWK = {thumbprint};
194
+
195
+ export const generateJwkAsync = async (generateKeyAlgorithm: RsaHashedKeyGenParams | EcKeyGenParams) => {
196
+ // @ts-ignore
197
+ const jwk = await EC.generate(generateKeyAlgorithm);
198
+ // console.info('Private Key:', JSON.stringify(jwk));
199
+ // @ts-ignore
200
+ // console.info('Public Key:', JSON.stringify(EC.neuter(jwk)));
201
+ return jwk;
202
+ }
169
203
 
204
+ export const generateJwtDemonstratingProofOfPossessionAsync = (demonstratingProofOfPossessionConfiguration: DemonstratingProofOfPossessionConfiguration) => async (jwk, method = 'POST', url: string, extrasClaims={}) => {
170
205
 
171
- const guid = function () {
206
+ const claims = {
207
+ // https://www.rfc-editor.org/rfc/rfc9449.html#name-concept
208
+ jti: btoa(guid()),
209
+ htm: method,
210
+ htu: url,
211
+ iat: Math.round(Date.now() / 1000),
212
+ ...extrasClaims,
213
+ };
214
+ // @ts-ignore
215
+ const kid = await JWK.thumbprint(jwk, demonstratingProofOfPossessionConfiguration.digestAlgorithm);
216
+ // @ts-ignore
217
+ const jwt = await JWT.sign(jwk, { kid: kid }, claims, demonstratingProofOfPossessionConfiguration)
218
+ // console.info('JWT:', jwt);
219
+ return jwt;
220
+ }
221
+
222
+ const guid = () => {
172
223
  // RFC4122: The version 4 UUID is meant for generating UUIDs from truly-random or
173
224
  // pseudo-random numbers.
174
225
  // The algorithm is as follows:
@@ -213,36 +264,3 @@ const guid = function () {
213
264
 
214
265
  return guidResponse;
215
266
  };
216
-
217
-
218
- export const generateJwkAsync = () => {
219
- // @ts-ignore
220
- return EC.generate().then(function(jwk) {
221
- // console.info('Private Key:', JSON.stringify(jwk));
222
- // @ts-ignore
223
- // console.info('Public Key:', JSON.stringify(EC.neuter(jwk)));
224
- return jwk;
225
- });
226
- }
227
-
228
- export const generateJwtDemonstratingProofOfPossessionAsync = (jwk, method = 'POST', url: string, extrasClaims={}) => {
229
-
230
- const claims = {
231
- // https://www.rfc-editor.org/rfc/rfc9449.html#name-concept
232
- jti: btoa(guid()),
233
- htm: method,
234
- htu: url,
235
- iat: Math.round(Date.now() / 1000),
236
- ...extrasClaims,
237
- };
238
- // @ts-ignore
239
- return JWK.thumbprint(jwk).then(function(kid) {
240
- // @ts-ignore
241
- return JWT.sign(jwk, { /*kid: kid*/ }, claims).then(function(jwt) {
242
- // console.info('JWT:', jwt);
243
- return jwt;
244
- });
245
- });
246
- }
247
-
248
- export default EC;
@@ -0,0 +1,78 @@
1
+ import {initWorkerAsync} from "./initWorker";
2
+ import {autoRenewTokens} from "./renewTokens";
3
+ import {initSession} from "./initSession";
4
+ import {setTokens} from "./parseTokens";
5
+ import {eventNames} from "./events";
6
+ import Oidc from "./oidc";
7
+
8
+ export const tryKeepSessionAsync = async (oidc: Oidc) =>{
9
+
10
+ let serviceWorker;
11
+ if (oidc.tokens != null) {
12
+ return false;
13
+ }
14
+ oidc.publishEvent(eventNames.tryKeepExistingSessionAsync_begin, {});
15
+ try {
16
+ const configuration = oidc.configuration;
17
+ const oidcServerConfiguration = await oidc.initAsync(configuration.authority, configuration.authority_configuration);
18
+ serviceWorker = await initWorkerAsync(configuration, oidc.configurationName);
19
+ if (serviceWorker) {
20
+ const { tokens } = await serviceWorker.initAsync(oidcServerConfiguration, 'tryKeepExistingSessionAsync', configuration);
21
+ if (tokens) {
22
+ serviceWorker.startKeepAliveServiceWorker();
23
+ // @ts-ignore
24
+ oidc.tokens = tokens;
25
+ const getLoginParams = serviceWorker.getLoginParams(oidc.configurationName);
26
+ // @ts-ignore
27
+ oidc.timeoutId = autoRenewTokens(oidc, oidc.tokens.refreshToken, oidc.tokens.expiresAt, getLoginParams.extras);
28
+ const sessionState = await serviceWorker.getSessionStateAsync();
29
+ // @ts-ignore
30
+ await oidc.startCheckSessionAsync(oidcServerConfiguration.check_session_iframe, configuration.client_id, sessionState);
31
+ oidc.publishEvent(eventNames.tryKeepExistingSessionAsync_end, {
32
+ success: true,
33
+ message: 'tokens inside ServiceWorker are valid',
34
+ });
35
+ return true;
36
+ }
37
+ oidc.publishEvent(eventNames.tryKeepExistingSessionAsync_end, {
38
+ success: false,
39
+ message: 'no exiting session found',
40
+ });
41
+ } else {
42
+ if (configuration.service_worker_relative_url) {
43
+ oidc.publishEvent(eventNames.service_worker_not_supported_by_browser, {
44
+ message: 'service worker is not supported by this browser',
45
+ });
46
+ }
47
+ const session = initSession(oidc.configurationName, configuration.storage ?? sessionStorage);
48
+ const { tokens } = await session.initAsync();
49
+ if (tokens) {
50
+ // @ts-ignore
51
+ oidc.tokens = setTokens(tokens, null, configuration.token_renew_mode);
52
+ const getLoginParams = session.getLoginParams();
53
+ // @ts-ignore
54
+ oidc.timeoutId = autoRenewTokens(oidc, tokens.refreshToken, oidc.tokens.expiresAt, getLoginParams.extras);
55
+ const sessionState = await session.getSessionStateAsync();
56
+ // @ts-ignore
57
+ await oidc.startCheckSessionAsync(oidcServerConfiguration.check_session_iframe, configuration.client_id, sessionState);
58
+ oidc.publishEvent(eventNames.tryKeepExistingSessionAsync_end, {
59
+ success: true,
60
+ message: 'tokens inside storage are valid',
61
+ });
62
+ return true;
63
+ }
64
+ }
65
+ oidc.publishEvent(eventNames.tryKeepExistingSessionAsync_end, {
66
+ success: false,
67
+ message: serviceWorker ? 'service worker sessions not retrieved' : 'session storage sessions not retrieved',
68
+ });
69
+ return false;
70
+ } catch (exception) {
71
+ console.error(exception);
72
+ if (serviceWorker) {
73
+ await serviceWorker.clearAsync();
74
+ }
75
+ oidc.publishEvent(eventNames.tryKeepExistingSessionAsync_error, 'tokens inside ServiceWorker are invalid');
76
+ return false;
77
+ }
78
+ }
package/src/login.ts CHANGED
@@ -11,6 +11,7 @@ import {getParseQueryStringFromLocation} from './route-utils.js';
11
11
  import {OidcConfiguration, StringMap} from './types.js';
12
12
  import {generateJwkAsync, generateJwtDemonstratingProofOfPossessionAsync} from "./jwt";
13
13
  import {ILOidcLocation} from "./location";
14
+ import Oidc from "./oidc";
14
15
 
15
16
  // eslint-disable-next-line @typescript-eslint/ban-types
16
17
  export const defaultLoginAsync = (configurationName:string, configuration:OidcConfiguration, publishEvent :(string, any)=>void, initAsync:Function, oidcLocation: ILOidcLocation) => (callbackPath:string = undefined, extras:StringMap = null, isSilentSignin = false, scope:string = undefined) => {
@@ -75,7 +76,7 @@ export const defaultLoginAsync = (configurationName:string, configuration:OidcCo
75
76
  return loginLocalAsync();
76
77
  };
77
78
 
78
- export const loginCallbackAsync = (oidc) => async (isSilentSignin = false) => {
79
+ export const loginCallbackAsync = (oidc:Oidc) => async (isSilentSignin = false) => {
79
80
  try {
80
81
  oidc.publishEvent(eventNames.loginCallbackAsync_begin, {});
81
82
  const configuration = oidc.configuration;
@@ -148,14 +149,14 @@ export const loginCallbackAsync = (oidc) => async (isSilentSignin = false) => {
148
149
  const url = oidcServerConfiguration.tokenEndpoint;
149
150
  const headersExtras = {};
150
151
  if(configuration.demonstrating_proof_of_possession) {
151
- const jwk = await generateJwkAsync();
152
+ const jwk = await generateJwkAsync(configuration.demonstrating_proof_of_possession_configuration.generateKeyAlgorithm);
152
153
  if (serviceWorker) {
153
154
  await serviceWorker.setDemonstratingProofOfPossessionJwkAsync(jwk);
154
155
  } else {
155
156
  const session = initSession(oidc.configurationName, configuration.storage);
156
157
  await session.setDemonstratingProofOfPossessionJwkAsync(jwk);
157
158
  }
158
- headersExtras['DPoP'] = await generateJwtDemonstratingProofOfPossessionAsync(jwk, 'POST', url);
159
+ headersExtras['DPoP'] = await generateJwtDemonstratingProofOfPossessionAsync(configuration.demonstrating_proof_of_possession_configuration)(jwk, 'POST', url);
159
160
  }
160
161
 
161
162
  const tokenResponse = await performFirstTokenRequestAsync(storage)(url,
package/src/logout.ts CHANGED
@@ -4,6 +4,7 @@ import { performRevocationRequestAsync, TOKEN_TYPE } from './requests.js';
4
4
  import timer from './timer.js';
5
5
  import { StringMap } from './types.js';
6
6
  import {ILOidcLocation} from "./location";
7
+ import Oidc from "./oidc";
7
8
 
8
9
  export const oidcLogoutTokens = {
9
10
  access_token: 'access_token',
package/src/oidc.ts CHANGED
@@ -5,8 +5,13 @@ import {initSession} from './initSession.js';
5
5
  import {defaultServiceWorkerUpdateRequireCallback, initWorkerAsync, sleepAsync} from './initWorker.js';
6
6
  import {defaultLoginAsync, loginCallbackAsync} from './login.js';
7
7
  import {destroyAsync, logoutAsync} from './logout.js';
8
- import {computeTimeLeft, isTokensOidcValid, setTokens, TokenRenewMode, Tokens,} from './parseTokens.js';
9
- import {autoRenewTokens, renewTokensAndStartTimerAsync} from './renewTokens.js';
8
+ import {isTokensOidcValid, TokenRenewMode, Tokens,} from './parseTokens.js';
9
+ import {
10
+ autoRenewTokens,
11
+ renewTokensAndStartTimerAsync,
12
+ synchroniseTokensStatus,
13
+ syncTokensInfoAsync
14
+ } from './renewTokens.js';
10
15
  import {fetchFromIssuer, performTokenRequestAsync} from './requests.js';
11
16
  import {getParseQueryStringFromLocation} from './route-utils.js';
12
17
  import defaultSilentLoginAsync, {_silentLoginAsync} from './silentLogin.js';
@@ -14,9 +19,13 @@ import timer from './timer.js';
14
19
  import {AuthorityConfiguration, Fetch, OidcConfiguration, StringMap} from './types.js';
15
20
  import {userInfoAsync} from './user.js';
16
21
  import {base64urlOfHashOfASCIIEncodingAsync} from "./crypto";
17
- import {generateJwtDemonstratingProofOfPossessionAsync} from "./jwt";
22
+ import {
23
+ defaultDemonstratingProofOfPossessionConfiguration,
24
+ generateJwtDemonstratingProofOfPossessionAsync
25
+ } from "./jwt";
18
26
  import {ILOidcLocation, OidcLocation} from "./location";
19
27
  import {activateServiceWorker} from "./initWorkerOption";
28
+ import {tryKeepSessionAsync} from "./keepSession";
20
29
 
21
30
 
22
31
 
@@ -83,11 +92,11 @@ export class Oidc {
83
92
  public userInfo: null;
84
93
  public tokens?: Tokens;
85
94
  public events: Array<any>;
86
- private timeoutId: NodeJS.Timeout;
95
+ public timeoutId: NodeJS.Timeout | number;
87
96
  public configurationName: string;
88
- private checkSessionIFrame: CheckSessionIFrame;
97
+ public checkSessionIFrame: CheckSessionIFrame;
89
98
  private getFetch: () => Fetch;
90
- private location: ILOidcLocation;
99
+ public location: ILOidcLocation;
91
100
  constructor(configuration:OidcConfiguration, configurationName = 'default', getFetch : () => Fetch, location: ILOidcLocation = new OidcLocation()) {
92
101
  let silent_login_uri = configuration.silent_login_uri;
93
102
  if (configuration.silent_redirect_uri && !configuration.silent_login_uri) {
@@ -112,6 +121,7 @@ export class Oidc {
112
121
  logout_tokens_to_invalidate: configuration.logout_tokens_to_invalidate ?? ['access_token', 'refresh_token'],
113
122
  service_worker_update_require_callback,
114
123
  service_worker_activate: configuration.service_worker_activate ?? activateServiceWorker,
124
+ demonstrating_proof_of_possession_configuration: configuration.demonstrating_proof_of_possession_configuration ?? defaultDemonstratingProofOfPossessionConfiguration,
115
125
  };
116
126
 
117
127
  this.getFetch = getFetch ?? getFetchDefault;
@@ -225,78 +235,8 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
225
235
  if (this.tryKeepExistingSessionPromise !== null) {
226
236
  return this.tryKeepExistingSessionPromise;
227
237
  }
228
- const funcAsync = async () => {
229
- let serviceWorker;
230
- if (this.tokens != null) {
231
- return false;
232
- }
233
- this.publishEvent(eventNames.tryKeepExistingSessionAsync_begin, {});
234
- try {
235
- const configuration = this.configuration;
236
- const oidcServerConfiguration = await this.initAsync(configuration.authority, configuration.authority_configuration);
237
- serviceWorker = await initWorkerAsync(configuration, this.configurationName);
238
- if (serviceWorker) {
239
- const { tokens } = await serviceWorker.initAsync(oidcServerConfiguration, 'tryKeepExistingSessionAsync', configuration);
240
- if (tokens) {
241
- serviceWorker.startKeepAliveServiceWorker();
242
- // @ts-ignore
243
- this.tokens = tokens;
244
- const getLoginParams = serviceWorker.getLoginParams(this.configurationName);
245
- // @ts-ignore
246
- this.timeoutId = autoRenewTokens(this, this.tokens.refreshToken, this.tokens.expiresAt, getLoginParams.extras);
247
- const sessionState = await serviceWorker.getSessionStateAsync();
248
- // @ts-ignore
249
- await this.startCheckSessionAsync(oidcServerConfiguration.check_session_iframe, configuration.client_id, sessionState);
250
- this.publishEvent(eventNames.tryKeepExistingSessionAsync_end, {
251
- success: true,
252
- message: 'tokens inside ServiceWorker are valid',
253
- });
254
- return true;
255
- }
256
- this.publishEvent(eventNames.tryKeepExistingSessionAsync_end, {
257
- success: false,
258
- message: 'no exiting session found',
259
- });
260
- } else {
261
- if (configuration.service_worker_relative_url) {
262
- this.publishEvent(eventNames.service_worker_not_supported_by_browser, {
263
- message: 'service worker is not supported by this browser',
264
- });
265
- }
266
- const session = initSession(this.configurationName, configuration.storage ?? sessionStorage);
267
- const { tokens } = await session.initAsync();
268
- if (tokens) {
269
- // @ts-ignore
270
- this.tokens = setTokens(tokens, null, configuration.token_renew_mode);
271
- const getLoginParams = session.getLoginParams();
272
- // @ts-ignore
273
- this.timeoutId = autoRenewTokens(this, tokens.refreshToken, this.tokens.expiresAt, getLoginParams.extras);
274
- const sessionState = await session.getSessionStateAsync();
275
- // @ts-ignore
276
- await this.startCheckSessionAsync(oidcServerConfiguration.check_session_iframe, configuration.client_id, sessionState);
277
- this.publishEvent(eventNames.tryKeepExistingSessionAsync_end, {
278
- success: true,
279
- message: 'tokens inside storage are valid',
280
- });
281
- return true;
282
- }
283
- }
284
- this.publishEvent(eventNames.tryKeepExistingSessionAsync_end, {
285
- success: false,
286
- message: serviceWorker ? 'service worker sessions not retrieved' : 'session storage sessions not retrieved',
287
- });
288
- return false;
289
- } catch (exception) {
290
- console.error(exception);
291
- if (serviceWorker) {
292
- await serviceWorker.clearAsync();
293
- }
294
- this.publishEvent(eventNames.tryKeepExistingSessionAsync_error, 'tokens inside ServiceWorker are invalid');
295
- return false;
296
- }
297
- };
298
-
299
- this.tryKeepExistingSessionPromise = funcAsync();
238
+
239
+ this.tryKeepExistingSessionPromise = tryKeepSessionAsync(this);
300
240
  return this.tryKeepExistingSessionPromise.then((result) => {
301
241
  this.tryKeepExistingSessionPromise = null;
302
242
  return result;
@@ -349,8 +289,11 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
349
289
  return result;
350
290
  });
351
291
  }
292
+
293
+
352
294
 
353
295
  async synchroniseTokensAsync(refreshToken, index = 0, forceRefresh = false, extras:StringMap = null, updateTokens) {
296
+
354
297
  while (!navigator.onLine && document.hidden) {
355
298
  await sleepAsync({milliseconds: 1000});
356
299
  this.publishEvent(eventNames.refreshTokensAsync, { message: 'wait because navigator is offline and hidden' });
@@ -410,27 +353,27 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
410
353
  return { tokens: null, status: 'SESSION_LOST' };
411
354
  }
412
355
  try {
413
- const { status, tokens, nonce } = await this.syncTokensInfoAsync(configuration, this.configurationName, this.tokens, forceRefresh);
356
+ const { status, tokens, nonce } = await syncTokensInfoAsync(this)(configuration, this.configurationName, this.tokens, forceRefresh);
414
357
  switch (status) {
415
- case 'SESSION_LOST':
358
+ case synchroniseTokensStatus.SESSION_LOST:
416
359
  updateTokens(null);
417
360
  this.publishEvent(eventNames.refreshTokensAsync_error, { message: 'refresh token session lost' });
418
361
  return { tokens: null, status: 'SESSION_LOST' };
419
- case 'NOT_CONNECTED':
362
+ case synchroniseTokensStatus.NOT_CONNECTED:
420
363
  updateTokens(null);
421
364
  return { tokens: null, status: null };
422
- case 'TOKENS_VALID':
365
+ case synchroniseTokensStatus.TOKENS_VALID:
423
366
  updateTokens(tokens);
424
367
  return { tokens, status: 'LOGGED_IN' };
425
- case 'TOKEN_UPDATED_BY_ANOTHER_TAB_TOKENS_VALID':
368
+ case synchroniseTokensStatus.TOKEN_UPDATED_BY_ANOTHER_TAB_TOKENS_VALID:
426
369
  updateTokens(tokens);
427
370
  this.publishEvent(Oidc.eventNames.token_renewed, { reason: 'TOKEN_UPDATED_BY_ANOTHER_TAB_TOKENS_VALID' });
428
371
  return { tokens, status: 'LOGGED_IN' };
429
- case 'LOGOUT_FROM_ANOTHER_TAB':
372
+ case synchroniseTokensStatus.LOGOUT_FROM_ANOTHER_TAB:
430
373
  updateTokens(null);
431
374
  this.publishEvent(eventNames.logout_from_another_tab, { status: 'session syncTokensAsync' });
432
375
  return { tokens: null, status: 'LOGGED_OUT' };
433
- case 'REQUIRE_SYNC_TOKENS':
376
+ case synchroniseTokensStatus.REQUIRE_SYNC_TOKENS:
434
377
  this.publishEvent(eventNames.refreshTokensAsync_begin, { refreshToken, status, tryNumber: index });
435
378
  return await localsilentLoginAsync();
436
379
  default: {
@@ -516,7 +459,7 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
516
459
  const claimsExtras = {ath: await base64urlOfHashOfASCIIEncodingAsync(accessToken),};
517
460
 
518
461
  const serviceWorker = await initWorkerAsync(configuration, this.configurationName);
519
- let demonstratingProofOfPossessionNonce:string = null;
462
+ let demonstratingProofOfPossessionNonce:string;
520
463
  let jwk;
521
464
  if (serviceWorker) {
522
465
  demonstratingProofOfPossessionNonce = await serviceWorker.getDemonstratingProofOfPossessionNonce();
@@ -531,56 +474,7 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
531
474
  claimsExtras['nonce'] = demonstratingProofOfPossessionNonce;
532
475
  }
533
476
 
534
- return await generateJwtDemonstratingProofOfPossessionAsync(jwk, method, url, claimsExtras);
535
- }
536
-
537
- async syncTokensInfoAsync(configuration, configurationName, currentTokens, forceRefresh = false) {
538
- // 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)
539
- // const configuration = this.configuration;
540
- const nullNonce = { nonce: null };
541
- if (!currentTokens) {
542
- return { tokens: null, status: 'NOT_CONNECTED', nonce: nullNonce };
543
- }
544
- let nonce = nullNonce;
545
- const oidcServerConfiguration = await this.initAsync(configuration.authority, configuration.authority_configuration);
546
- const serviceWorker = await initWorkerAsync(configuration, configurationName);
547
- if (serviceWorker) {
548
- const { status, tokens } = await serviceWorker.initAsync(oidcServerConfiguration, 'syncTokensAsync', configuration);
549
- if (status === 'LOGGED_OUT') {
550
- return { tokens: null, status: 'LOGOUT_FROM_ANOTHER_TAB', nonce: nullNonce };
551
- } else if (status === 'SESSIONS_LOST') {
552
- return { tokens: null, status: 'SESSIONS_LOST', nonce: nullNonce };
553
- } else if (!status || !tokens) {
554
- return { tokens: null, status: 'REQUIRE_SYNC_TOKENS', nonce: nullNonce };
555
- } else if (tokens.issuedAt !== currentTokens.issuedAt) {
556
- const timeLeft = computeTimeLeft(configuration.refresh_time_before_tokens_expiration_in_second, tokens.expiresAt);
557
- const status = (timeLeft > 0) ? 'TOKEN_UPDATED_BY_ANOTHER_TAB_TOKENS_VALID' : 'TOKEN_UPDATED_BY_ANOTHER_TAB_TOKENS_INVALID';
558
- const nonce = await serviceWorker.getNonceAsync();
559
- return { tokens, status, nonce };
560
- }
561
- nonce = await serviceWorker.getNonceAsync();
562
- } else {
563
- const session = initSession(configurationName, configuration.storage ?? sessionStorage);
564
- const { tokens, status } = await session.initAsync();
565
- if (!tokens) {
566
- return { tokens: null, status: 'LOGOUT_FROM_ANOTHER_TAB', nonce: nullNonce };
567
- } else if (status === 'SESSIONS_LOST') {
568
- return { tokens: null, status: 'SESSIONS_LOST', nonce: nullNonce };
569
- } else if (tokens.issuedAt !== currentTokens.issuedAt) {
570
- const timeLeft = computeTimeLeft(configuration.refresh_time_before_tokens_expiration_in_second, tokens.expiresAt);
571
- const status = (timeLeft > 0) ? 'TOKEN_UPDATED_BY_ANOTHER_TAB_TOKENS_VALID' : 'TOKEN_UPDATED_BY_ANOTHER_TAB_TOKENS_INVALID';
572
- const nonce = await session.getNonceAsync();
573
- return { tokens, status, nonce };
574
- }
575
- nonce = await session.getNonceAsync();
576
- }
577
-
578
- const timeLeft = computeTimeLeft(configuration.refresh_time_before_tokens_expiration_in_second, currentTokens.expiresAt);
579
- const status = (timeLeft > 0) ? 'TOKENS_VALID' : 'TOKENS_INVALID';
580
- if (forceRefresh) {
581
- return { tokens: currentTokens, status: 'FORCE_REFRESH', nonce };
582
- }
583
- return { tokens: currentTokens, status, nonce };
477
+ return await generateJwtDemonstratingProofOfPossessionAsync(configuration.demonstrating_proof_of_possession_configuration)(jwk, method, url, claimsExtras);
584
478
  }
585
479
 
586
480
  loginCallbackWithAutoTokensRenewPromise:Promise<LoginCallback> = null;
@@ -20,7 +20,7 @@ const extractTokenPayload = (token:string) => {
20
20
  return null;
21
21
  };
22
22
 
23
- const countLetter = (str, find) => {
23
+ const countLetter = (str : string, find) => {
24
24
  return (str.split(find)).length - 1;
25
25
  };
26
26