@axa-fr/react-oidc 5.7.8 → 5.8.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.
Files changed (38) hide show
  1. package/dist/OidcSecure.d.ts +2 -1
  2. package/dist/OidcSecure.d.ts.map +1 -1
  3. package/dist/OidcSecure.js +5 -4
  4. package/dist/OidcSecure.js.map +1 -1
  5. package/dist/ReactOidc.d.ts +1 -1
  6. package/dist/ReactOidc.d.ts.map +1 -1
  7. package/dist/ReactOidc.js +3 -2
  8. package/dist/ReactOidc.js.map +1 -1
  9. package/dist/core/default-component/Callback.component.d.ts.map +1 -1
  10. package/dist/core/default-component/Callback.component.js +7 -9
  11. package/dist/core/default-component/Callback.component.js.map +1 -1
  12. package/dist/core/default-component/ServiceWorkerInstall.component.d.ts.map +1 -1
  13. package/dist/core/default-component/ServiceWorkerInstall.component.js +4 -7
  14. package/dist/core/default-component/ServiceWorkerInstall.component.js.map +1 -1
  15. package/dist/core/default-component/SilentCallback.component.d.ts.map +1 -1
  16. package/dist/core/default-component/SilentCallback.component.js +3 -5
  17. package/dist/core/default-component/SilentCallback.component.js.map +1 -1
  18. package/dist/core/routes/OidcRoutes.d.ts.map +1 -1
  19. package/dist/core/routes/OidcRoutes.js +4 -2
  20. package/dist/core/routes/OidcRoutes.js.map +1 -1
  21. package/dist/vanilla/initSession.js +9 -9
  22. package/dist/vanilla/initSession.js.map +1 -1
  23. package/dist/vanilla/oidc.d.ts +10 -3
  24. package/dist/vanilla/oidc.d.ts.map +1 -1
  25. package/dist/vanilla/oidc.js +146 -99
  26. package/dist/vanilla/oidc.js.map +1 -1
  27. package/package.json +2 -2
  28. package/src/App.tsx +14 -10
  29. package/src/Home.tsx +3 -2
  30. package/src/index.tsx +1 -1
  31. package/src/oidc/OidcSecure.tsx +9 -5
  32. package/src/oidc/ReactOidc.tsx +2 -2
  33. package/src/oidc/core/default-component/Callback.component.tsx +10 -13
  34. package/src/oidc/core/default-component/ServiceWorkerInstall.component.tsx +4 -7
  35. package/src/oidc/core/default-component/SilentCallback.component.tsx +3 -2
  36. package/src/oidc/core/routes/OidcRoutes.tsx +4 -2
  37. package/src/oidc/vanilla/initSession.ts +9 -9
  38. package/src/oidc/vanilla/oidc.ts +111 -63
@@ -1,6 +1,6 @@
1
1
  import React, {useEffect, useState, ComponentType} from 'react';
2
2
  import AuthenticatingError from "./AuthenticateError.component";
3
- import Oidc from "../../vanilla/oidc";
3
+ import Oidc, {getLoginParams} from "../../vanilla/oidc";
4
4
  import Authenticating from "./Authenticating.component";
5
5
 
6
6
  const ServiceWorkerInstall: ComponentType<any> = ({callBackError, authenticating, configurationName }) => {
@@ -15,12 +15,9 @@ const ServiceWorkerInstall: ComponentType<any> = ({callBackError, authenticating
15
15
  let isMounted = true;
16
16
  const playCallbackAsync = async () => {
17
17
  try {
18
- const params = new Proxy(new URLSearchParams(window.location.search), {
19
- // @ts-ignore
20
- get: (searchParams, prop) => searchParams.get(prop),
21
- });
18
+ const loginParams = getLoginParams(configurationName)
22
19
  // @ts-ignore
23
- await getOidc(configurationName).loginAsync(decodeURIComponent(params.callbackPath), false);
20
+ await getOidc(configurationName).loginAsync(loginParams.callbackPath, loginParams.extras,false, loginParams.state);
24
21
  if(isMounted) {
25
22
  setLoading(false);
26
23
  }
@@ -32,7 +29,7 @@ const ServiceWorkerInstall: ComponentType<any> = ({callBackError, authenticating
32
29
  }
33
30
  };
34
31
  playCallbackAsync();
35
- return () => {
32
+ return () => {
36
33
  isMounted = false;
37
34
  };
38
35
  },[]);
@@ -1,5 +1,5 @@
1
1
  import React, {useEffect, ComponentType} from 'react';
2
- import Oidc from "../../vanilla/oidc";
2
+ import Oidc, {getLoginParams} from "../../vanilla/oidc";
3
3
  import {OidcSecure} from "../../OidcSecure";
4
4
 
5
5
  const CallBack = ({configurationName}) =>{
@@ -23,7 +23,8 @@ const CallBack = ({configurationName}) =>{
23
23
  }
24
24
 
25
25
  const CallbackManager: ComponentType<any> = ({configurationName }) => {
26
- return <OidcSecure configurationName={configurationName}>
26
+ const loginParams = getLoginParams(configurationName);
27
+ return <OidcSecure configurationName={configurationName} state={loginParams.state} extras={loginParams.extras}>
27
28
  <CallBack configurationName={configurationName}/>
28
29
  </OidcSecure>;
29
30
  };
@@ -38,11 +38,13 @@ const OidcRoutes: FC<PropsWithChildren<OidcRoutesProps>> = ({
38
38
  const [path, setPath] = useState(pathname);
39
39
 
40
40
  useEffect(() => {
41
- const setNewPath = () => setPath(window.location.pathname);
41
+ const setNewPath = () => {
42
+ setPath(window.location.pathname);
43
+ };
42
44
  setNewPath();
43
45
  window.addEventListener('popstate', setNewPath, false);
44
46
  return () => window.removeEventListener('popstate', setNewPath, false);
45
- });
47
+ }, []);
46
48
 
47
49
  const callbackPath = getPath(redirect_uri);
48
50
 
@@ -1,35 +1,35 @@
1
1
  export const initSession = (configurationName) => {
2
2
 
3
3
  const saveItemsAsync =(items) =>{
4
- sessionStorage.items = JSON.stringify(items);
4
+ sessionStorage[`oidc_items.${configurationName}`] = JSON.stringify(items);
5
5
  return Promise.resolve();
6
6
  }
7
7
 
8
8
  const loadItemsAsync=() =>{
9
- return Promise.resolve(JSON.parse(sessionStorage.items));
9
+ return Promise.resolve(JSON.parse(sessionStorage[`oidc_items.${configurationName}`]));
10
10
  }
11
11
 
12
12
  const clearAsync=() =>{
13
- sessionStorage[configurationName] = JSON.stringify({tokens:null});
13
+ sessionStorage[`oidc.${configurationName}`] = JSON.stringify({tokens:null});
14
14
  return Promise.resolve();
15
15
  }
16
16
 
17
17
  const initAsync=async () => {
18
- if(!sessionStorage[configurationName]){
19
- sessionStorage[configurationName] = JSON.stringify({tokens:null});
18
+ if(!sessionStorage[`oidc.${configurationName}`]){
19
+ sessionStorage[`oidc.${configurationName}`] = JSON.stringify({tokens:null});
20
20
  }
21
- return Promise.resolve({ tokens : JSON.parse(sessionStorage[configurationName]).tokens });
21
+ return Promise.resolve({ tokens : JSON.parse(sessionStorage[`oidc.${configurationName}`]).tokens });
22
22
  }
23
23
 
24
24
  const setTokens = (tokens) => {
25
- sessionStorage[configurationName] = JSON.stringify({tokens});
25
+ sessionStorage[`oidc.${configurationName}`] = JSON.stringify({tokens});
26
26
  }
27
27
 
28
28
  const getTokens = () => {
29
- if(!sessionStorage[configurationName]){
29
+ if(!sessionStorage[`oidc.${configurationName}`]){
30
30
  return null;
31
31
  }
32
- return JSON.stringify({ tokens : JSON.parse(sessionStorage[configurationName]).tokens });
32
+ return JSON.stringify({ tokens : JSON.parse(sessionStorage[`oidc.${configurationName}`]).tokens });
33
33
  }
34
34
 
35
35
  return { saveItemsAsync, loadItemsAsync, clearAsync, initAsync, setTokens, getTokens };
@@ -59,6 +59,11 @@ export interface StringMap {
59
59
  [key: string]: string;
60
60
  }
61
61
 
62
+ export interface loginCallbackResult {
63
+ state: string,
64
+ callbackPath: string,
65
+ }
66
+
62
67
  export interface AuthorityConfiguration {
63
68
  authorization_endpoint: string;
64
69
  token_endpoint: string;
@@ -101,7 +106,7 @@ const loginCallbackWithAutoTokensRenewAsync = async (oidc) => {
101
106
  }
102
107
  oidc.publishEvent(Oidc.eventNames.token_aquired, oidc.tokens);
103
108
  oidc.timeoutId = await autoRenewTokensAsync(oidc, tokens.refreshToken, oidc.tokens.expiresAt)
104
- return response.state;
109
+ return { state:response.state, callbackPath : response.callbackPath };
105
110
  }
106
111
 
107
112
  const autoRenewTokensAsync = async (oidc, refreshToken, expiresAt) => {
@@ -127,6 +132,10 @@ const autoRenewTokensAsync = async (oidc, refreshToken, expiresAt) => {
127
132
  }, 1000);
128
133
  }
129
134
 
135
+ export const getLoginParams = (configurationName) => {
136
+ return JSON.parse(sessionStorage[`oidc_login.${configurationName}`]);
137
+ }
138
+
130
139
  const userInfoAsync = async (oidc) => {
131
140
  if(oidc.userInfo != null){
132
141
  return oidc.userInfo;
@@ -237,8 +246,8 @@ export class Oidc {
237
246
  }
238
247
 
239
248
  removeEventSubscription(id){
240
- const newEvents = this.events.filter(e => e.id === id);
241
- this.events = newEvents;
249
+ const newEvents = this.events.filter(e => e.id !== id);
250
+ this.events = newEvents;
242
251
  }
243
252
 
244
253
  publishEvent(eventName, data){
@@ -321,79 +330,105 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
321
330
  }
322
331
  return await AuthorizationServiceConfiguration.fetchFromIssuer(authority, new FetchRequestor());
323
332
  }
324
-
333
+
334
+ tryKeepExistingSessionPromise = null;
325
335
  async tryKeepExistingSessionAsync() {
326
- let serviceWorker
327
- if(this.tokens != null){
328
- return false;
336
+ if(this.tryKeepExistingSessionPromise !== null){
337
+ return this.tryKeepExistingSessionPromise;
329
338
  }
330
- this.publishEvent(eventNames.tryKeepExistingSessionAsync_begin, {});
331
- try {
332
- const configuration = this.configuration;
333
- const oidcServerConfiguration = await this.initAsync(configuration.authority, configuration.authority_configuration);
334
- serviceWorker = await initWorkerAsync(configuration.service_worker_relative_url, this.configurationName);
335
- if(serviceWorker) {
336
- const { tokens } = await serviceWorker.initAsync(oidcServerConfiguration, "tryKeepExistingSessionAsync");
337
- if (tokens) {
338
- serviceWorker.startKeepAliveServiceWorker();
339
- const updatedTokens = await this.refreshTokensAsync(tokens.refresh_token, true);
340
- // @ts-ignore
341
- this.tokens = await setTokensAsync(serviceWorker, updatedTokens);
342
- this.serviceWorker = serviceWorker;
343
- // @ts-ignore
344
- this.timeoutId = await autoRenewTokensAsync(this, updatedTokens.refreshToken, this.tokens.expiresAt);
345
- this.publishEvent(eventNames.tryKeepExistingSessionAsync_end, {success: true, message : "tokens inside ServiceWorker are valid"});
346
- return true;
347
- }
348
- this.publishEvent(eventNames.tryKeepExistingSessionAsync_end, {success: false, message : "no exiting session found"});
349
- } else {
350
- if(configuration.service_worker_relative_url) {
351
- this.publishEvent(eventNames.service_worker_not_supported_by_browser, {
352
- message: "service worker is not supported by this browser"
339
+
340
+ const funcAsync =async () => {
341
+ let serviceWorker
342
+ if (this.tokens != null) {
343
+ return false;
344
+ }
345
+ this.publishEvent(eventNames.tryKeepExistingSessionAsync_begin, {});
346
+ try {
347
+ const configuration = this.configuration;
348
+ const oidcServerConfiguration = await this.initAsync(configuration.authority, configuration.authority_configuration);
349
+ serviceWorker = await initWorkerAsync(configuration.service_worker_relative_url, this.configurationName);
350
+ if (serviceWorker) {
351
+ const {tokens} = await serviceWorker.initAsync(oidcServerConfiguration, "tryKeepExistingSessionAsync");
352
+ if (tokens) {
353
+ serviceWorker.startKeepAliveServiceWorker();
354
+ const updatedTokens = await this.refreshTokensAsync(tokens.refresh_token, true);
355
+ // @ts-ignore
356
+ this.tokens = await setTokensAsync(serviceWorker, updatedTokens);
357
+ this.serviceWorker = serviceWorker;
358
+ // @ts-ignore
359
+ this.timeoutId = await autoRenewTokensAsync(this, updatedTokens.refreshToken, this.tokens.expiresAt);
360
+ this.publishEvent(eventNames.tryKeepExistingSessionAsync_end, {
361
+ success: true,
362
+ message: "tokens inside ServiceWorker are valid"
363
+ });
364
+ return true;
365
+ }
366
+ this.publishEvent(eventNames.tryKeepExistingSessionAsync_end, {
367
+ success: false,
368
+ message: "no exiting session found"
353
369
  });
370
+ } else {
371
+ if (configuration.service_worker_relative_url) {
372
+ this.publishEvent(eventNames.service_worker_not_supported_by_browser, {
373
+ message: "service worker is not supported by this browser"
374
+ });
375
+ }
376
+ const session = initSession(this.configurationName);
377
+ const {tokens} = await session.initAsync();
378
+ if (tokens) {
379
+ const updatedTokens = await this.refreshTokensAsync(tokens.refreshToken, true);
380
+ // @ts-ignore
381
+ this.tokens = await setTokensAsync(serviceWorker, updatedTokens);
382
+ session.setTokens(this.tokens);
383
+ this.session = session;
384
+ // @ts-ignore
385
+ this.timeoutId = await autoRenewTokensAsync(this, updatedTokens.refreshToken, this.tokens.expiresAt);
386
+ this.publishEvent(eventNames.tryKeepExistingSessionAsync_end, {
387
+ success: true,
388
+ message: "tokens inside ServiceWorker are valid"
389
+ });
390
+ return true;
391
+ }
354
392
  }
355
- const session = initSession(this.configurationName);
356
- const {tokens} = await session.initAsync();
357
- if (tokens) {
358
- const updatedTokens = await this.refreshTokensAsync(tokens.refreshToken, true);
359
- // @ts-ignore
360
- this.tokens = await setTokensAsync(serviceWorker, updatedTokens);
361
- session.setTokens(this.tokens);
362
- this.session = session;
363
- // @ts-ignore
364
- this.timeoutId = await autoRenewTokensAsync(this, updatedTokens.refreshToken, this.tokens.expiresAt);
365
- this.publishEvent(eventNames.tryKeepExistingSessionAsync_end, {success: true, message : "tokens inside ServiceWorker are valid"});
366
- return true;
393
+ this.publishEvent(eventNames.tryKeepExistingSessionAsync_end, {
394
+ success: false,
395
+ message: "no service worker"
396
+ });
397
+ return false;
398
+ } catch (exception) {
399
+ if (serviceWorker) {
400
+ await serviceWorker.clearAsync();
367
401
  }
402
+ this.publishEvent(eventNames.tryKeepExistingSessionAsync_error, "tokens inside ServiceWorker are invalid");
403
+ return false;
368
404
  }
369
- this.publishEvent(eventNames.tryKeepExistingSessionAsync_end, {success: false, message : "no service worker"});
370
- return false;
371
- } catch (exception) {
372
- if(serviceWorker){
373
- await serviceWorker.clearAsync();
374
- }
375
- this.publishEvent(eventNames.tryKeepExistingSessionAsync_error, "tokens inside ServiceWorker are invalid");
376
- return false;
377
405
  }
406
+
407
+ this.tryKeepExistingSessionPromise = funcAsync();
408
+ return this.tryKeepExistingSessionPromise.then((result) => {
409
+ this.tryKeepExistingSessionPromise =null;
410
+ return result;
411
+ });
378
412
  }
379
413
 
380
- async loginAsync(callbackPath:string=undefined, extras:StringMap=null, installServiceWorker=true) {
414
+ async loginAsync(callbackPath:string=undefined, extras:StringMap=null, installServiceWorker=true, state:string=undefined) {
381
415
  try {
382
416
  const location = window.location;
383
417
  const url = callbackPath || location.pathname + (location.search || '') + (location.hash || '');
384
- const state = url;
385
418
  this.publishEvent(eventNames.loginAsync_begin, {});
386
419
  const configuration = this.configuration
387
420
  // Security we cannot loggin from Iframe
388
421
  if (!configuration.silent_redirect_uri && isInIframe()) {
389
422
  throw new Error("Login from iframe is forbidden");
390
423
  }
424
+ sessionStorage[`oidc_login.${this.configurationName}`] = JSON.stringify({callbackPath:url,extras,state});
425
+
391
426
  let serviceWorker = await initWorkerAsync(configuration.service_worker_relative_url, this.configurationName);
392
427
  const oidcServerConfiguration = await this.initAsync(configuration.authority, configuration.authority_configuration);
393
428
  if(serviceWorker && installServiceWorker) {
394
- const isServiceWorkerProxyActive = await serviceWorker.isServiceWorkerProxyActiveAsync()
429
+ const isServiceWorkerProxyActive = await serviceWorker.isServiceWorkerProxyActiveAsync();
395
430
  if(!isServiceWorkerProxyActive) {
396
- window.location.href = configuration.redirect_uri + "/service-worker-install?callbackPath=" + encodeURIComponent(url);
431
+ window.location.href = `${configuration.redirect_uri}/service-worker-install`;
397
432
  return;
398
433
  }
399
434
  }
@@ -418,13 +453,13 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
418
453
  extras: extras ?? configuration.extras
419
454
  });
420
455
  authorizationHandler.performAuthorizationRequest(oidcServerConfiguration, authRequest);
421
- } catch(exception){
422
- this.publishEvent(eventNames.loginAsync_error, exception);
423
- throw exception;
456
+ } catch(exception) {
457
+ this.publishEvent(eventNames.loginAsync_error, exception);
458
+ throw exception;
424
459
  }
425
460
  }
426
461
 
427
- async loginCallbackAsync() {
462
+ async loginCallbackAsync(){
428
463
  try {
429
464
  this.publishEvent(eventNames.loginCallbackAsync_begin, {});
430
465
  const configuration = this.configuration;
@@ -446,7 +481,6 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
446
481
  const items = await session.loadItemsAsync();
447
482
  storage = new MemoryStorageBackend(session.saveItemsAsync, items);
448
483
  }
449
-
450
484
  const promise = new Promise((resolve, reject) => {
451
485
  const tokenHandler = new BaseTokenRequestHandler(new FetchRequestor());
452
486
  // @ts-ignore
@@ -459,6 +493,7 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
459
493
  reject(error);
460
494
  }
461
495
  if (!response) {
496
+ reject("no response");
462
497
  return;
463
498
  }
464
499
 
@@ -484,7 +519,12 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
484
519
 
485
520
  try {
486
521
  const tokenResponse = await tokenHandler.performTokenRequest(oidcServerConfiguration, tokenRequest);
487
- resolve({tokens:tokenResponse, state: request.state});
522
+ const loginParams = getLoginParams(this.configurationName);
523
+ resolve({
524
+ tokens:tokenResponse,
525
+ state: request.state,
526
+ callbackPath : loginParams.callbackPath,
527
+ });
488
528
  this.publishEvent(eventNames.loginCallbackAsync_end, {})
489
529
  } catch(exception){
490
530
  this.publishEvent(eventNames.loginCallbackAsync_error, exception);
@@ -558,9 +598,17 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
558
598
  return await localSilentSigninAsync(exception);
559
599
  }
560
600
  }
561
-
562
- loginCallbackWithAutoTokensRenewAsync():Promise<string>{
563
- return loginCallbackWithAutoTokensRenewAsync(this);
601
+
602
+ loginCallbackWithAutoTokensRenewPromise:Promise<loginCallbackResult> = null;
603
+ loginCallbackWithAutoTokensRenewAsync():Promise<loginCallbackResult>{
604
+ if(this.loginCallbackWithAutoTokensRenewPromise !== null){
605
+ return this.loginCallbackWithAutoTokensRenewPromise;
606
+ }
607
+ this.loginCallbackWithAutoTokensRenewPromise = loginCallbackWithAutoTokensRenewAsync(this);
608
+ return this.loginCallbackWithAutoTokensRenewPromise.then(result =>{
609
+ this.loginCallbackWithAutoTokensRenewPromise = null;
610
+ return result;
611
+ })
564
612
  }
565
613
 
566
614
  userInfoAsync(){