@asgardeo/auth-spa 0.2.18 → 0.2.21

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 (115) hide show
  1. package/.eslintrc.js +1 -2
  2. package/README.md +12 -5
  3. package/babel.config.js +1 -2
  4. package/dist/asgardeo-spa.production.esm.js +100 -42
  5. package/dist/asgardeo-spa.production.esm.js.map +1 -1
  6. package/dist/asgardeo-spa.production.js +101 -43
  7. package/dist/asgardeo-spa.production.js.map +1 -1
  8. package/dist/asgardeo-spa.production.min.js +1 -1
  9. package/dist/asgardeo-spa.production.min.js.map +1 -1
  10. package/dist/polyfilled/asgardeo-spa.production.esm.js +98 -40
  11. package/dist/polyfilled/asgardeo-spa.production.esm.js.map +1 -1
  12. package/dist/polyfilled/asgardeo-spa.production.js +98 -40
  13. package/dist/polyfilled/asgardeo-spa.production.js.map +1 -1
  14. package/dist/polyfilled/asgardeo-spa.production.min.js +1 -1
  15. package/dist/polyfilled/asgardeo-spa.production.min.js.map +1 -1
  16. package/dist/src/client.d.ts +4 -3
  17. package/dist/src/client.d.ts.map +1 -1
  18. package/dist/src/client.js +13 -4
  19. package/dist/src/client.js.map +1 -1
  20. package/dist/src/clients/main-thread-client.d.ts.map +1 -1
  21. package/dist/src/clients/main-thread-client.js +41 -25
  22. package/dist/src/clients/main-thread-client.js.map +1 -1
  23. package/dist/src/clients/web-worker-client.d.ts +1 -1
  24. package/dist/src/clients/web-worker-client.d.ts.map +1 -1
  25. package/dist/src/clients/web-worker-client.js +55 -30
  26. package/dist/src/clients/web-worker-client.js.map +1 -1
  27. package/dist/src/constants/errors.d.ts +19 -0
  28. package/dist/src/constants/errors.d.ts.map +1 -0
  29. package/dist/src/constants/errors.js +19 -0
  30. package/dist/src/constants/errors.js.map +1 -0
  31. package/dist/src/constants/hooks.d.ts +2 -1
  32. package/dist/src/constants/hooks.d.ts.map +1 -1
  33. package/dist/src/constants/hooks.js +1 -0
  34. package/dist/src/constants/hooks.js.map +1 -1
  35. package/dist/src/constants/index.d.ts +1 -0
  36. package/dist/src/constants/index.d.ts.map +1 -1
  37. package/dist/src/constants/index.js +1 -0
  38. package/dist/src/constants/index.js.map +1 -1
  39. package/dist/src/constants/parameters.d.ts +1 -0
  40. package/dist/src/constants/parameters.d.ts.map +1 -1
  41. package/dist/src/constants/parameters.js +1 -0
  42. package/dist/src/constants/parameters.js.map +1 -1
  43. package/dist/src/helpers/session-management-helper.d.ts +1 -1
  44. package/dist/src/helpers/session-management-helper.d.ts.map +1 -1
  45. package/dist/src/helpers/session-management-helper.js +33 -43
  46. package/dist/src/helpers/session-management-helper.js.map +1 -1
  47. package/dist/src/index-polyfill.d.ts +0 -1
  48. package/dist/src/index-polyfill.d.ts.map +1 -1
  49. package/dist/src/index-polyfill.js +0 -1
  50. package/dist/src/index-polyfill.js.map +1 -1
  51. package/dist/src/models/client.d.ts +3 -3
  52. package/dist/src/models/client.d.ts.map +1 -1
  53. package/dist/src/models/http-client.d.ts +1 -1
  54. package/dist/src/models/http-client.d.ts.map +1 -1
  55. package/dist/src/models/index.d.ts +1 -0
  56. package/dist/src/models/index.d.ts.map +1 -1
  57. package/dist/src/models/index.js +1 -0
  58. package/dist/src/models/index.js.map +1 -1
  59. package/dist/src/models/message.d.ts +1 -0
  60. package/dist/src/models/message.d.ts.map +1 -1
  61. package/dist/src/models/request-custom-grant.d.ts +25 -0
  62. package/dist/src/models/request-custom-grant.d.ts.map +1 -0
  63. package/dist/src/models/request-custom-grant.js +19 -0
  64. package/dist/src/models/request-custom-grant.js.map +1 -0
  65. package/dist/src/models/session-management-helper.d.ts +2 -1
  66. package/dist/src/models/session-management-helper.d.ts.map +1 -1
  67. package/dist/src/models/sign-out-error.d.ts +22 -0
  68. package/dist/src/models/sign-out-error.d.ts.map +1 -0
  69. package/dist/src/models/sign-out-error.js +19 -0
  70. package/dist/src/models/sign-out-error.js.map +1 -0
  71. package/dist/src/models/web-worker.d.ts +3 -3
  72. package/dist/src/models/web-worker.d.ts.map +1 -1
  73. package/dist/src/models/web-worker.js.map +1 -1
  74. package/dist/src/public-api.d.ts +1 -1
  75. package/dist/src/public-api.d.ts.map +1 -1
  76. package/dist/src/public-api.js +1 -1
  77. package/dist/src/public-api.js.map +1 -1
  78. package/dist/src/utils/crypto-utils.d.ts +35 -0
  79. package/dist/src/utils/crypto-utils.d.ts.map +1 -0
  80. package/dist/src/utils/crypto-utils.js +58 -0
  81. package/dist/src/utils/crypto-utils.js.map +1 -0
  82. package/dist/src/utils/spa-utils.d.ts +5 -3
  83. package/dist/src/utils/spa-utils.d.ts.map +1 -1
  84. package/dist/src/utils/spa-utils.js +26 -10
  85. package/dist/src/utils/spa-utils.js.map +1 -1
  86. package/dist/src/worker/client.worker.js +2 -2
  87. package/dist/src/worker/client.worker.js.map +1 -1
  88. package/dist/src/worker/worker-core.d.ts.map +1 -1
  89. package/dist/src/worker/worker-core.js +15 -13
  90. package/dist/src/worker/worker-core.js.map +1 -1
  91. package/dist/tsconfig.tsbuildinfo +1 -1
  92. package/package.json +31 -30
  93. package/rollup.config.js +3 -5
  94. package/src/client.ts +23 -17
  95. package/src/clients/main-thread-client.ts +52 -21
  96. package/src/clients/web-worker-client.ts +67 -26
  97. package/src/constants/errors.ts +19 -0
  98. package/src/constants/hooks.ts +2 -1
  99. package/src/constants/index.ts +1 -0
  100. package/src/constants/parameters.ts +1 -0
  101. package/src/helpers/session-management-helper.ts +31 -40
  102. package/src/index-polyfill.ts +0 -1
  103. package/src/models/client.ts +3 -2
  104. package/src/models/http-client.ts +3 -2
  105. package/src/models/index.ts +1 -0
  106. package/src/models/message.ts +1 -0
  107. package/src/models/request-custom-grant.ts +26 -0
  108. package/src/models/session-management-helper.ts +3 -2
  109. package/src/models/sign-out-error.ts +22 -0
  110. package/src/models/web-worker.ts +8 -2
  111. package/src/public-api.ts +2 -1
  112. package/src/utils/crypto-utils.ts +78 -0
  113. package/src/utils/spa-utils.ts +33 -10
  114. package/src/worker/client.worker.ts +1 -1
  115. package/src/worker/worker-core.ts +17 -12
@@ -20,17 +20,21 @@ import {
20
20
  AUTHORIZATION_CODE,
21
21
  AsgardeoAuthClient,
22
22
  AuthClientConfig,
23
+ AuthenticationUtils,
23
24
  BasicUserInfo,
24
25
  CustomGrantConfig,
25
26
  DecodedIDTokenPayload,
27
+ FetchResponse,
26
28
  GetAuthURLConfig,
27
29
  OIDCEndpoints,
28
30
  ResponseMode,
29
31
  SESSION_STATE,
32
+ STATE,
30
33
  Store,
31
34
  TokenResponse
32
35
  } from "@asgardeo/auth-js";
33
36
  import {
37
+ ACCESS_TOKEN_INVALID,
34
38
  CHECK_SESSION_SIGNED_IN,
35
39
  CHECK_SESSION_SIGNED_OUT,
36
40
  CUSTOM_GRANT_CONFIG,
@@ -53,8 +57,10 @@ import {
53
57
  MainThreadClientInterface,
54
58
  Message
55
59
  } from "../models";
60
+ import { SPACustomGrantConfig } from "../models/request-custom-grant";
56
61
  import { LocalStore, MemoryStore, SessionStore } from "../stores";
57
62
  import { SPAUtils } from "../utils";
63
+ import { SPACryptoUtils } from "../utils/crypto-utils";
58
64
 
59
65
  const initiateStore = (store: Storage | undefined): Store => {
60
66
  switch (store) {
@@ -73,12 +79,13 @@ export const MainThreadClient = async (
73
79
  config: AuthClientConfig<MainThreadClientConfig>
74
80
  ): Promise<MainThreadClientInterface> => {
75
81
  const _store: Store = initiateStore(config.storage);
76
- const _authenticationClient = new AsgardeoAuthClient<MainThreadClientConfig>(_store);
82
+ const _cryptoUtils: SPACryptoUtils = new SPACryptoUtils();
83
+ const _authenticationClient = new AsgardeoAuthClient<MainThreadClientConfig>(_store, _cryptoUtils);
77
84
  await _authenticationClient.initialize(config);
78
85
 
79
86
  const _spaHelper = new SPAHelper<MainThreadClientConfig>(_authenticationClient);
80
87
  const _dataLayer = _authenticationClient.getDataLayer();
81
- const _sessionManagementHelper = SessionManagementHelper(
88
+ const _sessionManagementHelper = await SessionManagementHelper(
82
89
  async () => {
83
90
  return _authenticationClient.signOut();
84
91
  },
@@ -86,6 +93,8 @@ export const MainThreadClient = async (
86
93
  (sessionState: string) => _dataLayer.setSessionDataParameter(SESSION_STATE, sessionState ?? "")
87
94
  );
88
95
 
96
+ let _getSignOutURLFromSessionStorage: boolean = false;
97
+
89
98
  const _httpClient: HttpClientInstance = HttpClient.getInstance();
90
99
  let _isHttpHandlerEnabled: boolean = true;
91
100
  let _httpErrorCallback: (error: HttpError) => void | Promise<void>;
@@ -147,7 +156,7 @@ export const MainThreadClient = async (
147
156
  } catch (refreshError: any) {
148
157
  if (_isHttpHandlerEnabled) {
149
158
  if (typeof _httpErrorCallback === "function") {
150
- await _httpErrorCallback(error);
159
+ await _httpErrorCallback({ ...error, code: ACCESS_TOKEN_INVALID });
151
160
  }
152
161
  if (typeof _httpFinishCallback === "function") {
153
162
  _httpFinishCallback();
@@ -256,7 +265,7 @@ export const MainThreadClient = async (
256
265
  } catch (refreshError: any) {
257
266
  if (_isHttpHandlerEnabled) {
258
267
  if (typeof _httpErrorCallback === "function") {
259
- await _httpErrorCallback(error);
268
+ await _httpErrorCallback({ ...error, code: ACCESS_TOKEN_INVALID });
260
269
  }
261
270
  if (typeof _httpFinishCallback === "function") {
262
271
  _httpFinishCallback();
@@ -353,15 +362,15 @@ export const MainThreadClient = async (
353
362
  config.checkSessionInterval ?? 3,
354
363
  config.sessionRefreshInterval ?? 300,
355
364
  config.signInRedirectURL,
356
- oidcEndpoints.authorizationEndpoint ?? "",
357
- config.enablePKCE
365
+ async (params?: GetAuthURLConfig): Promise<string> => _authenticationClient.getAuthorizationURL(params)
358
366
  );
359
367
  };
360
368
 
361
369
  const signIn = async (
362
370
  signInConfig?: GetAuthURLConfig,
363
371
  authorizationCode?: string,
364
- sessionState?: string
372
+ sessionState?: string,
373
+ state?: string
365
374
  ): Promise<BasicUserInfo> => {
366
375
  const config = await _dataLayer.getConfigData();
367
376
 
@@ -398,18 +407,22 @@ export const MainThreadClient = async (
398
407
 
399
408
  let resolvedAuthorizationCode: string;
400
409
  let resolvedSessionState: string;
410
+ let resolvedState: string;
401
411
 
402
412
  if (config?.responseMode === ResponseMode.formPost && authorizationCode) {
403
413
  resolvedAuthorizationCode = authorizationCode;
404
414
  resolvedSessionState = sessionState ?? "";
415
+ resolvedState = state ?? "";
405
416
  } else {
406
417
  resolvedAuthorizationCode = new URL(window.location.href).searchParams.get(AUTHORIZATION_CODE) ?? "";
407
418
  resolvedSessionState = new URL(window.location.href).searchParams.get(SESSION_STATE) ?? "";
419
+ resolvedState = new URL(window.location.href).searchParams.get(STATE) ?? "";
420
+
408
421
  SPAUtils.removeAuthorizationCode();
409
422
  }
410
423
 
411
424
  if (resolvedAuthorizationCode) {
412
- return requestAccessToken(resolvedAuthorizationCode, resolvedSessionState);
425
+ return requestAccessToken(resolvedAuthorizationCode, resolvedSessionState, resolvedState);
413
426
  }
414
427
 
415
428
  const error = new URL(window.location.href).searchParams.get(ERROR);
@@ -435,7 +448,9 @@ export const MainThreadClient = async (
435
448
 
436
449
  return _authenticationClient.getAuthorizationURL(signInConfig).then(async (url: string) => {
437
450
  if (config.storage === Storage.BrowserMemory && config.enablePKCE) {
438
- SPAUtils.setPKCE((await _authenticationClient.getPKCECode()) as string);
451
+ const pkceKey: string = AuthenticationUtils.extractPKCEKeyFromStateParam(resolvedState);
452
+
453
+ SPAUtils.setPKCE(pkceKey, (await _authenticationClient.getPKCECode(resolvedState)) as string);
439
454
  }
440
455
 
441
456
  location.href = url;
@@ -455,10 +470,13 @@ export const MainThreadClient = async (
455
470
  };
456
471
 
457
472
  const signOut = async (): Promise<boolean> => {
458
- if (await _authenticationClient.isAuthenticated()) {
473
+ if (await _authenticationClient.isAuthenticated() && !_getSignOutURLFromSessionStorage) {
459
474
  location.href = await _authenticationClient.signOut();
460
475
  } else {
461
476
  location.href = SPAUtils.getSignOutURL();
477
+ await _dataLayer.removeOIDCProviderMetaData();
478
+ await _dataLayer.removeTemporaryData();
479
+ await _dataLayer.removeSessionData();
462
480
  }
463
481
 
464
482
  _spaHelper.clearRefreshTokenTimeout();
@@ -468,7 +486,7 @@ export const MainThreadClient = async (
468
486
  return true;
469
487
  };
470
488
 
471
- const requestCustomGrant = async (config: CustomGrantConfig): Promise<BasicUserInfo | HttpResponse> => {
489
+ const requestCustomGrant = async (config: SPACustomGrantConfig): Promise<BasicUserInfo | FetchResponse> => {
472
490
  let useDefaultEndpoint = true;
473
491
  let matches = false;
474
492
  const clientConfig = await _dataLayer.getConfigData();
@@ -492,13 +510,17 @@ export const MainThreadClient = async (
492
510
  if (useDefaultEndpoint || matches) {
493
511
  return _authenticationClient
494
512
  .requestCustomGrant(config)
495
- .then(async (response: HttpResponse | TokenResponse) => {
513
+ .then(async (response: FetchResponse | TokenResponse) => {
514
+ if (config.preventSignOutURLUpdate) {
515
+ _getSignOutURLFromSessionStorage = true;
516
+ }
517
+
496
518
  if (config.returnsSession) {
497
519
  _spaHelper.refreshAccessTokenAutomatically();
498
520
 
499
521
  return _authenticationClient.getBasicUserInfo();
500
522
  } else {
501
- return response as HttpResponse;
523
+ return response as FetchResponse;
502
524
  }
503
525
  })
504
526
  .catch((error) => {
@@ -548,22 +570,27 @@ export const MainThreadClient = async (
548
570
 
549
571
  const requestAccessToken = async (
550
572
  resolvedAuthorizationCode: string,
551
- resolvedSessionState: string
573
+ resolvedSessionState: string,
574
+ resolvedState: string
552
575
  ): Promise<BasicUserInfo> => {
553
576
  const config = await _dataLayer.getConfigData();
554
577
 
555
578
  if (config.storage === Storage.BrowserMemory && config.enablePKCE) {
556
- const pkce = SPAUtils.getPKCE();
579
+ const pkce = SPAUtils.getPKCE(AuthenticationUtils.extractPKCEKeyFromStateParam(resolvedState));
557
580
 
558
- await _authenticationClient.setPKCECode(pkce);
581
+ await _authenticationClient.setPKCECode(
582
+ AuthenticationUtils.extractPKCEKeyFromStateParam(resolvedState),
583
+ pkce);
559
584
  }
560
585
 
561
586
  return _authenticationClient
562
- .requestAccessToken(resolvedAuthorizationCode, resolvedSessionState)
587
+ .requestAccessToken(resolvedAuthorizationCode, resolvedSessionState, resolvedState)
563
588
  .then(async () => {
564
- if (config.storage === Storage.BrowserMemory) {
589
+ // Disable this temporarily
590
+ /* if (config.storage === Storage.BrowserMemory) {
565
591
  SPAUtils.setSignOutURL(await _authenticationClient.getSignOutURL());
566
- }
592
+ } */
593
+ SPAUtils.setSignOutURL(await _authenticationClient.getSignOutURL());
567
594
 
568
595
  _spaHelper.clearRefreshTokenTimeout();
569
596
  _spaHelper.refreshAccessTokenAutomatically();
@@ -622,7 +649,11 @@ export const MainThreadClient = async (
622
649
  const url: string = urlObject.toString();
623
650
 
624
651
  if (config.storage === Storage.BrowserMemory && config.enablePKCE) {
625
- SPAUtils.setPKCE((await _authenticationClient.getPKCECode()) as string);
652
+ const state = urlObject.searchParams.get(STATE);
653
+
654
+ SPAUtils.setPKCE(
655
+ AuthenticationUtils.extractPKCEKeyFromStateParam( state ?? ""),
656
+ (await _authenticationClient.getPKCECode(state ?? "")) as string);
626
657
  }
627
658
 
628
659
  promptNoneIFrame.src = url;
@@ -645,7 +676,7 @@ export const MainThreadClient = async (
645
676
  }
646
677
 
647
678
  if (data?.type == CHECK_SESSION_SIGNED_IN && data?.data?.code) {
648
- requestAccessToken(data.data.code, data?.data?.sessionState)
679
+ requestAccessToken(data.data.code, data?.data?.sessionState, data?.data?.state)
649
680
  .then((response: BasicUserInfo) => {
650
681
  window.removeEventListener("message", listenToPromptNoneIFrame);
651
682
  resolve(response);
@@ -19,14 +19,17 @@
19
19
  import {
20
20
  AUTHORIZATION_CODE,
21
21
  AuthClientConfig,
22
+ AuthenticationUtils,
22
23
  BasicUserInfo,
23
24
  CustomGrantConfig,
24
25
  DecodedIDTokenPayload,
26
+ FetchResponse,
25
27
  GetAuthURLConfig,
26
28
  OIDCEndpoints,
27
29
  OIDCProviderMetaData,
28
30
  ResponseMode,
29
- SESSION_STATE
31
+ SESSION_STATE,
32
+ STATE
30
33
  } from "@asgardeo/auth-js";
31
34
  import WorkerFile from "web-worker:../worker/client.worker.ts";
32
35
  import {
@@ -76,9 +79,11 @@ import {
76
79
  WebWorkerClientConfig,
77
80
  WebWorkerClientInterface
78
81
  } from "../models";
82
+ import { SPACustomGrantConfig } from "../models/request-custom-grant";
79
83
  import { SPAUtils } from "../utils";
80
84
 
81
- export const WebWorkerClient = (config: AuthClientConfig<WebWorkerClientConfig>): WebWorkerClientInterface => {
85
+ export const WebWorkerClient = async (
86
+ config: AuthClientConfig<WebWorkerClientConfig>): Promise<WebWorkerClientInterface> => {
82
87
  /**
83
88
  * HttpClient handlers
84
89
  */
@@ -88,8 +93,9 @@ export const WebWorkerClient = (config: AuthClientConfig<WebWorkerClientConfig>)
88
93
  */
89
94
  const _requestTimeout: number = config?.requestTimeout ?? 60000;
90
95
  let _isHttpHandlerEnabled: boolean = true;
96
+ let _getSignOutURLFromSessionStorage: boolean = false;
91
97
 
92
- const _sessionManagementHelper = SessionManagementHelper(
98
+ const _sessionManagementHelper = await SessionManagementHelper(
93
99
  async () => {
94
100
  const message: Message<string> = {
95
101
  type: SIGN_OUT
@@ -154,14 +160,18 @@ export const WebWorkerClient = (config: AuthClientConfig<WebWorkerClientConfig>)
154
160
  * @returns {Promise<HttpResponse|boolean>} A promise that resolves with a boolean value or the request
155
161
  * response if the the `returnResponse` attribute in the `requestParams` object is set to `true`.
156
162
  */
157
- const requestCustomGrant = (requestParams: CustomGrantConfig): Promise<HttpResponse | BasicUserInfo> => {
163
+ const requestCustomGrant = (requestParams: SPACustomGrantConfig): Promise<FetchResponse | BasicUserInfo> => {
158
164
  const message: Message<CustomGrantConfig> = {
159
165
  data: requestParams,
160
166
  type: REQUEST_CUSTOM_GRANT
161
167
  };
162
168
 
163
- return communicate<CustomGrantConfig, HttpResponse | BasicUserInfo>(message)
169
+ return communicate<CustomGrantConfig, FetchResponse | BasicUserInfo>(message)
164
170
  .then((response) => {
171
+ if (requestParams.preventSignOutURLUpdate) {
172
+ _getSignOutURLFromSessionStorage = true;
173
+ }
174
+
165
175
  return Promise.resolve(response);
166
176
  })
167
177
  .catch((error) => {
@@ -339,8 +349,7 @@ export const WebWorkerClient = (config: AuthClientConfig<WebWorkerClientConfig>)
339
349
  config.checkSessionInterval ?? 3,
340
350
  config.sessionRefreshInterval ?? 300,
341
351
  config.signInRedirectURL,
342
- oidcEndpoints.authorizationEndpoint ?? "",
343
- config.enablePKCE
352
+ async (params?: GetAuthURLConfig): Promise<string> => (await getAuthorizationURL(params)).authorizationURL
344
353
  );
345
354
  };
346
355
 
@@ -387,7 +396,11 @@ export const WebWorkerClient = (config: AuthClientConfig<WebWorkerClientConfig>)
387
396
  try {
388
397
  const response: AuthorizationResponse = await communicate<GetAuthURLConfig, AuthorizationResponse>(message);
389
398
 
390
- response.pkce && config.enablePKCE && SPAUtils.setPKCE(response.pkce);
399
+ const pkceKey: string = AuthenticationUtils.extractPKCEKeyFromStateParam(
400
+ new URL(response.authorizationURL).searchParams.get(STATE) ?? ""
401
+ );
402
+
403
+ response.pkce && config.enablePKCE && SPAUtils.setPKCE(pkceKey, response.pkce);
391
404
 
392
405
  const urlString: string = response.authorizationURL;
393
406
 
@@ -416,7 +429,7 @@ export const WebWorkerClient = (config: AuthClientConfig<WebWorkerClientConfig>)
416
429
  }
417
430
 
418
431
  if (data?.type == CHECK_SESSION_SIGNED_IN && data?.data?.code) {
419
- requestAccessToken(data?.data?.code, data?.data?.sessionState)
432
+ requestAccessToken(data?.data?.code, data?.data?.sessionState, data?.data?.state)
420
433
  .then((response: BasicUserInfo) => {
421
434
  window.removeEventListener("message", listenToPromptNoneIFrame);
422
435
  resolve(response);
@@ -435,22 +448,54 @@ export const WebWorkerClient = (config: AuthClientConfig<WebWorkerClientConfig>)
435
448
  });
436
449
  };
437
450
 
451
+ /**
452
+ * Generates an authorization URL.
453
+ *
454
+ * @param {GetAuthURLConfig} params Authorization URL params.
455
+ * @returns {Promise<string>} Authorization URL.
456
+ */
457
+ const getAuthorizationURL = async (params?: GetAuthURLConfig): Promise<AuthorizationResponse> => {
458
+ const config: AuthClientConfig<WebWorkerClientConfig> = await getConfigData();
459
+
460
+ const message: Message<GetAuthURLConfig> = {
461
+ data: params,
462
+ type: GET_AUTH_URL
463
+ };
464
+
465
+ return communicate<GetAuthURLConfig, AuthorizationResponse>(message).then(
466
+ async (response: AuthorizationResponse) => {
467
+ if (response.pkce && config.enablePKCE) {
468
+ const pkceKey: string = AuthenticationUtils.extractPKCEKeyFromStateParam(
469
+ new URL(response.authorizationURL).searchParams.get(STATE) ?? "");
470
+
471
+ SPAUtils.setPKCE(pkceKey, response.pkce);
472
+ }
473
+
474
+ return Promise.resolve(response);
475
+ });
476
+ };
477
+
438
478
  const requestAccessToken = async (
439
479
  resolvedAuthorizationCode: string,
440
- resolvedSessionState: string
480
+ resolvedSessionState: string,
481
+ resolvedState: string
441
482
  ): Promise<BasicUserInfo> => {
442
483
  const config: AuthClientConfig<WebWorkerClientConfig> = await getConfigData();
484
+ const pkceKey: string = AuthenticationUtils.extractPKCEKeyFromStateParam(resolvedState);
443
485
 
444
486
  const message: Message<AuthorizationInfo> = {
445
487
  data: {
446
488
  code: resolvedAuthorizationCode,
447
- pkce: config.enablePKCE ? SPAUtils.getPKCE() : undefined,
448
- sessionState: resolvedSessionState
489
+ pkce: config.enablePKCE
490
+ ? SPAUtils.getPKCE(pkceKey)
491
+ : undefined,
492
+ sessionState: resolvedSessionState,
493
+ state: resolvedState
449
494
  },
450
495
  type: REQUEST_ACCESS_TOKEN
451
496
  };
452
497
 
453
- config.enablePKCE && SPAUtils.removePKCE();
498
+ config.enablePKCE && SPAUtils.removePKCE(pkceKey);
454
499
 
455
500
  return communicate<AuthorizationInfo, BasicUserInfo>(message)
456
501
  .then((response) => {
@@ -488,7 +533,8 @@ export const WebWorkerClient = (config: AuthClientConfig<WebWorkerClientConfig>)
488
533
  const signIn = async (
489
534
  params?: GetAuthURLConfig,
490
535
  authorizationCode?: string,
491
- sessionState?: string
536
+ sessionState?: string,
537
+ state?: string
492
538
  ): Promise<BasicUserInfo> => {
493
539
  const config: AuthClientConfig<WebWorkerClientConfig> = await getConfigData();
494
540
 
@@ -544,30 +590,25 @@ export const WebWorkerClient = (config: AuthClientConfig<WebWorkerClientConfig>)
544
590
 
545
591
  let resolvedAuthorizationCode: string;
546
592
  let resolvedSessionState: string;
593
+ let resolvedState: string;
547
594
 
548
595
  if (config?.responseMode === ResponseMode.formPost && authorizationCode) {
549
596
  resolvedAuthorizationCode = authorizationCode;
550
597
  resolvedSessionState = sessionState ?? "";
598
+ resolvedState = state ?? "";
551
599
  } else {
552
600
  resolvedAuthorizationCode = new URL(window.location.href).searchParams.get(AUTHORIZATION_CODE) ?? "";
553
601
  resolvedSessionState = new URL(window.location.href).searchParams.get(SESSION_STATE) ?? "";
602
+ resolvedState = new URL(window.location.href).searchParams.get(STATE) ?? "";
603
+
554
604
  SPAUtils.removeAuthorizationCode();
555
605
  }
556
606
 
557
607
  if (resolvedAuthorizationCode) {
558
- return requestAccessToken(resolvedAuthorizationCode, resolvedSessionState);
608
+ return requestAccessToken(resolvedAuthorizationCode, resolvedSessionState, resolvedState);
559
609
  }
560
610
 
561
- const message: Message<GetAuthURLConfig> = {
562
- data: params,
563
- type: GET_AUTH_URL
564
- };
565
-
566
- return communicate<GetAuthURLConfig, AuthorizationResponse>(message)
567
- .then(async (response) => {
568
- if (response.pkce && config.enablePKCE) {
569
- SPAUtils.setPKCE(response.pkce);
570
- }
611
+ return getAuthorizationURL(params).then(async (response: AuthorizationResponse)=>{
571
612
 
572
613
  location.href = response.authorizationURL;
573
614
 
@@ -596,7 +637,7 @@ export const WebWorkerClient = (config: AuthClientConfig<WebWorkerClientConfig>)
596
637
  const signOut = (): Promise<boolean> => {
597
638
  return isAuthenticated()
598
639
  .then(async (response: boolean) => {
599
- if (response) {
640
+ if (response && !_getSignOutURLFromSessionStorage) {
600
641
  const message: Message<null> = {
601
642
  type: SIGN_OUT
602
643
  };
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.com) All Rights Reserved.
3
+ *
4
+ * WSO2 Inc. licenses this file to you under the Apache License,
5
+ * Version 2.0 (the "License"); you may not use this file except
6
+ * in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing,
12
+ * software distributed under the License is distributed on an
13
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
+ * KIND, either express or implied. See the License for the
15
+ * specific language governing permissions and limitations
16
+ * under the License.
17
+ */
18
+
19
+ export const ACCESS_TOKEN_INVALID = "Access token is invalid";
@@ -25,5 +25,6 @@ export enum Hooks {
25
25
  HttpRequestError = "http-request-error",
26
26
  HttpRequestSuccess = "http-request-success",
27
27
  RevokeAccessToken = "revoke-access-token",
28
- CustomGrant = "custom-grant"
28
+ CustomGrant = "custom-grant",
29
+ SignOutFailed = "sign-out-failed"
29
30
  }
@@ -21,3 +21,4 @@ export * from "./storage";
21
21
  export * from "./hooks";
22
22
  export * from "./session-management";
23
23
  export * from "./parameters";
24
+ export * from "./errors";
@@ -19,3 +19,4 @@
19
19
  export const ERROR = "error";
20
20
  export const ERROR_DESCRIPTION = "error_description";
21
21
  export const CUSTOM_GRANT_CONFIG = "custom_grant_config";
22
+ export const STATE_QUERY = "state";
@@ -16,7 +16,7 @@
16
16
  * under the License.
17
17
  */
18
18
 
19
- import { SESSION_STATE } from "@asgardeo/auth-js";
19
+ import { GetAuthURLConfig, SESSION_STATE } from "@asgardeo/auth-js";
20
20
  import {
21
21
  CHECK_SESSION_SIGNED_IN,
22
22
  CHECK_SESSION_SIGNED_OUT,
@@ -27,6 +27,7 @@ import {
27
27
  SET_SESSION_STATE_FROM_IFRAME,
28
28
  SILENT_SIGN_IN_STATE,
29
29
  STATE,
30
+ STATE_QUERY,
30
31
  Storage
31
32
  } from "../constants";
32
33
  import { AuthorizationInfo, Message, SessionManagementHelperInterface } from "../models";
@@ -38,14 +39,13 @@ export const SessionManagementHelper = (() => {
38
39
  let _sessionState: () => Promise<string>;
39
40
  let _interval: number;
40
41
  let _redirectURL: string;
41
- let _authorizationEndpoint: string;
42
42
  let _sessionRefreshInterval: number;
43
43
  let _signOut: () => Promise<string>;
44
44
  let _sessionRefreshIntervalTimeout: number;
45
45
  let _checkSessionIntervalTimeout: number;
46
46
  let _storage: Storage;
47
47
  let _setSessionState: (sessionState: string) => void;
48
- let _isPKCEEnabled: boolean;
48
+ let _getAuthorizationURL: (params?: GetAuthURLConfig) => Promise<string>;
49
49
 
50
50
  const initialize = (
51
51
  clientID: string,
@@ -54,17 +54,15 @@ export const SessionManagementHelper = (() => {
54
54
  interval: number,
55
55
  sessionRefreshInterval: number,
56
56
  redirectURL: string,
57
- authorizationEndpoint: string,
58
- isPKCEEnabled: boolean
57
+ getAuthorizationURL: (params?: GetAuthURLConfig) => Promise<string>
59
58
  ): void => {
60
59
  _clientID = clientID;
61
60
  _checkSessionEndpoint = checkSessionEndpoint;
62
61
  _sessionState = getSessionState;
63
62
  _interval = interval;
64
63
  _redirectURL = redirectURL;
65
- _authorizationEndpoint = authorizationEndpoint;
66
64
  _sessionRefreshInterval = sessionRefreshInterval;
67
- _isPKCEEnabled = isPKCEEnabled;
65
+ _getAuthorizationURL = getAuthorizationURL;
68
66
 
69
67
  if (_interval > -1) {
70
68
  initiateCheckSession();
@@ -115,17 +113,6 @@ export const SessionManagementHelper = (() => {
115
113
  clearInterval(_sessionRefreshIntervalTimeout);
116
114
  }
117
115
 
118
- const getRandomPKCEChallenge = (): string => {
119
- const chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz-_";
120
- const stringLength = 43;
121
- let randomString = "";
122
- for (let i = 0; i < stringLength; i++) {
123
- const rnum = Math.floor(Math.random() * chars.length);
124
- randomString += chars.substring(rnum, rnum + 1);
125
- }
126
- return randomString;
127
- };
128
-
129
116
  const listenToResponseFromOPIFrame = (): void => {
130
117
  async function receiveMessage(e: MessageEvent) {
131
118
  const targetOrigin = _checkSessionEndpoint;
@@ -149,7 +136,7 @@ export const SessionManagementHelper = (() => {
149
136
  window?.addEventListener("message", receiveMessage, false);
150
137
  };
151
138
 
152
- const sendPromptNoneRequest = () => {
139
+ const sendPromptNoneRequest = async () => {
153
140
  const rpIFrame = document.getElementById(RP_IFRAME) as HTMLIFrameElement;
154
141
 
155
142
  const promptNoneIFrame: HTMLIFrameElement = rpIFrame?.contentDocument?.getElementById(
@@ -170,20 +157,12 @@ export const SessionManagementHelper = (() => {
170
157
  window?.addEventListener("message", receiveMessageListener);
171
158
  }
172
159
 
173
- const promptNoneURL = new URL(_authorizationEndpoint);
174
- promptNoneURL.searchParams.set("response_type", "code");
175
- promptNoneURL.searchParams.set("client_id", _clientID);
176
- promptNoneURL.searchParams.set("scope", "openid");
177
- promptNoneURL.searchParams.set("redirect_uri", _redirectURL);
178
- promptNoneURL.searchParams.set("state", STATE);
179
- promptNoneURL.searchParams.set("prompt", "none");
180
-
181
- if(_isPKCEEnabled){
182
- promptNoneURL.searchParams.set("code_challenge_method", "S256");
183
- promptNoneURL.searchParams.set("code_challenge", getRandomPKCEChallenge());
184
- }
160
+ const promptNoneURL: string = await _getAuthorizationURL({
161
+ prompt: "none",
162
+ state: STATE
163
+ });
185
164
 
186
- promptNoneIFrame.src = promptNoneURL.toString();
165
+ promptNoneIFrame.src = promptNoneURL;
187
166
  }
188
167
  };
189
168
 
@@ -196,20 +175,21 @@ export const SessionManagementHelper = (() => {
196
175
  const receivePromptNoneResponse = async (
197
176
  setSessionState?: (sessionState: string | null) => Promise<void>
198
177
  ): Promise<boolean> => {
199
- const state = new URL(window.location.href).searchParams.get("state");
178
+ const state = new URL(window.location.href).searchParams.get(STATE_QUERY);
200
179
  const sessionState = new URL(window.location.href).searchParams.get(SESSION_STATE);
201
180
  const parent = window.parent.parent;
202
181
 
203
- if (state !== null && (state === STATE || state === SILENT_SIGN_IN_STATE)) {
182
+ if (state !== null && (state.includes(STATE) || state.includes(SILENT_SIGN_IN_STATE))) {
204
183
  // Prompt none response.
205
184
  const code = new URL(window.location.href).searchParams.get("code");
206
185
 
207
186
  if (code !== null && code.length !== 0) {
208
- if (state === SILENT_SIGN_IN_STATE) {
187
+ if (state.includes(SILENT_SIGN_IN_STATE)) {
209
188
  const message: Message<AuthorizationInfo> = {
210
189
  data: {
211
190
  code,
212
- sessionState: sessionState ?? ""
191
+ sessionState: sessionState ?? "",
192
+ state
213
193
  },
214
194
  type: CHECK_SESSION_SIGNED_IN
215
195
  };
@@ -228,7 +208,7 @@ export const SessionManagementHelper = (() => {
228
208
  const newSessionState = new URL(window.location.href).searchParams.get("session_state");
229
209
 
230
210
  if (_storage === Storage.LocalStorage || _storage === Storage.SessionStorage) {
231
- setSessionState && await setSessionState(newSessionState);
211
+ setSessionState && (await setSessionState(newSessionState));
232
212
  } else {
233
213
  const message: Message<string> = {
234
214
  data: newSessionState ?? "",
@@ -246,7 +226,7 @@ export const SessionManagementHelper = (() => {
246
226
 
247
227
  return true;
248
228
  } else {
249
- if (state === SILENT_SIGN_IN_STATE) {
229
+ if (state.includes(SILENT_SIGN_IN_STATE)) {
250
230
  const message: Message<null> = {
251
231
  type: CHECK_SESSION_SIGNED_OUT
252
232
  };
@@ -275,15 +255,16 @@ export const SessionManagementHelper = (() => {
275
255
  return false;
276
256
  };
277
257
 
278
- return (
258
+ return async (
279
259
  signOut: () => Promise<string>,
280
260
  storage: Storage,
281
261
  setSessionState: (sessionState: string) => void
282
- ): SessionManagementHelperInterface => {
262
+ ): Promise<SessionManagementHelperInterface> => {
283
263
  let rpIFrame = document.createElement("iframe");
284
264
  rpIFrame.setAttribute("id", RP_IFRAME);
285
265
  rpIFrame.style.display = "none";
286
266
 
267
+ let rpIframeLoaded: boolean = false;
287
268
  rpIFrame.onload = () => {
288
269
  rpIFrame = document.getElementById(RP_IFRAME) as HTMLIFrameElement;
289
270
 
@@ -303,6 +284,8 @@ export const SessionManagementHelper = (() => {
303
284
 
304
285
  opIFrame && rpIFrame?.contentDocument?.body?.appendChild(opIFrame);
305
286
  promptNoneIFrame && rpIFrame?.contentDocument?.body?.appendChild(promptNoneIFrame);
287
+
288
+ rpIframeLoaded = true;
306
289
  }
307
290
 
308
291
  document?.body?.appendChild(rpIFrame);
@@ -312,6 +295,14 @@ export const SessionManagementHelper = (() => {
312
295
  _storage = storage;
313
296
  _setSessionState = setSessionState;
314
297
 
298
+ const sleep = (): Promise<any> => {
299
+ return new Promise((resolve) => setTimeout(resolve, 1));
300
+ };
301
+
302
+ while (rpIframeLoaded === false) {
303
+ await sleep();
304
+ }
305
+
315
306
  return {
316
307
  initialize,
317
308
  receivePromptNoneResponse,
@@ -17,7 +17,6 @@
17
17
  */
18
18
 
19
19
  import "core-js/stable";
20
- import "regenerator-runtime/runtime";
21
20
 
22
21
  // Export the public API.
23
22
  export * from "./public-api";