@asgardeo/auth-spa 0.3.8 → 0.3.9
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/dist/asgardeo-spa.production.esm.js +13 -13
- package/dist/asgardeo-spa.production.esm.js.map +1 -1
- package/dist/asgardeo-spa.production.js +13 -13
- 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 +42 -40
- package/dist/polyfilled/asgardeo-spa.production.esm.js.map +1 -1
- package/dist/polyfilled/asgardeo-spa.production.js +42 -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 +21 -16
- package/dist/src/client.d.ts.map +1 -1
- package/dist/src/client.js +29 -3
- package/dist/src/client.js.map +1 -1
- package/dist/src/clients/main-thread-client.d.ts +3 -2
- package/dist/src/clients/main-thread-client.d.ts.map +1 -1
- package/dist/src/clients/main-thread-client.js +83 -385
- package/dist/src/clients/main-thread-client.js.map +1 -1
- package/dist/src/clients/web-worker-client.d.ts +3 -2
- package/dist/src/clients/web-worker-client.d.ts.map +1 -1
- package/dist/src/clients/web-worker-client.js +98 -138
- package/dist/src/clients/web-worker-client.js.map +1 -1
- package/dist/src/helpers/authentication-helper.d.ts +50 -0
- package/dist/src/helpers/authentication-helper.d.ts.map +1 -0
- package/dist/src/helpers/authentication-helper.js +482 -0
- package/dist/src/helpers/authentication-helper.js.map +1 -0
- package/dist/src/helpers/index.d.ts +1 -0
- package/dist/src/helpers/index.d.ts.map +1 -1
- package/dist/src/helpers/index.js +1 -0
- package/dist/src/helpers/index.js.map +1 -1
- package/dist/src/public-api.d.ts +3 -0
- package/dist/src/public-api.d.ts.map +1 -1
- package/dist/src/public-api.js +5 -0
- package/dist/src/public-api.js.map +1 -1
- package/dist/src/worker/index.d.ts +1 -1
- package/dist/src/worker/index.d.ts.map +1 -1
- package/dist/src/worker/index.js +1 -1
- package/dist/src/worker/index.js.map +1 -1
- package/dist/src/worker/worker-core.d.ts +3 -2
- package/dist/src/worker/worker-core.d.ts.map +1 -1
- package/dist/src/worker/worker-core.js +23 -202
- package/dist/src/worker/worker-core.js.map +1 -1
- package/dist/src/worker/worker-receiver.d.ts +22 -0
- package/dist/src/worker/worker-receiver.d.ts.map +1 -0
- package/dist/src/worker/worker-receiver.js +233 -0
- package/dist/src/worker/worker-receiver.js.map +1 -0
- package/dist/src/{worker/client.worker.d.ts → worker.d.ts} +2 -2
- package/dist/src/worker.d.ts.map +1 -0
- package/dist/src/worker.js +24 -0
- package/dist/src/worker.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/client.ts +65 -19
- package/src/clients/main-thread-client.ts +137 -486
- package/src/clients/web-worker-client.ts +128 -169
- package/src/helpers/authentication-helper.ts +661 -0
- package/src/helpers/index.ts +1 -0
- package/src/public-api.ts +7 -0
- package/src/worker/index.ts +1 -1
- package/src/worker/worker-core.ts +48 -261
- package/src/worker/worker-receiver.ts +297 -0
- package/src/worker.ts +30 -0
- package/dist/src/worker/client.worker.d.ts.map +0 -1
- package/dist/src/worker/client.worker.js +0 -232
- package/dist/src/worker/client.worker.js.map +0 -1
- package/src/worker/client.worker.ts +0 -286
|
@@ -0,0 +1,661 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) 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
|
+
import {
|
|
20
|
+
AsgardeoAuthClient,
|
|
21
|
+
AsgardeoAuthException,
|
|
22
|
+
AuthClientConfig,
|
|
23
|
+
AuthenticationUtils,
|
|
24
|
+
BasicUserInfo,
|
|
25
|
+
CustomGrantConfig,
|
|
26
|
+
DataLayer,
|
|
27
|
+
DecodedIDTokenPayload,
|
|
28
|
+
FetchResponse,
|
|
29
|
+
GetAuthURLConfig,
|
|
30
|
+
OIDCEndpoints,
|
|
31
|
+
TokenResponse
|
|
32
|
+
} from "@asgardeo/auth-js";
|
|
33
|
+
import { SPAHelper } from "./spa-helper";
|
|
34
|
+
import { Message, SPAUtils, SessionManagementHelperInterface } from "..";
|
|
35
|
+
import {
|
|
36
|
+
ACCESS_TOKEN_INVALID,
|
|
37
|
+
CHECK_SESSION_SIGNED_IN,
|
|
38
|
+
CHECK_SESSION_SIGNED_OUT,
|
|
39
|
+
CUSTOM_GRANT_CONFIG,
|
|
40
|
+
ERROR,
|
|
41
|
+
ERROR_DESCRIPTION,
|
|
42
|
+
PROMPT_NONE_IFRAME,
|
|
43
|
+
RP_IFRAME,
|
|
44
|
+
Storage
|
|
45
|
+
} from "../constants";
|
|
46
|
+
import {
|
|
47
|
+
AuthorizationInfo,
|
|
48
|
+
HttpClientInstance,
|
|
49
|
+
HttpError,
|
|
50
|
+
HttpRequestConfig,
|
|
51
|
+
HttpResponse,
|
|
52
|
+
MainThreadClientConfig,
|
|
53
|
+
WebWorkerClientConfig
|
|
54
|
+
} from "../models";
|
|
55
|
+
import { SPACustomGrantConfig } from "../models/request-custom-grant";
|
|
56
|
+
|
|
57
|
+
export class AuthenticationHelper<
|
|
58
|
+
T extends MainThreadClientConfig | WebWorkerClientConfig
|
|
59
|
+
> {
|
|
60
|
+
protected _authenticationClient: AsgardeoAuthClient<T>;
|
|
61
|
+
protected _dataLayer: DataLayer<T>;
|
|
62
|
+
protected _spaHelper: SPAHelper<T>;
|
|
63
|
+
|
|
64
|
+
public constructor(
|
|
65
|
+
authClient: AsgardeoAuthClient<T>,
|
|
66
|
+
spaHelper: SPAHelper<T>
|
|
67
|
+
) {
|
|
68
|
+
this._authenticationClient = authClient;
|
|
69
|
+
this._dataLayer = this._authenticationClient.getDataLayer();
|
|
70
|
+
this._spaHelper = spaHelper;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
public async attachToken(request: HttpRequestConfig): Promise<void> {
|
|
74
|
+
const requestConfig = { attachToken: true, ...request };
|
|
75
|
+
if (requestConfig.attachToken) {
|
|
76
|
+
request.headers = {
|
|
77
|
+
...request.headers,
|
|
78
|
+
Authorization: `Bearer ${ await this._authenticationClient.getAccessToken() }`
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
public setHttpRequestStartCallback(
|
|
84
|
+
_httpClient: HttpClientInstance,
|
|
85
|
+
callback: () => void
|
|
86
|
+
): void {
|
|
87
|
+
_httpClient?.setHttpRequestStartCallback &&
|
|
88
|
+
_httpClient.setHttpRequestStartCallback(callback);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
public setHttpRequestSuccessCallback(
|
|
92
|
+
_httpClient: HttpClientInstance,
|
|
93
|
+
callback: (response: HttpResponse) => void
|
|
94
|
+
): void {
|
|
95
|
+
_httpClient?.setHttpRequestSuccessCallback &&
|
|
96
|
+
_httpClient.setHttpRequestSuccessCallback(callback);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
public setHttpRequestFinishCallback(
|
|
100
|
+
_httpClient: HttpClientInstance,
|
|
101
|
+
callback: () => void
|
|
102
|
+
): void {
|
|
103
|
+
_httpClient?.setHttpRequestFinishCallback &&
|
|
104
|
+
_httpClient.setHttpRequestFinishCallback(callback);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
public enableHttpHandler(httpClient: HttpClientInstance): void {
|
|
108
|
+
httpClient?.enableHandler && httpClient.enableHandler();
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
public disableHttpHandler (httpClient: HttpClientInstance): void {
|
|
112
|
+
httpClient?.disableHandler && httpClient.disableHandler();
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
public initializeSessionManger(
|
|
116
|
+
config: AuthClientConfig<T>,
|
|
117
|
+
oidcEndpoints: OIDCEndpoints,
|
|
118
|
+
getSessionState: () => Promise<string>,
|
|
119
|
+
getAuthzURL: (params?: GetAuthURLConfig) => Promise<string>,
|
|
120
|
+
sessionManagementHelper: SessionManagementHelperInterface
|
|
121
|
+
): void {
|
|
122
|
+
sessionManagementHelper.initialize(
|
|
123
|
+
config.clientID,
|
|
124
|
+
oidcEndpoints.checkSessionIframe ?? "",
|
|
125
|
+
getSessionState,
|
|
126
|
+
config.checkSessionInterval ?? 3,
|
|
127
|
+
config.sessionRefreshInterval ?? 300,
|
|
128
|
+
config.signInRedirectURL,
|
|
129
|
+
getAuthzURL
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
public async requestCustomGrant(
|
|
134
|
+
config: SPACustomGrantConfig,
|
|
135
|
+
enableRetrievingSignOutURLFromSession?: (config: SPACustomGrantConfig) => void
|
|
136
|
+
): Promise<BasicUserInfo | FetchResponse> {
|
|
137
|
+
let useDefaultEndpoint = true;
|
|
138
|
+
let matches = false;
|
|
139
|
+
|
|
140
|
+
// If the config does not contains a token endpoint, default token endpoint will be used.
|
|
141
|
+
if (config?.tokenEndpoint) {
|
|
142
|
+
useDefaultEndpoint = false;
|
|
143
|
+
|
|
144
|
+
for (const baseUrl of [
|
|
145
|
+
...((await this._dataLayer.getConfigData())?.resourceServerURLs ?? []),
|
|
146
|
+
(config as any).baseUrl
|
|
147
|
+
]) {
|
|
148
|
+
if (baseUrl && config.tokenEndpoint?.startsWith(baseUrl)) {
|
|
149
|
+
matches = true;
|
|
150
|
+
break;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
if (config.shouldReplayAfterRefresh) {
|
|
155
|
+
this._dataLayer.setTemporaryDataParameter(
|
|
156
|
+
CUSTOM_GRANT_CONFIG,
|
|
157
|
+
JSON.stringify(config)
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
if (useDefaultEndpoint || matches) {
|
|
161
|
+
return this._authenticationClient
|
|
162
|
+
.requestCustomGrant(config)
|
|
163
|
+
.then(async (response: FetchResponse | TokenResponse) => {
|
|
164
|
+
if (enableRetrievingSignOutURLFromSession &&
|
|
165
|
+
typeof enableRetrievingSignOutURLFromSession === "function") {
|
|
166
|
+
enableRetrievingSignOutURLFromSession(config);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
if (config.returnsSession) {
|
|
170
|
+
this._spaHelper.refreshAccessTokenAutomatically();
|
|
171
|
+
|
|
172
|
+
return this._authenticationClient.getBasicUserInfo();
|
|
173
|
+
} else {
|
|
174
|
+
return response as FetchResponse;
|
|
175
|
+
}
|
|
176
|
+
})
|
|
177
|
+
.catch((error) => {
|
|
178
|
+
return Promise.reject(error);
|
|
179
|
+
});
|
|
180
|
+
} else {
|
|
181
|
+
return Promise.reject(
|
|
182
|
+
new AsgardeoAuthException(
|
|
183
|
+
"SPA-MAIN_THREAD_CLIENT-RCG-IV01",
|
|
184
|
+
"Request to the provided endpoint is prohibited.",
|
|
185
|
+
"Requests can only be sent to resource servers specified by the `resourceServerURLs`" +
|
|
186
|
+
" attribute while initializing the SDK. The specified token endpoint in this request " +
|
|
187
|
+
"cannot be found among the `resourceServerURLs`"
|
|
188
|
+
)
|
|
189
|
+
);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
public async getCustomGrantConfigData(): Promise<AuthClientConfig<CustomGrantConfig> | null> {
|
|
194
|
+
const configString = await this._dataLayer.getTemporaryDataParameter(
|
|
195
|
+
CUSTOM_GRANT_CONFIG
|
|
196
|
+
);
|
|
197
|
+
|
|
198
|
+
if (configString) {
|
|
199
|
+
return JSON.parse(configString as string);
|
|
200
|
+
} else {
|
|
201
|
+
return null;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
public async refreshAccessToken(
|
|
206
|
+
enableRetrievingSignOutURLFromSession?: (config: SPACustomGrantConfig) => void
|
|
207
|
+
): Promise<BasicUserInfo> {
|
|
208
|
+
try {
|
|
209
|
+
await this._authenticationClient.refreshAccessToken();
|
|
210
|
+
const customGrantConfig = await this.getCustomGrantConfigData();
|
|
211
|
+
if (customGrantConfig) {
|
|
212
|
+
await this.requestCustomGrant(
|
|
213
|
+
customGrantConfig,
|
|
214
|
+
enableRetrievingSignOutURLFromSession
|
|
215
|
+
);
|
|
216
|
+
}
|
|
217
|
+
this._spaHelper.refreshAccessTokenAutomatically();
|
|
218
|
+
|
|
219
|
+
return this._authenticationClient.getBasicUserInfo();
|
|
220
|
+
} catch (error) {
|
|
221
|
+
return Promise.reject(error);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
public async httpRequest(
|
|
226
|
+
httpClient: HttpClientInstance,
|
|
227
|
+
requestConfig: HttpRequestConfig,
|
|
228
|
+
isHttpHandlerEnabled?: boolean,
|
|
229
|
+
httpErrorCallback?: (error: HttpError) => void | Promise<void>,
|
|
230
|
+
httpFinishCallback?: () => void,
|
|
231
|
+
enableRetrievingSignOutURLFromSession?: (config: SPACustomGrantConfig) => void
|
|
232
|
+
): Promise<HttpResponse> {
|
|
233
|
+
let matches = false;
|
|
234
|
+
const config = await this._dataLayer.getConfigData();
|
|
235
|
+
|
|
236
|
+
for (const baseUrl of [
|
|
237
|
+
...((await config?.resourceServerURLs) ?? []),
|
|
238
|
+
(config as any).baseUrl
|
|
239
|
+
]) {
|
|
240
|
+
if (baseUrl && requestConfig?.url?.startsWith(baseUrl)) {
|
|
241
|
+
matches = true;
|
|
242
|
+
|
|
243
|
+
break;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
if (matches) {
|
|
248
|
+
return httpClient
|
|
249
|
+
.request(requestConfig)
|
|
250
|
+
.then((response: HttpResponse) => {
|
|
251
|
+
return Promise.resolve(response);
|
|
252
|
+
})
|
|
253
|
+
.catch(async (error: HttpError) => {
|
|
254
|
+
if (error?.response?.status === 401 || !error?.response) {
|
|
255
|
+
// Try to refresh the token
|
|
256
|
+
let refreshAccessTokenResponse: BasicUserInfo;
|
|
257
|
+
try {
|
|
258
|
+
refreshAccessTokenResponse = await this.refreshAccessToken(
|
|
259
|
+
enableRetrievingSignOutURLFromSession
|
|
260
|
+
);
|
|
261
|
+
} catch (refreshError: any) {
|
|
262
|
+
if (isHttpHandlerEnabled) {
|
|
263
|
+
if (typeof httpErrorCallback === "function") {
|
|
264
|
+
await httpErrorCallback({
|
|
265
|
+
...error,
|
|
266
|
+
code: ACCESS_TOKEN_INVALID
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
if (typeof httpFinishCallback === "function") {
|
|
270
|
+
httpFinishCallback();
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
throw new AsgardeoAuthException(
|
|
275
|
+
"SPA-AUTH_HELPER-HR-SE01",
|
|
276
|
+
refreshError?.name ?? "Refresh token request failed.",
|
|
277
|
+
refreshError?.message ??
|
|
278
|
+
"An error occurred while trying to refresh the " +
|
|
279
|
+
"access token following a 401 response from the server."
|
|
280
|
+
);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
// Retry the request after refreshing the token
|
|
284
|
+
if (refreshAccessTokenResponse) {
|
|
285
|
+
try {
|
|
286
|
+
const httpResponse = await httpClient.request(requestConfig);
|
|
287
|
+
return Promise.resolve(httpResponse);
|
|
288
|
+
} catch (error: any) {
|
|
289
|
+
if (isHttpHandlerEnabled) {
|
|
290
|
+
if (typeof httpErrorCallback === "function") {
|
|
291
|
+
await httpErrorCallback(error);
|
|
292
|
+
}
|
|
293
|
+
if (typeof httpFinishCallback === "function") {
|
|
294
|
+
httpFinishCallback();
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
return Promise.reject(error);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
if (isHttpHandlerEnabled) {
|
|
303
|
+
if (typeof httpErrorCallback === "function") {
|
|
304
|
+
await httpErrorCallback(error);
|
|
305
|
+
}
|
|
306
|
+
if (typeof httpFinishCallback === "function") {
|
|
307
|
+
httpFinishCallback();
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
return Promise.reject(error);
|
|
312
|
+
});
|
|
313
|
+
} else {
|
|
314
|
+
return Promise.reject(
|
|
315
|
+
new AsgardeoAuthException(
|
|
316
|
+
"SPA-AUTH_HELPER-HR-IV02",
|
|
317
|
+
"Request to the provided endpoint is prohibited.",
|
|
318
|
+
"Requests can only be sent to resource servers specified by the `resourceServerURLs`" +
|
|
319
|
+
" attribute while initializing the SDK. The specified endpoint in this request " +
|
|
320
|
+
"cannot be found among the `resourceServerURLs`"
|
|
321
|
+
)
|
|
322
|
+
);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
public async httpRequestAll(
|
|
327
|
+
requestConfigs: HttpRequestConfig[],
|
|
328
|
+
httpClient: HttpClientInstance,
|
|
329
|
+
isHttpHandlerEnabled?: boolean,
|
|
330
|
+
httpErrorCallback?: (error: HttpError) => void | Promise<void>,
|
|
331
|
+
httpFinishCallback?: () => void
|
|
332
|
+
): Promise<HttpResponse[] | undefined> {
|
|
333
|
+
let matches = true;
|
|
334
|
+
const config = await this._dataLayer.getConfigData();
|
|
335
|
+
|
|
336
|
+
for (const requestConfig of requestConfigs) {
|
|
337
|
+
let urlMatches = false;
|
|
338
|
+
|
|
339
|
+
for (const baseUrl of [
|
|
340
|
+
...((await config)?.resourceServerURLs ?? []),
|
|
341
|
+
(config as any).baseUrl
|
|
342
|
+
]) {
|
|
343
|
+
if (baseUrl && requestConfig.url?.startsWith(baseUrl)) {
|
|
344
|
+
urlMatches = true;
|
|
345
|
+
|
|
346
|
+
break;
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
if (!urlMatches) {
|
|
351
|
+
matches = false;
|
|
352
|
+
|
|
353
|
+
break;
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
const requests: Promise<HttpResponse<any>>[] = [];
|
|
358
|
+
|
|
359
|
+
if (matches) {
|
|
360
|
+
requestConfigs.forEach((request) => {
|
|
361
|
+
requests.push(httpClient.request(request));
|
|
362
|
+
});
|
|
363
|
+
|
|
364
|
+
return (
|
|
365
|
+
httpClient?.all &&
|
|
366
|
+
httpClient
|
|
367
|
+
.all(requests)
|
|
368
|
+
.then((responses: HttpResponse[]) => {
|
|
369
|
+
return Promise.resolve(responses);
|
|
370
|
+
})
|
|
371
|
+
.catch(async (error: HttpError) => {
|
|
372
|
+
if (error?.response?.status === 401 || !error?.response) {
|
|
373
|
+
let refreshTokenResponse: TokenResponse | BasicUserInfo;
|
|
374
|
+
try {
|
|
375
|
+
refreshTokenResponse = await this._authenticationClient.refreshAccessToken();
|
|
376
|
+
} catch (refreshError: any) {
|
|
377
|
+
if (isHttpHandlerEnabled) {
|
|
378
|
+
if (typeof httpErrorCallback === "function") {
|
|
379
|
+
await httpErrorCallback({
|
|
380
|
+
...error,
|
|
381
|
+
code: ACCESS_TOKEN_INVALID
|
|
382
|
+
});
|
|
383
|
+
}
|
|
384
|
+
if (typeof httpFinishCallback === "function") {
|
|
385
|
+
httpFinishCallback();
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
throw new AsgardeoAuthException(
|
|
390
|
+
"SPA-AUTH_HELPER-HRA-SE01",
|
|
391
|
+
refreshError?.name ?? "Refresh token request failed.",
|
|
392
|
+
refreshError?.message ??
|
|
393
|
+
"An error occurred while trying to refresh the " +
|
|
394
|
+
"access token following a 401 response from the server."
|
|
395
|
+
);
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
if (refreshTokenResponse) {
|
|
399
|
+
return (
|
|
400
|
+
httpClient.all &&
|
|
401
|
+
httpClient
|
|
402
|
+
.all(requests)
|
|
403
|
+
.then((response) => {
|
|
404
|
+
return Promise.resolve(response);
|
|
405
|
+
})
|
|
406
|
+
.catch(async (error) => {
|
|
407
|
+
if (isHttpHandlerEnabled) {
|
|
408
|
+
if (typeof httpErrorCallback === "function") {
|
|
409
|
+
await httpErrorCallback(error);
|
|
410
|
+
}
|
|
411
|
+
if (typeof httpFinishCallback === "function") {
|
|
412
|
+
httpFinishCallback();
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
return Promise.reject(error);
|
|
417
|
+
})
|
|
418
|
+
);
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
if (isHttpHandlerEnabled) {
|
|
423
|
+
if (typeof httpErrorCallback === "function") {
|
|
424
|
+
await httpErrorCallback(error);
|
|
425
|
+
}
|
|
426
|
+
if (typeof httpFinishCallback === "function") {
|
|
427
|
+
httpFinishCallback();
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
return Promise.reject(error);
|
|
432
|
+
})
|
|
433
|
+
);
|
|
434
|
+
} else {
|
|
435
|
+
throw new AsgardeoAuthException(
|
|
436
|
+
"SPA-AUTH_HELPER-HRA-IV02",
|
|
437
|
+
"Request to the provided endpoint is prohibited.",
|
|
438
|
+
"Requests can only be sent to resource servers specified by the `resourceServerURLs`" +
|
|
439
|
+
" attribute while initializing the SDK. The specified endpoint in this request " +
|
|
440
|
+
"cannot be found among the `resourceServerURLs`"
|
|
441
|
+
);
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
public async requestAccessToken(
|
|
446
|
+
authorizationCode?: string,
|
|
447
|
+
sessionState?: string,
|
|
448
|
+
checkSession?: () => Promise<void>,
|
|
449
|
+
pkce?: string,
|
|
450
|
+
state?: string
|
|
451
|
+
): Promise<BasicUserInfo> {
|
|
452
|
+
const config = await this._dataLayer.getConfigData();
|
|
453
|
+
|
|
454
|
+
if (config.storage === Storage.BrowserMemory && config.enablePKCE && sessionState) {
|
|
455
|
+
const pkce = SPAUtils.getPKCE(
|
|
456
|
+
AuthenticationUtils.extractPKCEKeyFromStateParam(sessionState)
|
|
457
|
+
);
|
|
458
|
+
|
|
459
|
+
await this._authenticationClient.setPKCECode(
|
|
460
|
+
AuthenticationUtils.extractPKCEKeyFromStateParam(sessionState),
|
|
461
|
+
pkce
|
|
462
|
+
);
|
|
463
|
+
} else if (config.storage === Storage.WebWorker && pkce) {
|
|
464
|
+
await this._authenticationClient.setPKCECode(pkce, state ?? "");
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
if (authorizationCode) {
|
|
468
|
+
return this._authenticationClient
|
|
469
|
+
.requestAccessToken(authorizationCode, sessionState ?? "", state ?? "")
|
|
470
|
+
.then(async () => {
|
|
471
|
+
// Disable this temporarily
|
|
472
|
+
/* if (config.storage === Storage.BrowserMemory) {
|
|
473
|
+
SPAUtils.setSignOutURL(await _authenticationClient.getSignOutURL());
|
|
474
|
+
} */
|
|
475
|
+
if (config.storage !== Storage.WebWorker) {
|
|
476
|
+
SPAUtils.setSignOutURL(await this._authenticationClient.getSignOutURL());
|
|
477
|
+
|
|
478
|
+
if (this._spaHelper) {
|
|
479
|
+
this._spaHelper.clearRefreshTokenTimeout();
|
|
480
|
+
this._spaHelper.refreshAccessTokenAutomatically();
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
// Enable OIDC Sessions Management only if it is set to true in the config.
|
|
484
|
+
if (
|
|
485
|
+
checkSession &&
|
|
486
|
+
typeof checkSession === "function" &&
|
|
487
|
+
config.enableOIDCSessionManagement
|
|
488
|
+
) {
|
|
489
|
+
checkSession();
|
|
490
|
+
}
|
|
491
|
+
} else {
|
|
492
|
+
if (this._spaHelper) {
|
|
493
|
+
this._spaHelper.refreshAccessTokenAutomatically();
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
return this._authenticationClient.getBasicUserInfo();
|
|
498
|
+
})
|
|
499
|
+
.catch((error) => {
|
|
500
|
+
return Promise.reject(error);
|
|
501
|
+
});
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
return Promise.reject(
|
|
505
|
+
new AsgardeoAuthException(
|
|
506
|
+
"SPA-AUTH_HELPER-RAT1-NF01",
|
|
507
|
+
"No authorization code.",
|
|
508
|
+
"No authorization code was found."
|
|
509
|
+
)
|
|
510
|
+
);
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
public async trySignInSilently(
|
|
514
|
+
constructSilentSignInUrl: () => Promise<string>,
|
|
515
|
+
requestAccessToken: (authzCode: string, sessionState: string, state: string) => Promise<BasicUserInfo>,
|
|
516
|
+
sessionManagementHelper: SessionManagementHelperInterface
|
|
517
|
+
): Promise<BasicUserInfo | boolean> {
|
|
518
|
+
|
|
519
|
+
// This block is executed by the iFrame when the server redirects with the authorization code.
|
|
520
|
+
if (SPAUtils.isInitializedSilentSignIn()) {
|
|
521
|
+
await sessionManagementHelper.receivePromptNoneResponse();
|
|
522
|
+
|
|
523
|
+
return Promise.resolve({
|
|
524
|
+
allowedScopes: "",
|
|
525
|
+
displayName: "",
|
|
526
|
+
email: "",
|
|
527
|
+
sessionState: "",
|
|
528
|
+
sub: "",
|
|
529
|
+
tenantDomain: "",
|
|
530
|
+
username: ""
|
|
531
|
+
});
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
// This gets executed in the main thread and sends the prompt none request.
|
|
535
|
+
const rpIFrame = document.getElementById(RP_IFRAME) as HTMLIFrameElement;
|
|
536
|
+
|
|
537
|
+
const promptNoneIFrame: HTMLIFrameElement = rpIFrame?.contentDocument?.getElementById(
|
|
538
|
+
PROMPT_NONE_IFRAME
|
|
539
|
+
) as HTMLIFrameElement;
|
|
540
|
+
|
|
541
|
+
try {
|
|
542
|
+
const url = await constructSilentSignInUrl();
|
|
543
|
+
|
|
544
|
+
promptNoneIFrame.src = url;
|
|
545
|
+
} catch (error) {
|
|
546
|
+
return Promise.reject(error);
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
return new Promise((resolve, reject) => {
|
|
550
|
+
const timer = setTimeout(() => {
|
|
551
|
+
resolve(false);
|
|
552
|
+
}, 10000);
|
|
553
|
+
|
|
554
|
+
const listenToPromptNoneIFrame = async (e: MessageEvent) => {
|
|
555
|
+
const data: Message<AuthorizationInfo | null> = e.data;
|
|
556
|
+
|
|
557
|
+
if (data?.type == CHECK_SESSION_SIGNED_OUT) {
|
|
558
|
+
window.removeEventListener("message", listenToPromptNoneIFrame);
|
|
559
|
+
clearTimeout(timer);
|
|
560
|
+
resolve(false);
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
if (data?.type == CHECK_SESSION_SIGNED_IN && data?.data?.code) {
|
|
564
|
+
requestAccessToken(data?.data?.code, data?.data?.sessionState, data?.data?.state)
|
|
565
|
+
.then((response: BasicUserInfo) => {
|
|
566
|
+
window.removeEventListener("message", listenToPromptNoneIFrame);
|
|
567
|
+
resolve(response);
|
|
568
|
+
})
|
|
569
|
+
.catch((error) => {
|
|
570
|
+
window.removeEventListener("message", listenToPromptNoneIFrame);
|
|
571
|
+
reject(error);
|
|
572
|
+
})
|
|
573
|
+
.finally(() => {
|
|
574
|
+
clearTimeout(timer);
|
|
575
|
+
});
|
|
576
|
+
}
|
|
577
|
+
};
|
|
578
|
+
|
|
579
|
+
window.addEventListener("message", listenToPromptNoneIFrame);
|
|
580
|
+
});
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
public async handleSignIn (
|
|
584
|
+
shouldStopAuthn: () => Promise<boolean>,
|
|
585
|
+
checkSession: () => Promise<void>,
|
|
586
|
+
tryRetrievingUserInfo?: () => Promise<BasicUserInfo | undefined>
|
|
587
|
+
): Promise<BasicUserInfo | undefined> {
|
|
588
|
+
const config = await this._dataLayer.getConfigData();
|
|
589
|
+
|
|
590
|
+
if (await shouldStopAuthn()) {
|
|
591
|
+
return Promise.resolve({
|
|
592
|
+
allowedScopes: "",
|
|
593
|
+
displayName: "",
|
|
594
|
+
email: "",
|
|
595
|
+
sessionState: "",
|
|
596
|
+
sub: "",
|
|
597
|
+
tenantDomain: "",
|
|
598
|
+
username: ""
|
|
599
|
+
});
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
if (config.storage !== Storage.WebWorker) {
|
|
603
|
+
if (await this._authenticationClient.isAuthenticated()) {
|
|
604
|
+
this._spaHelper.clearRefreshTokenTimeout();
|
|
605
|
+
this._spaHelper.refreshAccessTokenAutomatically();
|
|
606
|
+
|
|
607
|
+
// Enable OIDC Sessions Management only if it is set to true in the config.
|
|
608
|
+
if (config.enableOIDCSessionManagement) {
|
|
609
|
+
checkSession();
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
return Promise.resolve(await this._authenticationClient.getBasicUserInfo());
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
const error = new URL(window.location.href).searchParams.get(ERROR);
|
|
617
|
+
const errorDescription = new URL(window.location.href).searchParams.get(ERROR_DESCRIPTION);
|
|
618
|
+
|
|
619
|
+
if (error) {
|
|
620
|
+
const url = new URL(window.location.href);
|
|
621
|
+
url.searchParams.delete(ERROR);
|
|
622
|
+
url.searchParams.delete(ERROR_DESCRIPTION);
|
|
623
|
+
|
|
624
|
+
history.pushState(null, document.title, url.toString());
|
|
625
|
+
|
|
626
|
+
throw new AsgardeoAuthException("SPA-AUTH_HELPER-SI-SE01", error, errorDescription ?? "");
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
if (config.storage === Storage.WebWorker && tryRetrievingUserInfo) {
|
|
630
|
+
const basicUserInfo = await tryRetrievingUserInfo();
|
|
631
|
+
|
|
632
|
+
if (basicUserInfo) {
|
|
633
|
+
return basicUserInfo;
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
public async getBasicUserInfo(): Promise<BasicUserInfo> {
|
|
639
|
+
return this._authenticationClient.getBasicUserInfo();
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
public async getDecodedIDToken(): Promise<DecodedIDTokenPayload> {
|
|
643
|
+
return this._authenticationClient.getDecodedIDToken();
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
public async getIDToken(): Promise<string> {
|
|
647
|
+
return this._authenticationClient.getIDToken();
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
public async getOIDCServiceEndpoints(): Promise<OIDCEndpoints> {
|
|
651
|
+
return this._authenticationClient.getOIDCServiceEndpoints();
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
public async getAccessToken(): Promise<string> {
|
|
655
|
+
return this._authenticationClient.getAccessToken();
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
public async isAuthenticated(): Promise<boolean> {
|
|
659
|
+
return this._authenticationClient.isAuthenticated();
|
|
660
|
+
}
|
|
661
|
+
}
|
package/src/helpers/index.ts
CHANGED
package/src/public-api.ts
CHANGED
|
@@ -30,3 +30,10 @@ export * from "./constants/storage";
|
|
|
30
30
|
export * from "./constants/hooks";
|
|
31
31
|
|
|
32
32
|
export * from "@asgardeo/auth-js";
|
|
33
|
+
|
|
34
|
+
// helpers
|
|
35
|
+
export * from "./helpers/authentication-helper";
|
|
36
|
+
export * from "./helpers/spa-helper";
|
|
37
|
+
|
|
38
|
+
// worker receiver
|
|
39
|
+
export * from "./worker/worker-receiver";
|
package/src/worker/index.ts
CHANGED