@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.
- package/.eslintrc.js +1 -2
- package/README.md +12 -5
- package/babel.config.js +1 -2
- package/dist/asgardeo-spa.production.esm.js +100 -42
- package/dist/asgardeo-spa.production.esm.js.map +1 -1
- package/dist/asgardeo-spa.production.js +101 -43
- package/dist/asgardeo-spa.production.js.map +1 -1
- package/dist/asgardeo-spa.production.min.js +1 -1
- package/dist/asgardeo-spa.production.min.js.map +1 -1
- package/dist/polyfilled/asgardeo-spa.production.esm.js +98 -40
- package/dist/polyfilled/asgardeo-spa.production.esm.js.map +1 -1
- package/dist/polyfilled/asgardeo-spa.production.js +98 -40
- package/dist/polyfilled/asgardeo-spa.production.js.map +1 -1
- package/dist/polyfilled/asgardeo-spa.production.min.js +1 -1
- package/dist/polyfilled/asgardeo-spa.production.min.js.map +1 -1
- package/dist/src/client.d.ts +4 -3
- package/dist/src/client.d.ts.map +1 -1
- package/dist/src/client.js +13 -4
- package/dist/src/client.js.map +1 -1
- package/dist/src/clients/main-thread-client.d.ts.map +1 -1
- package/dist/src/clients/main-thread-client.js +41 -25
- package/dist/src/clients/main-thread-client.js.map +1 -1
- package/dist/src/clients/web-worker-client.d.ts +1 -1
- package/dist/src/clients/web-worker-client.d.ts.map +1 -1
- package/dist/src/clients/web-worker-client.js +55 -30
- package/dist/src/clients/web-worker-client.js.map +1 -1
- package/dist/src/constants/errors.d.ts +19 -0
- package/dist/src/constants/errors.d.ts.map +1 -0
- package/dist/src/constants/errors.js +19 -0
- package/dist/src/constants/errors.js.map +1 -0
- package/dist/src/constants/hooks.d.ts +2 -1
- package/dist/src/constants/hooks.d.ts.map +1 -1
- package/dist/src/constants/hooks.js +1 -0
- package/dist/src/constants/hooks.js.map +1 -1
- package/dist/src/constants/index.d.ts +1 -0
- package/dist/src/constants/index.d.ts.map +1 -1
- package/dist/src/constants/index.js +1 -0
- package/dist/src/constants/index.js.map +1 -1
- package/dist/src/constants/parameters.d.ts +1 -0
- package/dist/src/constants/parameters.d.ts.map +1 -1
- package/dist/src/constants/parameters.js +1 -0
- package/dist/src/constants/parameters.js.map +1 -1
- package/dist/src/helpers/session-management-helper.d.ts +1 -1
- package/dist/src/helpers/session-management-helper.d.ts.map +1 -1
- package/dist/src/helpers/session-management-helper.js +33 -43
- package/dist/src/helpers/session-management-helper.js.map +1 -1
- package/dist/src/index-polyfill.d.ts +0 -1
- package/dist/src/index-polyfill.d.ts.map +1 -1
- package/dist/src/index-polyfill.js +0 -1
- package/dist/src/index-polyfill.js.map +1 -1
- package/dist/src/models/client.d.ts +3 -3
- package/dist/src/models/client.d.ts.map +1 -1
- package/dist/src/models/http-client.d.ts +1 -1
- package/dist/src/models/http-client.d.ts.map +1 -1
- package/dist/src/models/index.d.ts +1 -0
- package/dist/src/models/index.d.ts.map +1 -1
- package/dist/src/models/index.js +1 -0
- package/dist/src/models/index.js.map +1 -1
- package/dist/src/models/message.d.ts +1 -0
- package/dist/src/models/message.d.ts.map +1 -1
- package/dist/src/models/request-custom-grant.d.ts +25 -0
- package/dist/src/models/request-custom-grant.d.ts.map +1 -0
- package/dist/src/models/request-custom-grant.js +19 -0
- package/dist/src/models/request-custom-grant.js.map +1 -0
- package/dist/src/models/session-management-helper.d.ts +2 -1
- package/dist/src/models/session-management-helper.d.ts.map +1 -1
- package/dist/src/models/sign-out-error.d.ts +22 -0
- package/dist/src/models/sign-out-error.d.ts.map +1 -0
- package/dist/src/models/sign-out-error.js +19 -0
- package/dist/src/models/sign-out-error.js.map +1 -0
- package/dist/src/models/web-worker.d.ts +3 -3
- package/dist/src/models/web-worker.d.ts.map +1 -1
- package/dist/src/models/web-worker.js.map +1 -1
- package/dist/src/public-api.d.ts +1 -1
- package/dist/src/public-api.d.ts.map +1 -1
- package/dist/src/public-api.js +1 -1
- package/dist/src/public-api.js.map +1 -1
- package/dist/src/utils/crypto-utils.d.ts +35 -0
- package/dist/src/utils/crypto-utils.d.ts.map +1 -0
- package/dist/src/utils/crypto-utils.js +58 -0
- package/dist/src/utils/crypto-utils.js.map +1 -0
- package/dist/src/utils/spa-utils.d.ts +5 -3
- package/dist/src/utils/spa-utils.d.ts.map +1 -1
- package/dist/src/utils/spa-utils.js +26 -10
- package/dist/src/utils/spa-utils.js.map +1 -1
- package/dist/src/worker/client.worker.js +2 -2
- package/dist/src/worker/client.worker.js.map +1 -1
- package/dist/src/worker/worker-core.d.ts.map +1 -1
- package/dist/src/worker/worker-core.js +15 -13
- package/dist/src/worker/worker-core.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +31 -30
- package/rollup.config.js +3 -5
- package/src/client.ts +23 -17
- package/src/clients/main-thread-client.ts +52 -21
- package/src/clients/web-worker-client.ts +67 -26
- package/src/constants/errors.ts +19 -0
- package/src/constants/hooks.ts +2 -1
- package/src/constants/index.ts +1 -0
- package/src/constants/parameters.ts +1 -0
- package/src/helpers/session-management-helper.ts +31 -40
- package/src/index-polyfill.ts +0 -1
- package/src/models/client.ts +3 -2
- package/src/models/http-client.ts +3 -2
- package/src/models/index.ts +1 -0
- package/src/models/message.ts +1 -0
- package/src/models/request-custom-grant.ts +26 -0
- package/src/models/session-management-helper.ts +3 -2
- package/src/models/sign-out-error.ts +22 -0
- package/src/models/web-worker.ts +8 -2
- package/src/public-api.ts +2 -1
- package/src/utils/crypto-utils.ts +78 -0
- package/src/utils/spa-utils.ts +33 -10
- package/src/worker/client.worker.ts +1 -1
- 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
|
|
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
|
-
|
|
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
|
-
|
|
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:
|
|
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:
|
|
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
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
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 = (
|
|
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:
|
|
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,
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
448
|
-
|
|
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
|
-
|
|
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";
|
package/src/constants/hooks.ts
CHANGED
|
@@ -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
|
}
|
package/src/constants/index.ts
CHANGED
|
@@ -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
|
|
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
|
-
|
|
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
|
-
|
|
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 =
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
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
|
|
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(
|
|
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
|
|
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
|
|
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
|
|
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,
|