@tidecloak/js 0.12.47 → 0.13.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/lib/tidecloak.js +1630 -1760
- package/dist/cjs/lib/tidecloak.js.map +1 -1
- package/dist/cjs/src/IAMService.js +11 -5
- package/dist/cjs/src/IAMService.js.map +1 -1
- package/dist/cjs/src/index.js +21 -4
- package/dist/cjs/src/index.js.map +1 -1
- package/dist/esm/lib/tidecloak.js +1619 -1760
- package/dist/esm/lib/tidecloak.js.map +1 -1
- package/dist/esm/src/IAMService.js +1 -1
- package/dist/esm/src/IAMService.js.map +1 -1
- package/dist/esm/src/index.js +6 -2
- package/dist/esm/src/index.js.map +1 -1
- package/dist/types/lib/tidecloak.d.ts +31 -325
- package/dist/types/src/IAMService.d.ts +2 -1
- package/dist/types/src/index.d.ts +2 -2
- package/package.json +29 -18
- package/scripts/postinstall.js +43 -0
- package/dist/cjs/src/policy-react.js +0 -3
- package/dist/cjs/src/policy-react.js.map +0 -1
- package/dist/cjs/src/policy.css +0 -1
- package/dist/esm/src/policy-react.js +0 -3
- package/dist/esm/src/policy-react.js.map +0 -1
- package/dist/esm/src/policy.css +0 -1
- package/dist/types/IAMService.d.ts +0 -106
- package/dist/types/index.d.ts +0 -3
- package/dist/types/policy-react.d.ts +0 -1
- package/dist/types/src/policy-react.d.ts +0 -1
- package/scripts/postinstall.cjs +0 -36
- package/silent-check-sso.html +0 -1
|
@@ -4,6 +4,15 @@
|
|
|
4
4
|
*
|
|
5
5
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
6
|
* you may not use this file except 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, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
7
16
|
*
|
|
8
17
|
* Modifications Copyright (C) 2025 Tide Foundation Ltd
|
|
9
18
|
* Tide Protocol - Infrastructure for a TRUE Zero-Trust paradigm
|
|
@@ -22,1786 +31,1792 @@
|
|
|
22
31
|
* You should have received a copy of the Tide Community Open Code License along
|
|
23
32
|
* with this program. If not, see https://tide.org/licenses_tcoc2-0-0-en
|
|
24
33
|
*/
|
|
25
|
-
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
26
|
-
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
27
|
-
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
28
|
-
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
29
|
-
};
|
|
30
|
-
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
31
|
-
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
32
|
-
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
33
|
-
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
34
|
-
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
35
|
-
};
|
|
36
|
-
var _TideCloak_instances, _TideCloak_refreshQueue, _TideCloak_adapter, _TideCloak_useNonce, _TideCloak_callbackStorage, _TideCloak_logInfo, _TideCloak_logWarn, _TideCloak_loginIframe, _TideCloak_config, _TideCloak_loadAdapter, _TideCloak_loadDefaultAdapter, _TideCloak_loadCordovaAdapter, _TideCloak_loadCordovaNativeAdapter, _TideCloak_loadConfig, _TideCloak_setupEndpoints, _TideCloak_loadOidcConfig, _TideCloak_setupOidcEndpoints, _TideCloak_check3pCookiesSupported, _TideCloak_processInit, _TideCloak_setupCheckLoginIframe, _TideCloak_checkLoginIframe, _TideCloak_checkSsoSilently, _TideCloak_parseCallback, _TideCloak_parseCallbackUrl, _TideCloak_parseCallbackParams, _TideCloak_processCallback, _TideCloak_scheduleCheckIframe, _TideCloak_getVoucherUrl, _TideCloak_setToken, _TideCloak_getRealmUrl, _TideCloak_createLogger, _LocalStorage_instances, _LocalStorage_clearInvalidValues, _LocalStorage_clearAllValues, _LocalStorage_getStoredEntries, _LocalStorage_parseExpiry, _CookieStorage_instances, _CookieStorage_getCookie, _CookieStorage_setCookie, _CookieStorage_cookieExpiration;
|
|
37
34
|
// MODIFIED: Added dependency to external Tide helper libraries.
|
|
38
|
-
import { RequestEnclave, ApprovalEnclave
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
);
|
|
69
|
-
/** @type {KeycloakAdapter} */
|
|
70
|
-
_TideCloak_adapter.set(this, void 0);
|
|
71
|
-
/** @type {boolean} */
|
|
72
|
-
_TideCloak_useNonce.set(this, true
|
|
73
|
-
/** @type {CallbackStorage} */
|
|
74
|
-
);
|
|
75
|
-
/** @type {CallbackStorage} */
|
|
76
|
-
_TideCloak_callbackStorage.set(this, void 0);
|
|
77
|
-
_TideCloak_logInfo.set(this, __classPrivateFieldGet(this, _TideCloak_instances, "m", _TideCloak_createLogger).call(this, console.info));
|
|
78
|
-
_TideCloak_logWarn.set(this, __classPrivateFieldGet(this, _TideCloak_instances, "m", _TideCloak_createLogger).call(this, console.warn)
|
|
79
|
-
/** @type {LoginIframe} */
|
|
80
|
-
);
|
|
81
|
-
/** @type {LoginIframe} */
|
|
82
|
-
_TideCloak_loginIframe.set(this, {
|
|
83
|
-
enable: true,
|
|
84
|
-
callbackList: [],
|
|
85
|
-
interval: 5
|
|
86
|
-
}
|
|
87
|
-
/** @type {KeycloakConfig} config */
|
|
88
|
-
);
|
|
89
|
-
/** @type {KeycloakConfig} config */
|
|
90
|
-
_TideCloak_config.set(this, void 0);
|
|
91
|
-
this.didInitialize = false;
|
|
92
|
-
this.authenticated = false;
|
|
93
|
-
this.loginRequired = false;
|
|
94
|
-
/** @type {KeycloakResponseMode} */
|
|
95
|
-
this.responseMode = 'fragment';
|
|
96
|
-
/** @type {KeycloakResponseType} */
|
|
97
|
-
this.responseType = 'code';
|
|
98
|
-
/** @type {KeycloakFlow} */
|
|
99
|
-
this.flow = 'standard';
|
|
100
|
-
/** @type {boolean} */
|
|
101
|
-
this.silentCheckSsoFallback = true;
|
|
102
|
-
/** @type {KeycloakPkceMethod} */
|
|
103
|
-
this.pkceMethod = 'S256';
|
|
104
|
-
this.enableLogging = false;
|
|
105
|
-
/** @type {'GET' | 'POST'} */
|
|
106
|
-
this.logoutMethod = 'GET';
|
|
107
|
-
this.messageReceiveTimeout = 10000;
|
|
108
|
-
if (typeof config !== 'string' && !isObject(config)) {
|
|
109
|
-
throw new Error("The 'TideCloak' constructor must be provided with a configuration object, or a URL to a JSON configuration file.");
|
|
110
|
-
}
|
|
111
|
-
// if (isObject(config)) {
|
|
112
|
-
// const requiredProperties = 'oidcProvider' in config
|
|
113
|
-
// ? ['clientId']
|
|
114
|
-
// : ['url', 'realm', 'clientId', 'homeOrkUrl', 'vendorId', 'clientOriginAuth']
|
|
115
|
-
// for (const property of requiredProperties) {
|
|
116
|
-
// if (!config[property]) {
|
|
117
|
-
// throw new Error(`The configuration object is missing the required '${property}' property.`)
|
|
118
|
-
// }
|
|
119
|
-
// }
|
|
120
|
-
// }
|
|
121
|
-
if (!globalThis.isSecureContext) {
|
|
122
|
-
__classPrivateFieldGet(this, _TideCloak_logWarn, "f").call(this, "[TIDECLOAK] TideCloak JS must be used in a 'secure context' to function properly as it relies on browser APIs that are otherwise not available.\n" +
|
|
123
|
-
'Continuing to run your application insecurely will lead to unexpected behavior and breakage.\n\n' +
|
|
124
|
-
'For more information see: https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts');
|
|
125
|
-
}
|
|
126
|
-
__classPrivateFieldSet(this, _TideCloak_config, config, "f");
|
|
35
|
+
import { RequestEnclave, ApprovalEnclave } from "heimdall-tide";
|
|
36
|
+
import { StringFromUint8Array, StringToUint8Array, CreateTideMemory } from "../modules/tide-js/Cryptide/Serialization.js";
|
|
37
|
+
import { AuthorizedEncryptionFlow } from "../modules/tide-js/Flow/EncryptionFlows/AuthorizedEncryptionFlow.js";
|
|
38
|
+
import dVVKSigningFlow_DEPRECATED from "../modules/tide-js/Flow/SigningFlows/dVVKSigningFlow_DEPRECATED.js";
|
|
39
|
+
import CardanoTxBodySignRequest from "../modules/tide-js/Models/Transactions/CardanoTxBodySignRequest.js";
|
|
40
|
+
import RuleSettingsSignRequest from "../modules/tide-js/Models/Rules/RuleSettingSignRequest.js";
|
|
41
|
+
import AuthorizationBuilder from "../modules/tide-js/Models/AuthorizationBuilder.js";
|
|
42
|
+
import { GenSessKey, GetPublic } from "../modules/tide-js/Cryptide/Math.js";
|
|
43
|
+
import NetworkClient from "../modules/tide-js/Clients/NetworkClient.js";
|
|
44
|
+
import { ModelRegistry } from "../modules/tide-js/Models/ModelRegistry.js";
|
|
45
|
+
import processThresholdRules from "../modules/tide-js/RulesEngine/thresholdRules.js";
|
|
46
|
+
import dVVKDecryptionFlow from "../modules/tide-js/Flow/DecryptionFlows/dVVKDecryptionFlow.js";
|
|
47
|
+
import dVVKSigningFlow from "../modules/tide-js/Flow/SigningFlows/dVVKSigningFlow.js";
|
|
48
|
+
// MODIFIED: Refactored `Keycloak` class into `TideCloak`.
|
|
49
|
+
function TideCloak(config) {
|
|
50
|
+
if (!(this instanceof TideCloak)) {
|
|
51
|
+
throw new Error("The 'TideCloak' constructor must be invoked with 'new'.");
|
|
52
|
+
}
|
|
53
|
+
if (typeof config !== 'string' && !isObject(config)) {
|
|
54
|
+
throw new Error("The 'TideCloak' constructor must be provided with a configuration object, or a URL to a JSON configuration file.");
|
|
55
|
+
}
|
|
56
|
+
if (isObject(config)) {
|
|
57
|
+
const requiredProperties = 'oidcProvider' in config
|
|
58
|
+
? ['clientId']
|
|
59
|
+
: ['url', 'realm', 'clientId', 'homeOrkUrl', 'vendorId', 'clientOriginAuth'];
|
|
60
|
+
for (const property of requiredProperties) {
|
|
61
|
+
if (!config[property]) {
|
|
62
|
+
throw new Error(`The configuration object is missing the required '${property}' property.`);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
127
65
|
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
66
|
+
var kc = this;
|
|
67
|
+
var adapter;
|
|
68
|
+
var refreshQueue = [];
|
|
69
|
+
var callbackStorage;
|
|
70
|
+
var loginIframe = {
|
|
71
|
+
enable: true,
|
|
72
|
+
callbackList: [],
|
|
73
|
+
interval: 5
|
|
74
|
+
};
|
|
75
|
+
kc.didInitialize = false;
|
|
76
|
+
var useNonce = true;
|
|
77
|
+
var logInfo = createLogger(console.info);
|
|
78
|
+
var logWarn = createLogger(console.warn);
|
|
79
|
+
if (!globalThis.isSecureContext) {
|
|
80
|
+
logWarn("[TIDECLOAK] TideCloak-JS must be used in a 'secure context' to function properly as it relies on browser APIs that are otherwise not available.\n" +
|
|
81
|
+
"Continuing to run your application insecurely will lead to unexpected behavior and breakage.\n\n" +
|
|
82
|
+
"For more information see: https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts");
|
|
83
|
+
}
|
|
84
|
+
kc.init = function (initOptions = {}) {
|
|
85
|
+
if (kc.didInitialize) {
|
|
135
86
|
throw new Error("A 'TideCloak' instance can only be initialized once.");
|
|
136
87
|
}
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
88
|
+
kc.didInitialize = true;
|
|
89
|
+
kc.authenticated = false;
|
|
90
|
+
callbackStorage = createCallbackStorage();
|
|
91
|
+
var adapters = ['default', 'cordova', 'cordova-native'];
|
|
92
|
+
if (adapters.indexOf(initOptions.adapter) > -1) {
|
|
93
|
+
adapter = loadAdapter(initOptions.adapter);
|
|
142
94
|
}
|
|
143
|
-
else if (typeof initOptions.adapter ===
|
|
144
|
-
|
|
145
|
-
}
|
|
146
|
-
else if ('Cordova' in window || 'cordova' in window) {
|
|
147
|
-
__classPrivateFieldSet(this, _TideCloak_adapter, __classPrivateFieldGet(this, _TideCloak_instances, "m", _TideCloak_loadAdapter).call(this, 'cordova'), "f");
|
|
95
|
+
else if (typeof initOptions.adapter === "object") {
|
|
96
|
+
adapter = initOptions.adapter;
|
|
148
97
|
}
|
|
149
98
|
else {
|
|
150
|
-
|
|
99
|
+
if (window.Cordova || window.cordova) {
|
|
100
|
+
adapter = loadAdapter('cordova');
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
adapter = loadAdapter();
|
|
104
|
+
}
|
|
151
105
|
}
|
|
152
106
|
if (typeof initOptions.useNonce !== 'undefined') {
|
|
153
|
-
|
|
107
|
+
useNonce = initOptions.useNonce;
|
|
154
108
|
}
|
|
155
109
|
if (typeof initOptions.checkLoginIframe !== 'undefined') {
|
|
156
|
-
|
|
110
|
+
loginIframe.enable = initOptions.checkLoginIframe;
|
|
157
111
|
}
|
|
158
112
|
if (initOptions.checkLoginIframeInterval) {
|
|
159
|
-
|
|
113
|
+
loginIframe.interval = initOptions.checkLoginIframeInterval;
|
|
160
114
|
}
|
|
161
115
|
if (initOptions.onLoad === 'login-required') {
|
|
162
|
-
|
|
116
|
+
kc.loginRequired = true;
|
|
163
117
|
}
|
|
164
118
|
if (initOptions.responseMode) {
|
|
165
119
|
if (initOptions.responseMode === 'query' || initOptions.responseMode === 'fragment') {
|
|
166
|
-
|
|
120
|
+
kc.responseMode = initOptions.responseMode;
|
|
167
121
|
}
|
|
168
122
|
else {
|
|
169
|
-
throw
|
|
123
|
+
throw 'Invalid value for responseMode';
|
|
170
124
|
}
|
|
171
125
|
}
|
|
172
126
|
if (initOptions.flow) {
|
|
173
127
|
switch (initOptions.flow) {
|
|
174
128
|
case 'standard':
|
|
175
|
-
|
|
129
|
+
kc.responseType = 'code';
|
|
176
130
|
break;
|
|
177
131
|
case 'implicit':
|
|
178
|
-
|
|
132
|
+
kc.responseType = 'id_token token';
|
|
179
133
|
break;
|
|
180
134
|
case 'hybrid':
|
|
181
|
-
|
|
135
|
+
kc.responseType = 'code id_token token';
|
|
182
136
|
break;
|
|
183
137
|
default:
|
|
184
|
-
throw
|
|
138
|
+
throw 'Invalid value for flow';
|
|
185
139
|
}
|
|
186
|
-
|
|
140
|
+
kc.flow = initOptions.flow;
|
|
187
141
|
}
|
|
188
|
-
if (
|
|
189
|
-
|
|
142
|
+
if (initOptions.timeSkew != null) {
|
|
143
|
+
kc.timeSkew = initOptions.timeSkew;
|
|
190
144
|
}
|
|
191
145
|
if (initOptions.redirectUri) {
|
|
192
|
-
|
|
146
|
+
kc.redirectUri = initOptions.redirectUri;
|
|
193
147
|
}
|
|
194
148
|
if (initOptions.silentCheckSsoRedirectUri) {
|
|
195
|
-
|
|
149
|
+
kc.silentCheckSsoRedirectUri = initOptions.silentCheckSsoRedirectUri;
|
|
196
150
|
}
|
|
197
151
|
if (typeof initOptions.silentCheckSsoFallback === 'boolean') {
|
|
198
|
-
|
|
152
|
+
kc.silentCheckSsoFallback = initOptions.silentCheckSsoFallback;
|
|
153
|
+
}
|
|
154
|
+
else {
|
|
155
|
+
kc.silentCheckSsoFallback = true;
|
|
199
156
|
}
|
|
200
|
-
if (typeof initOptions.pkceMethod !==
|
|
201
|
-
if (initOptions.pkceMethod !==
|
|
157
|
+
if (typeof initOptions.pkceMethod !== "undefined") {
|
|
158
|
+
if (initOptions.pkceMethod !== "S256" && initOptions.pkceMethod !== false) {
|
|
202
159
|
throw new TypeError(`Invalid value for pkceMethod', expected 'S256' or false but got ${initOptions.pkceMethod}.`);
|
|
203
160
|
}
|
|
204
|
-
|
|
161
|
+
kc.pkceMethod = initOptions.pkceMethod;
|
|
162
|
+
}
|
|
163
|
+
else {
|
|
164
|
+
kc.pkceMethod = "S256";
|
|
205
165
|
}
|
|
206
166
|
if (typeof initOptions.enableLogging === 'boolean') {
|
|
207
|
-
|
|
167
|
+
kc.enableLogging = initOptions.enableLogging;
|
|
168
|
+
}
|
|
169
|
+
else {
|
|
170
|
+
kc.enableLogging = false;
|
|
208
171
|
}
|
|
209
172
|
if (initOptions.logoutMethod === 'POST') {
|
|
210
|
-
|
|
173
|
+
kc.logoutMethod = 'POST';
|
|
174
|
+
}
|
|
175
|
+
else {
|
|
176
|
+
kc.logoutMethod = 'GET';
|
|
211
177
|
}
|
|
212
178
|
if (typeof initOptions.scope === 'string') {
|
|
213
|
-
|
|
179
|
+
kc.scope = initOptions.scope;
|
|
214
180
|
}
|
|
215
181
|
if (typeof initOptions.acrValues === 'string') {
|
|
216
|
-
|
|
182
|
+
kc.acrValues = initOptions.acrValues;
|
|
217
183
|
}
|
|
218
184
|
if (typeof initOptions.messageReceiveTimeout === 'number' && initOptions.messageReceiveTimeout > 0) {
|
|
219
|
-
|
|
220
|
-
}
|
|
221
|
-
await __classPrivateFieldGet(this, _TideCloak_instances, "m", _TideCloak_loadConfig).call(this);
|
|
222
|
-
await __classPrivateFieldGet(this, _TideCloak_instances, "m", _TideCloak_check3pCookiesSupported).call(this);
|
|
223
|
-
await __classPrivateFieldGet(this, _TideCloak_instances, "m", _TideCloak_processInit).call(this, initOptions);
|
|
224
|
-
(_a = this.onReady) === null || _a === void 0 ? void 0 : _a.call(this, this.authenticated);
|
|
225
|
-
return this.authenticated;
|
|
226
|
-
}
|
|
227
|
-
;
|
|
228
|
-
/**
|
|
229
|
-
* @param {KeycloakLoginOptions} [options]
|
|
230
|
-
* @returns {Promise<void>}
|
|
231
|
-
*/
|
|
232
|
-
login(options) {
|
|
233
|
-
return __classPrivateFieldGet(this, _TideCloak_adapter, "f").login(options);
|
|
234
|
-
}
|
|
235
|
-
/**
|
|
236
|
-
* Ensure the access token is valid, refreshing if needed.
|
|
237
|
-
* @returns {Promise<void>}
|
|
238
|
-
*/
|
|
239
|
-
async ensureTokenReady() {
|
|
240
|
-
if (!this.tokenParsed)
|
|
241
|
-
return;
|
|
242
|
-
if (this.isTokenExpired()) {
|
|
243
|
-
await this.updateToken(-1);
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
/**
|
|
247
|
-
* @param {KeycloakLoginOptions} [options]
|
|
248
|
-
* @returns {Promise<string>}
|
|
249
|
-
*/
|
|
250
|
-
async createLoginUrl(options) {
|
|
251
|
-
const state = createUUID();
|
|
252
|
-
const nonce = createUUID();
|
|
253
|
-
const redirectUri = __classPrivateFieldGet(this, _TideCloak_adapter, "f").redirectUri(options);
|
|
254
|
-
/** @type {CallbackState} */
|
|
255
|
-
const callbackState = {
|
|
256
|
-
state,
|
|
257
|
-
nonce,
|
|
258
|
-
redirectUri,
|
|
259
|
-
loginOptions: options
|
|
260
|
-
};
|
|
261
|
-
if (options === null || options === void 0 ? void 0 : options.prompt) {
|
|
262
|
-
callbackState.prompt = options.prompt;
|
|
263
|
-
}
|
|
264
|
-
const url = (options === null || options === void 0 ? void 0 : options.action) === 'register'
|
|
265
|
-
? this.endpoints.register()
|
|
266
|
-
: this.endpoints.authorize();
|
|
267
|
-
let scope = (options === null || options === void 0 ? void 0 : options.scope) || this.scope;
|
|
268
|
-
const scopeValues = scope ? scope.split(' ') : [];
|
|
269
|
-
// Ensure the 'openid' scope is always included.
|
|
270
|
-
if (!scopeValues.includes('openid')) {
|
|
271
|
-
scopeValues.unshift('openid');
|
|
272
|
-
}
|
|
273
|
-
scope = scopeValues.join(' ');
|
|
274
|
-
const params = new URLSearchParams([
|
|
275
|
-
['client_id', /** @type {string} */ (this.clientId)],
|
|
276
|
-
// The endpoint URI MUST NOT include a fragment component.
|
|
277
|
-
// https://datatracker.ietf.org/doc/html/rfc6749#section-3.1.2
|
|
278
|
-
['redirect_uri', stripHash(redirectUri)],
|
|
279
|
-
['state', state],
|
|
280
|
-
['response_mode', this.responseMode],
|
|
281
|
-
['response_type', this.responseType],
|
|
282
|
-
['scope', scope]
|
|
283
|
-
]);
|
|
284
|
-
if (__classPrivateFieldGet(this, _TideCloak_useNonce, "f")) {
|
|
285
|
-
params.append('nonce', nonce);
|
|
286
|
-
}
|
|
287
|
-
if (options === null || options === void 0 ? void 0 : options.prompt) {
|
|
288
|
-
params.append('prompt', options.prompt);
|
|
289
|
-
}
|
|
290
|
-
if (typeof (options === null || options === void 0 ? void 0 : options.maxAge) === 'number') {
|
|
291
|
-
params.append('max_age', options.maxAge.toString());
|
|
292
|
-
}
|
|
293
|
-
if (options === null || options === void 0 ? void 0 : options.loginHint) {
|
|
294
|
-
params.append('login_hint', options.loginHint);
|
|
295
|
-
}
|
|
296
|
-
if (options === null || options === void 0 ? void 0 : options.idpHint) {
|
|
297
|
-
params.append('kc_idp_hint', options.idpHint);
|
|
298
|
-
}
|
|
299
|
-
if ((options === null || options === void 0 ? void 0 : options.action) && options.action !== 'register') {
|
|
300
|
-
params.append('kc_action', options.action);
|
|
301
|
-
}
|
|
302
|
-
if (options === null || options === void 0 ? void 0 : options.locale) {
|
|
303
|
-
params.append('ui_locales', options.locale);
|
|
304
|
-
}
|
|
305
|
-
if (options === null || options === void 0 ? void 0 : options.acr) {
|
|
306
|
-
params.append('claims', buildClaimsParameter(options.acr));
|
|
307
|
-
}
|
|
308
|
-
if ((options === null || options === void 0 ? void 0 : options.acrValues) || this.acrValues) {
|
|
309
|
-
params.append('acr_values', options.acrValues || this.acrValues);
|
|
310
|
-
}
|
|
311
|
-
if (this.pkceMethod) {
|
|
312
|
-
try {
|
|
313
|
-
const codeVerifier = generateCodeVerifier(96);
|
|
314
|
-
const pkceChallenge = await generatePkceChallenge(this.pkceMethod, codeVerifier);
|
|
315
|
-
callbackState.pkceCodeVerifier = codeVerifier;
|
|
316
|
-
params.append('code_challenge', pkceChallenge);
|
|
317
|
-
params.append('code_challenge_method', this.pkceMethod);
|
|
318
|
-
}
|
|
319
|
-
catch (error) {
|
|
320
|
-
throw new Error('Failed to generate PKCE challenge.', { cause: error });
|
|
321
|
-
}
|
|
322
|
-
}
|
|
323
|
-
__classPrivateFieldGet(this, _TideCloak_callbackStorage, "f").add(callbackState);
|
|
324
|
-
return `${url}?${params.toString()}`;
|
|
325
|
-
}
|
|
326
|
-
/**
|
|
327
|
-
* @param {KeycloakLogoutOptions} [options]
|
|
328
|
-
* @returns {Promise<void>}
|
|
329
|
-
*/
|
|
330
|
-
logout(options) {
|
|
331
|
-
return __classPrivateFieldGet(this, _TideCloak_adapter, "f").logout(options);
|
|
332
|
-
}
|
|
333
|
-
/**
|
|
334
|
-
* @param {KeycloakLogoutOptions} [options]
|
|
335
|
-
* @returns {string}
|
|
336
|
-
*/
|
|
337
|
-
createLogoutUrl(options) {
|
|
338
|
-
var _a;
|
|
339
|
-
const logoutMethod = (_a = options === null || options === void 0 ? void 0 : options.logoutMethod) !== null && _a !== void 0 ? _a : this.logoutMethod;
|
|
340
|
-
const url = this.endpoints.logout();
|
|
341
|
-
if (logoutMethod === 'POST') {
|
|
342
|
-
return url;
|
|
343
|
-
}
|
|
344
|
-
const params = new URLSearchParams([
|
|
345
|
-
['client_id', /** @type {string} */ (this.clientId)],
|
|
346
|
-
['post_logout_redirect_uri', __classPrivateFieldGet(this, _TideCloak_adapter, "f").redirectUri(options)]
|
|
347
|
-
]);
|
|
348
|
-
if (this.idToken) {
|
|
349
|
-
params.append('id_token_hint', this.idToken);
|
|
350
|
-
}
|
|
351
|
-
return `${url}?${params.toString()}`;
|
|
352
|
-
}
|
|
353
|
-
/**
|
|
354
|
-
* @param {KeycloakRegisterOptions} [options]
|
|
355
|
-
* @returns {Promise<void>}
|
|
356
|
-
*/
|
|
357
|
-
register(options) {
|
|
358
|
-
return __classPrivateFieldGet(this, _TideCloak_adapter, "f").register(options);
|
|
359
|
-
}
|
|
360
|
-
/**
|
|
361
|
-
* @param {KeycloakRegisterOptions} [options]
|
|
362
|
-
* @returns {Promise<string>}
|
|
363
|
-
*/
|
|
364
|
-
createRegisterUrl(options) {
|
|
365
|
-
return this.createLoginUrl({ ...options, action: 'register' });
|
|
366
|
-
}
|
|
367
|
-
/**
|
|
368
|
-
* @param {KeycloakAccountOptions} [options]
|
|
369
|
-
* @returns {string}
|
|
370
|
-
*/
|
|
371
|
-
createAccountUrl(options) {
|
|
372
|
-
const url = __classPrivateFieldGet(this, _TideCloak_instances, "m", _TideCloak_getRealmUrl).call(this);
|
|
373
|
-
if (!url) {
|
|
374
|
-
throw new Error('Unable to create account URL, make sure the adapter is not configured using a generic OIDC provider.');
|
|
375
|
-
}
|
|
376
|
-
const params = new URLSearchParams([
|
|
377
|
-
['referrer', /** @type {string} */ (this.clientId)],
|
|
378
|
-
['referrer_uri', __classPrivateFieldGet(this, _TideCloak_adapter, "f").redirectUri(options)]
|
|
379
|
-
]);
|
|
380
|
-
return `${url}/account?${params.toString()}`;
|
|
381
|
-
}
|
|
382
|
-
/**
|
|
383
|
-
* @returns {Promise<void>}
|
|
384
|
-
*/
|
|
385
|
-
accountManagement() {
|
|
386
|
-
return __classPrivateFieldGet(this, _TideCloak_adapter, "f").accountManagement();
|
|
387
|
-
}
|
|
388
|
-
/**
|
|
389
|
-
* @param {string} role
|
|
390
|
-
* @returns {boolean}
|
|
391
|
-
*/
|
|
392
|
-
hasRealmRole(role) {
|
|
393
|
-
const access = this.realmAccess;
|
|
394
|
-
return !!access && access.roles.indexOf(role) >= 0;
|
|
395
|
-
}
|
|
396
|
-
/**
|
|
397
|
-
* @param {string} role
|
|
398
|
-
* @param {string} [resource]
|
|
399
|
-
* @returns {boolean}
|
|
400
|
-
*/
|
|
401
|
-
hasResourceRole(role, resource) {
|
|
402
|
-
if (!this.resourceAccess) {
|
|
403
|
-
return false;
|
|
185
|
+
kc.messageReceiveTimeout = initOptions.messageReceiveTimeout;
|
|
404
186
|
}
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
})
|
|
421
|
-
|
|
422
|
-
}
|
|
423
|
-
/**
|
|
424
|
-
* @returns {Promise<KeycloakUserInfo>}
|
|
425
|
-
*/
|
|
426
|
-
async loadUserInfo() {
|
|
427
|
-
const url = this.endpoints.userinfo();
|
|
428
|
-
/** @type {KeycloakUserInfo} */
|
|
429
|
-
const userInfo = await fetchJSON(url, {
|
|
430
|
-
headers: [buildAuthorizationHeader(this.token)]
|
|
187
|
+
else {
|
|
188
|
+
kc.messageReceiveTimeout = 10000;
|
|
189
|
+
}
|
|
190
|
+
if (!kc.responseMode) {
|
|
191
|
+
kc.responseMode = 'fragment';
|
|
192
|
+
}
|
|
193
|
+
if (!kc.responseType) {
|
|
194
|
+
kc.responseType = 'code';
|
|
195
|
+
kc.flow = 'standard';
|
|
196
|
+
}
|
|
197
|
+
var promise = createPromise();
|
|
198
|
+
var initPromise = createPromise();
|
|
199
|
+
initPromise.promise.then(function () {
|
|
200
|
+
kc.onReady && kc.onReady(kc.authenticated);
|
|
201
|
+
promise.setSuccess(kc.authenticated);
|
|
202
|
+
}).catch(function (error) {
|
|
203
|
+
promise.setError(error);
|
|
431
204
|
});
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
*/
|
|
438
|
-
isTokenExpired(minValidity) {
|
|
439
|
-
if (!this.tokenParsed || (!this.refreshToken && this.flow !== 'implicit')) {
|
|
440
|
-
throw new Error('Not authenticated');
|
|
441
|
-
}
|
|
442
|
-
if (this.timeSkew == null) {
|
|
443
|
-
__classPrivateFieldGet(this, _TideCloak_logInfo, "f").call(this, '[TIDECLOAK] Unable to determine if token is expired as timeskew is not set');
|
|
444
|
-
return true;
|
|
445
|
-
}
|
|
446
|
-
if (typeof this.tokenParsed.exp !== 'number') {
|
|
447
|
-
return false;
|
|
448
|
-
}
|
|
449
|
-
let expiresIn = this.tokenParsed.exp - Math.ceil(new Date().getTime() / 1000) + this.timeSkew;
|
|
450
|
-
if (minValidity) {
|
|
451
|
-
if (isNaN(minValidity)) {
|
|
452
|
-
throw new Error('Invalid minValidity');
|
|
453
|
-
}
|
|
454
|
-
expiresIn -= minValidity;
|
|
455
|
-
}
|
|
456
|
-
return expiresIn < 0;
|
|
457
|
-
}
|
|
458
|
-
/**
|
|
459
|
-
* Matches Keycloak: minValidity is optional.
|
|
460
|
-
* @param {number} [minValidity]
|
|
461
|
-
* @returns {Promise<boolean>}
|
|
462
|
-
*/
|
|
463
|
-
async updateToken(minValidity) {
|
|
464
|
-
var _a, _b;
|
|
465
|
-
if (!this.refreshToken) {
|
|
466
|
-
throw new Error('Unable to update token, no refresh token available.');
|
|
467
|
-
}
|
|
468
|
-
minValidity = minValidity || 5;
|
|
469
|
-
if (__classPrivateFieldGet(this, _TideCloak_loginIframe, "f").enable) {
|
|
470
|
-
await __classPrivateFieldGet(this, _TideCloak_instances, "m", _TideCloak_checkLoginIframe).call(this);
|
|
471
|
-
}
|
|
472
|
-
let refreshToken = false;
|
|
473
|
-
if (minValidity === -1) {
|
|
474
|
-
refreshToken = true;
|
|
475
|
-
__classPrivateFieldGet(this, _TideCloak_logInfo, "f").call(this, '[TIDECLOAK] Refreshing token: forced refresh');
|
|
476
|
-
}
|
|
477
|
-
else if (!this.tokenParsed || this.isTokenExpired(minValidity)) {
|
|
478
|
-
refreshToken = true;
|
|
479
|
-
__classPrivateFieldGet(this, _TideCloak_logInfo, "f").call(this, '[TIDECLOAK] Refreshing token: token expired');
|
|
480
|
-
}
|
|
481
|
-
if (!refreshToken) {
|
|
482
|
-
return false;
|
|
483
|
-
}
|
|
484
|
-
/** @type {PromiseWithResolvers<boolean>} */
|
|
485
|
-
const { promise, resolve, reject } = Promise.withResolvers();
|
|
486
|
-
__classPrivateFieldGet(this, _TideCloak_refreshQueue, "f").push({ resolve, reject });
|
|
487
|
-
if (__classPrivateFieldGet(this, _TideCloak_refreshQueue, "f").length === 1) {
|
|
488
|
-
const url = this.endpoints.token();
|
|
489
|
-
let timeLocal = new Date().getTime();
|
|
490
|
-
try {
|
|
491
|
-
const response = await fetchRefreshToken(url, this.refreshToken, /** @type {string} */ (this.clientId));
|
|
492
|
-
__classPrivateFieldGet(this, _TideCloak_logInfo, "f").call(this, '[TIDECLOAK] Token refreshed');
|
|
493
|
-
timeLocal = (timeLocal + new Date().getTime()) / 2;
|
|
494
|
-
__classPrivateFieldGet(this, _TideCloak_instances, "m", _TideCloak_setToken).call(this, response.access_token, response.refresh_token, response.id_token, timeLocal, response.doken);
|
|
495
|
-
(_a = this.onAuthRefreshSuccess) === null || _a === void 0 ? void 0 : _a.call(this);
|
|
496
|
-
for (let p = __classPrivateFieldGet(this, _TideCloak_refreshQueue, "f").pop(); p != null; p = __classPrivateFieldGet(this, _TideCloak_refreshQueue, "f").pop()) {
|
|
497
|
-
p.resolve(true);
|
|
498
|
-
}
|
|
499
|
-
}
|
|
500
|
-
catch (error) {
|
|
501
|
-
__classPrivateFieldGet(this, _TideCloak_logWarn, "f").call(this, '[TIDECLOAK] Failed to refresh token');
|
|
502
|
-
if (error instanceof NetworkError && error.response.status === 400) {
|
|
503
|
-
this.clearToken();
|
|
205
|
+
var configPromise = loadConfig();
|
|
206
|
+
function onLoad() {
|
|
207
|
+
var doLogin = function (prompt) {
|
|
208
|
+
if (!prompt) {
|
|
209
|
+
options.prompt = 'none';
|
|
504
210
|
}
|
|
505
|
-
(
|
|
506
|
-
|
|
507
|
-
p.reject(error);
|
|
211
|
+
if (initOptions.locale) {
|
|
212
|
+
options.locale = initOptions.locale;
|
|
508
213
|
}
|
|
214
|
+
kc.login(options).then(function () {
|
|
215
|
+
initPromise.setSuccess();
|
|
216
|
+
}).catch(function (error) {
|
|
217
|
+
initPromise.setError(error);
|
|
218
|
+
});
|
|
219
|
+
};
|
|
220
|
+
var checkSsoSilently = async function () {
|
|
221
|
+
var ifrm = document.createElement("iframe");
|
|
222
|
+
var src = await kc.createLoginUrl({ prompt: 'none', redirectUri: kc.silentCheckSsoRedirectUri });
|
|
223
|
+
ifrm.setAttribute("src", src);
|
|
224
|
+
ifrm.setAttribute("sandbox", "allow-storage-access-by-user-activation allow-scripts allow-same-origin");
|
|
225
|
+
ifrm.setAttribute("title", "keycloak-silent-check-sso");
|
|
226
|
+
ifrm.style.display = "none";
|
|
227
|
+
document.body.appendChild(ifrm);
|
|
228
|
+
var messageCallback = function (event) {
|
|
229
|
+
if (event.origin !== window.location.origin || ifrm.contentWindow !== event.source) {
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
var oauth = parseCallback(event.data);
|
|
233
|
+
processCallback(oauth, initPromise);
|
|
234
|
+
document.body.removeChild(ifrm);
|
|
235
|
+
window.removeEventListener("message", messageCallback);
|
|
236
|
+
};
|
|
237
|
+
window.addEventListener("message", messageCallback);
|
|
238
|
+
};
|
|
239
|
+
var options = {};
|
|
240
|
+
switch (initOptions.onLoad) {
|
|
241
|
+
case 'check-sso':
|
|
242
|
+
if (loginIframe.enable) {
|
|
243
|
+
setupCheckLoginIframe().then(function () {
|
|
244
|
+
checkLoginIframe().then(function (unchanged) {
|
|
245
|
+
if (!unchanged) {
|
|
246
|
+
kc.silentCheckSsoRedirectUri ? checkSsoSilently() : doLogin(false);
|
|
247
|
+
}
|
|
248
|
+
else {
|
|
249
|
+
initPromise.setSuccess();
|
|
250
|
+
}
|
|
251
|
+
}).catch(function (error) {
|
|
252
|
+
initPromise.setError(error);
|
|
253
|
+
});
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
else {
|
|
257
|
+
kc.silentCheckSsoRedirectUri ? checkSsoSilently() : doLogin(false);
|
|
258
|
+
}
|
|
259
|
+
break;
|
|
260
|
+
case 'login-required':
|
|
261
|
+
doLogin(true);
|
|
262
|
+
break;
|
|
263
|
+
default:
|
|
264
|
+
throw 'Invalid value for onLoad';
|
|
509
265
|
}
|
|
510
266
|
}
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
if (this.token) {
|
|
516
|
-
__classPrivateFieldGet(this, _TideCloak_instances, "m", _TideCloak_setToken).call(this);
|
|
517
|
-
(_a = this.onAuthLogout) === null || _a === void 0 ? void 0 : _a.call(this);
|
|
518
|
-
if (this.loginRequired) {
|
|
519
|
-
this.login();
|
|
267
|
+
function processInit() {
|
|
268
|
+
var callback = parseCallback(window.location.href);
|
|
269
|
+
if (callback) {
|
|
270
|
+
window.history.replaceState(window.history.state, null, callback.newUrl);
|
|
520
271
|
}
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
return this.doken;
|
|
545
|
-
},
|
|
546
|
-
requireReloginCallback: async () => {
|
|
547
|
-
await this.login({
|
|
548
|
-
idpHint: 'tide',
|
|
549
|
-
prompt: 'login',
|
|
550
|
-
redirectUri: window.location.href
|
|
272
|
+
if (callback && callback.valid) {
|
|
273
|
+
return setupCheckLoginIframe().then(function () {
|
|
274
|
+
processCallback(callback, initPromise);
|
|
275
|
+
}).catch(function (error) {
|
|
276
|
+
initPromise.setError(error);
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
if (initOptions.token && initOptions.refreshToken) {
|
|
280
|
+
setToken(initOptions.token, initOptions.refreshToken, initOptions.idToken);
|
|
281
|
+
if (loginIframe.enable) {
|
|
282
|
+
setupCheckLoginIframe().then(function () {
|
|
283
|
+
checkLoginIframe().then(function (unchanged) {
|
|
284
|
+
if (unchanged) {
|
|
285
|
+
kc.onAuthSuccess && kc.onAuthSuccess();
|
|
286
|
+
initPromise.setSuccess();
|
|
287
|
+
scheduleCheckIframe();
|
|
288
|
+
}
|
|
289
|
+
else {
|
|
290
|
+
initPromise.setSuccess();
|
|
291
|
+
}
|
|
292
|
+
}).catch(function (error) {
|
|
293
|
+
initPromise.setError(error);
|
|
294
|
+
});
|
|
551
295
|
});
|
|
552
296
|
}
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
this.approvalEnclave = new ApprovalEnclaveNew({
|
|
566
|
-
homeOrkOrigin: this.dokenParsed['t.uho'],
|
|
567
|
-
signed_client_origin: __classPrivateFieldGet(this, _TideCloak_config, "f")['clientOriginAuth'],
|
|
568
|
-
vendorId: __classPrivateFieldGet(this, _TideCloak_config, "f").vendorId,
|
|
569
|
-
voucherURL: __classPrivateFieldGet(this, _TideCloak_instances, "m", _TideCloak_getVoucherUrl).call(this)
|
|
570
|
-
}).init({
|
|
571
|
-
doken: this.doken,
|
|
572
|
-
dokenRefreshCallback: async () => {
|
|
573
|
-
await this.ensureTokenReady();
|
|
574
|
-
if (!this.doken)
|
|
575
|
-
throw new Error('[TIDECLOAK] No doken found');
|
|
576
|
-
return this.doken;
|
|
577
|
-
},
|
|
578
|
-
requireReloginCallback: async () => {
|
|
579
|
-
await this.login({
|
|
580
|
-
idpHint: 'tide',
|
|
581
|
-
prompt: 'login',
|
|
582
|
-
redirectUri: window.location.href
|
|
297
|
+
else {
|
|
298
|
+
kc.updateToken(-1).then(function () {
|
|
299
|
+
kc.onAuthSuccess && kc.onAuthSuccess();
|
|
300
|
+
initPromise.setSuccess();
|
|
301
|
+
}).catch(function (error) {
|
|
302
|
+
kc.onAuthError && kc.onAuthError();
|
|
303
|
+
if (initOptions.onLoad) {
|
|
304
|
+
onLoad();
|
|
305
|
+
}
|
|
306
|
+
else {
|
|
307
|
+
initPromise.setError(error);
|
|
308
|
+
}
|
|
583
309
|
});
|
|
584
310
|
}
|
|
311
|
+
}
|
|
312
|
+
else if (initOptions.onLoad) {
|
|
313
|
+
onLoad();
|
|
314
|
+
}
|
|
315
|
+
else {
|
|
316
|
+
initPromise.setSuccess();
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
configPromise.then(function () {
|
|
320
|
+
check3pCookiesSupported()
|
|
321
|
+
.then(processInit)
|
|
322
|
+
.catch(function (error) {
|
|
323
|
+
promise.setError(error);
|
|
585
324
|
});
|
|
325
|
+
});
|
|
326
|
+
configPromise.catch(function (error) {
|
|
327
|
+
promise.setError(error);
|
|
328
|
+
});
|
|
329
|
+
return promise.promise;
|
|
330
|
+
};
|
|
331
|
+
kc.login = function (options) {
|
|
332
|
+
return adapter.login(options);
|
|
333
|
+
};
|
|
334
|
+
kc.ensureTokenReady = async function () {
|
|
335
|
+
if (kc.isTokenExpired()) {
|
|
336
|
+
await kc.updateToken(-1);
|
|
586
337
|
}
|
|
587
|
-
}
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
*/
|
|
593
|
-
async encrypt(toEncrypt) {
|
|
594
|
-
await this.ensureTokenReady();
|
|
338
|
+
};
|
|
339
|
+
// MODIFIED: Added role-based encryption functionality.
|
|
340
|
+
kc.encrypt = async function (toEncrypt) {
|
|
341
|
+
await kc.ensureTokenReady();
|
|
342
|
+
// Check config
|
|
595
343
|
if (!Array.isArray(toEncrypt)) {
|
|
596
|
-
throw
|
|
344
|
+
throw 'Pass array as parameter';
|
|
597
345
|
}
|
|
598
|
-
|
|
599
|
-
|
|
346
|
+
// Check user authenticated
|
|
347
|
+
if (!kc.tokenParsed) {
|
|
348
|
+
throw 'Not authenticated';
|
|
600
349
|
}
|
|
601
|
-
const dataToSend = toEncrypt.map(
|
|
350
|
+
const dataToSend = toEncrypt.map(e => {
|
|
602
351
|
if (!isObject(e))
|
|
603
|
-
throw
|
|
604
|
-
for (const property of [
|
|
352
|
+
throw 'All entries must be an object to encrypt';
|
|
353
|
+
for (const property of ["data", "tags"]) {
|
|
605
354
|
if (!e[property]) {
|
|
606
355
|
throw new Error(`The configuration object is missing the required '${property}' property.`);
|
|
607
356
|
}
|
|
608
357
|
}
|
|
609
358
|
if (!Array.isArray(e.tags))
|
|
610
|
-
throw
|
|
611
|
-
if (typeof e.data !==
|
|
612
|
-
throw
|
|
613
|
-
|
|
359
|
+
throw 'tags must be provided as a string array in object to encrypt';
|
|
360
|
+
if (typeof e.data !== "string" && !(e.data instanceof Uint8Array))
|
|
361
|
+
throw 'data must be provded as string or Uint8Array in object to encrypt';
|
|
362
|
+
// Check that the user has the roles required to encrypt the datas
|
|
614
363
|
for (const tag of e.tags) {
|
|
615
|
-
if (typeof tag !==
|
|
616
|
-
throw
|
|
617
|
-
|
|
364
|
+
if (typeof tag !== "string")
|
|
365
|
+
throw "tags must be provided as an array of strings";
|
|
366
|
+
var tagAccess = kc.hasRealmRole("_tide_" + tag + ".selfencrypt");
|
|
618
367
|
if (!tagAccess)
|
|
619
|
-
throw
|
|
368
|
+
throw `'User has not been given any access to '${tag}'`;
|
|
620
369
|
}
|
|
621
370
|
return {
|
|
622
|
-
data: typeof e.data ===
|
|
371
|
+
data: typeof e.data === "string" ? StringToUint8Array(e.data) : e.data, // convert data to byte array or leave as is if its already a byte array
|
|
623
372
|
tags: e.tags,
|
|
624
|
-
isRaw: typeof e.data ===
|
|
373
|
+
isRaw: typeof e.data === "string" ? false : true // indicate whether this piece of data was encrypted raw or not
|
|
625
374
|
};
|
|
626
375
|
});
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
376
|
+
kc.initEnclave();
|
|
377
|
+
// Now lets actually encrypt
|
|
378
|
+
// Construct Tide serialized data payloads
|
|
379
|
+
return (await kc.requestEnclave.encrypt(dataToSend)).map((e, i) => dataToSend[i].isRaw ? e : bytesToBase64(e)); // return a byte array cipher if encrypted as byte array, or a string cipher if encrypted as a string
|
|
380
|
+
};
|
|
381
|
+
function StringToUint8Array(string) {
|
|
382
|
+
const enc = new TextEncoder();
|
|
383
|
+
return enc.encode(string);
|
|
384
|
+
}
|
|
385
|
+
function StringFromUint8Array(bytes) {
|
|
386
|
+
const decoder = new TextDecoder('utf-8');
|
|
387
|
+
return decoder.decode(bytes);
|
|
388
|
+
}
|
|
389
|
+
kc.initEnclave = function () {
|
|
390
|
+
if (!kc.doken)
|
|
391
|
+
throw '[TIDECLOAK] No doken found';
|
|
392
|
+
if (!kc.tokenParsed)
|
|
393
|
+
throw '[TIDECLOAK] Token not parsed';
|
|
394
|
+
// Now lets actually encrypt
|
|
395
|
+
if (!kc.requestEnclave) {
|
|
396
|
+
kc.requestEnclave = new RequestEnclave({
|
|
397
|
+
homeOrkOrigin: kc.dokenParsed["t.uho"],
|
|
398
|
+
signed_client_origin: config['clientOriginAuth'],
|
|
399
|
+
vendorId: config.vendorId,
|
|
400
|
+
voucherURL: getVoucherUrl()
|
|
401
|
+
}).init({
|
|
402
|
+
doken: kc.doken,
|
|
403
|
+
dokenRefreshCallback: async () => {
|
|
404
|
+
await kc.ensureTokenReady();
|
|
405
|
+
if (!kc.doken)
|
|
406
|
+
throw '[TIDECLOAK] No doken found';
|
|
407
|
+
return kc.doken;
|
|
408
|
+
},
|
|
409
|
+
requireReloginCallback: async () => {
|
|
410
|
+
kc.login({
|
|
411
|
+
idpHint: 'tide', // the “alias” of the IdP you’ve configured in the realm
|
|
412
|
+
prompt: 'login', // forces them to actually re-enter credentials
|
|
413
|
+
redirectUri: window.location.href // send them back to the exact same URL
|
|
414
|
+
});
|
|
415
|
+
}
|
|
416
|
+
});
|
|
417
|
+
}
|
|
418
|
+
};
|
|
419
|
+
// MODIFIED: Added Tide-based micro-vouchers.
|
|
420
|
+
function getVoucherUrl() {
|
|
421
|
+
if (!kc.tokenParsed)
|
|
422
|
+
throw 'User authentication required to access voucher service';
|
|
423
|
+
const sid = kc.tokenParsed["sid"];
|
|
424
|
+
return getRealmUrl() + '/tidevouchers/fromUserSession?sessionId=' + sid;
|
|
425
|
+
}
|
|
426
|
+
// MODIFIED: Added role-based decryption functionality.
|
|
427
|
+
kc.decrypt = async function (toDecrypt) {
|
|
428
|
+
await kc.ensureTokenReady();
|
|
429
|
+
// Check config
|
|
669
430
|
if (!Array.isArray(toDecrypt)) {
|
|
670
|
-
throw
|
|
431
|
+
throw 'Pass array as parameter';
|
|
671
432
|
}
|
|
672
|
-
|
|
673
|
-
|
|
433
|
+
// Check user authenticated
|
|
434
|
+
if (!kc.tokenParsed) {
|
|
435
|
+
throw 'Not authenticated';
|
|
674
436
|
}
|
|
675
|
-
const dataToSend = toDecrypt.map(
|
|
437
|
+
const dataToSend = toDecrypt.map(e => {
|
|
676
438
|
if (!isObject(e))
|
|
677
|
-
throw
|
|
678
|
-
for (const property of [
|
|
439
|
+
throw 'All entries must be an object to decrypt';
|
|
440
|
+
for (const property of ["encrypted", "tags"]) {
|
|
679
441
|
if (!e[property]) {
|
|
680
442
|
throw new Error(`The configuration object is missing the required '${property}' property.`);
|
|
681
443
|
}
|
|
682
444
|
}
|
|
683
445
|
if (!Array.isArray(e.tags))
|
|
684
|
-
throw
|
|
685
|
-
if (typeof e.encrypted !==
|
|
686
|
-
throw
|
|
687
|
-
|
|
446
|
+
throw 'tags must be provided as a string array in object to decrypt';
|
|
447
|
+
if (typeof e.encrypted !== "string" && !(e.encrypted instanceof Uint8Array))
|
|
448
|
+
throw 'data must be provded as string or Uint8Array in object to decrypt';
|
|
449
|
+
// Check that the user has the roles required to encrypt the datas
|
|
688
450
|
for (const tag of e.tags) {
|
|
689
|
-
if (typeof tag !==
|
|
690
|
-
throw
|
|
691
|
-
|
|
451
|
+
if (typeof tag !== "string")
|
|
452
|
+
throw "tags must be provided as an array of strings";
|
|
453
|
+
var tagAccess = kc.hasRealmRole("_tide_" + tag + ".selfdecrypt");
|
|
692
454
|
if (!tagAccess)
|
|
693
|
-
throw
|
|
455
|
+
throw `'User has not been given any access to '${tag}'`;
|
|
694
456
|
}
|
|
695
457
|
return {
|
|
696
|
-
encrypted: typeof e.encrypted ===
|
|
458
|
+
encrypted: typeof e.encrypted === "string" ? base64ToBytes(e.encrypted) : e.encrypted,
|
|
697
459
|
tags: e.tags,
|
|
698
|
-
isRaw: typeof e.encrypted ===
|
|
460
|
+
isRaw: typeof e.encrypted === "string" ? false : true
|
|
699
461
|
};
|
|
700
462
|
});
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
}
|
|
706
|
-
_TideCloak_refreshQueue = new WeakMap(), _TideCloak_adapter = new WeakMap(), _TideCloak_useNonce = new WeakMap(), _TideCloak_callbackStorage = new WeakMap(), _TideCloak_logInfo = new WeakMap(), _TideCloak_logWarn = new WeakMap(), _TideCloak_loginIframe = new WeakMap(), _TideCloak_config = new WeakMap(), _TideCloak_instances = new WeakSet(), _TideCloak_loadAdapter = function _TideCloak_loadAdapter(type) {
|
|
707
|
-
if (type === 'default') {
|
|
708
|
-
return __classPrivateFieldGet(this, _TideCloak_instances, "m", _TideCloak_loadDefaultAdapter).call(this);
|
|
709
|
-
}
|
|
710
|
-
if (type === 'cordova') {
|
|
711
|
-
__classPrivateFieldGet(this, _TideCloak_loginIframe, "f").enable = false;
|
|
712
|
-
return __classPrivateFieldGet(this, _TideCloak_instances, "m", _TideCloak_loadCordovaAdapter).call(this);
|
|
713
|
-
}
|
|
714
|
-
if (type === 'cordova-native') {
|
|
715
|
-
__classPrivateFieldGet(this, _TideCloak_loginIframe, "f").enable = false;
|
|
716
|
-
return __classPrivateFieldGet(this, _TideCloak_instances, "m", _TideCloak_loadCordovaNativeAdapter).call(this);
|
|
717
|
-
}
|
|
718
|
-
throw new Error('invalid adapter type: ' + type);
|
|
719
|
-
}, _TideCloak_loadDefaultAdapter = function _TideCloak_loadDefaultAdapter() {
|
|
720
|
-
/** @type {KeycloakAdapter['redirectUri']}{} */
|
|
721
|
-
const redirectUri = (options) => {
|
|
722
|
-
return (options === null || options === void 0 ? void 0 : options.redirectUri) || this.redirectUri || globalThis.location.href;
|
|
463
|
+
kc.initEnclave();
|
|
464
|
+
// Now lets actually decrypt
|
|
465
|
+
// Construct Tide serialized data payloads
|
|
466
|
+
return (await kc.requestEnclave.decrypt(dataToSend)).map((d, i) => dataToSend[i].isRaw ? d : StringFromUint8Array(d));
|
|
723
467
|
};
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
},
|
|
758
|
-
register: async (options) => {
|
|
759
|
-
window.location.assign(await this.createRegisterUrl(options));
|
|
760
|
-
return await new Promise(() => { });
|
|
761
|
-
},
|
|
762
|
-
accountManagement: async () => {
|
|
763
|
-
const accountUrl = this.createAccountUrl();
|
|
764
|
-
if (typeof accountUrl !== 'undefined') {
|
|
765
|
-
window.location.href = accountUrl;
|
|
766
|
-
}
|
|
767
|
-
else {
|
|
768
|
-
throw new Error('Not supported by the OIDC server');
|
|
468
|
+
function generateRandomData(len) {
|
|
469
|
+
if (typeof crypto === "undefined" || typeof crypto.getRandomValues === "undefined") {
|
|
470
|
+
throw new Error("Web Crypto API is not available.");
|
|
471
|
+
}
|
|
472
|
+
return crypto.getRandomValues(new Uint8Array(len));
|
|
473
|
+
}
|
|
474
|
+
function generateCodeVerifier(len) {
|
|
475
|
+
return generateRandomString(len, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789');
|
|
476
|
+
}
|
|
477
|
+
function generateRandomString(len, alphabet) {
|
|
478
|
+
var randomData = generateRandomData(len);
|
|
479
|
+
var chars = new Array(len);
|
|
480
|
+
for (var i = 0; i < len; i++) {
|
|
481
|
+
chars[i] = alphabet.charCodeAt(randomData[i] % alphabet.length);
|
|
482
|
+
}
|
|
483
|
+
return String.fromCharCode.apply(null, chars);
|
|
484
|
+
}
|
|
485
|
+
async function generatePkceChallenge(pkceMethod, codeVerifier) {
|
|
486
|
+
if (pkceMethod !== "S256") {
|
|
487
|
+
throw new TypeError(`Invalid value for 'pkceMethod', expected 'S256' but got '${pkceMethod}'.`);
|
|
488
|
+
}
|
|
489
|
+
// hash codeVerifier, then encode as url-safe base64 without padding
|
|
490
|
+
const hashBytes = new Uint8Array(await sha256Digest(codeVerifier));
|
|
491
|
+
const encodedHash = bytesToBase64(hashBytes)
|
|
492
|
+
.replace(/\+/g, '-')
|
|
493
|
+
.replace(/\//g, '_')
|
|
494
|
+
.replace(/\=/g, '');
|
|
495
|
+
return encodedHash;
|
|
496
|
+
}
|
|
497
|
+
function buildClaimsParameter(requestedAcr) {
|
|
498
|
+
var claims = {
|
|
499
|
+
id_token: {
|
|
500
|
+
acr: requestedAcr
|
|
769
501
|
}
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
502
|
+
};
|
|
503
|
+
return JSON.stringify(claims);
|
|
504
|
+
}
|
|
505
|
+
kc.createLoginUrl = async function (options) {
|
|
506
|
+
var state = createUUID();
|
|
507
|
+
var nonce = createUUID();
|
|
508
|
+
var redirectUri = adapter.redirectUri(options);
|
|
509
|
+
var callbackState = {
|
|
510
|
+
state: state,
|
|
511
|
+
nonce: nonce,
|
|
512
|
+
redirectUri: encodeURIComponent(redirectUri),
|
|
513
|
+
loginOptions: options
|
|
514
|
+
};
|
|
515
|
+
if (options && options.prompt) {
|
|
516
|
+
callbackState.prompt = options.prompt;
|
|
517
|
+
}
|
|
518
|
+
var baseUrl;
|
|
519
|
+
if (options && options.action == 'register') {
|
|
520
|
+
baseUrl = kc.endpoints.register();
|
|
785
521
|
}
|
|
786
522
|
else {
|
|
787
|
-
|
|
523
|
+
baseUrl = kc.endpoints.authorize();
|
|
524
|
+
}
|
|
525
|
+
var scope = options && options.scope || kc.scope;
|
|
526
|
+
if (!scope) {
|
|
527
|
+
// if scope is not set, default to "openid"
|
|
528
|
+
scope = "openid";
|
|
529
|
+
}
|
|
530
|
+
else if (scope.indexOf("openid") === -1) {
|
|
531
|
+
// if openid scope is missing, prefix the given scopes with it
|
|
532
|
+
scope = "openid " + scope;
|
|
533
|
+
}
|
|
534
|
+
var url = baseUrl
|
|
535
|
+
+ '?client_id=' + encodeURIComponent(kc.clientId)
|
|
536
|
+
+ '&redirect_uri=' + encodeURIComponent(redirectUri)
|
|
537
|
+
+ '&state=' + encodeURIComponent(state)
|
|
538
|
+
+ '&response_mode=' + encodeURIComponent(kc.responseMode)
|
|
539
|
+
+ '&response_type=' + encodeURIComponent(kc.responseType)
|
|
540
|
+
+ '&scope=' + encodeURIComponent(scope);
|
|
541
|
+
if (useNonce) {
|
|
542
|
+
url = url + '&nonce=' + encodeURIComponent(nonce);
|
|
788
543
|
}
|
|
544
|
+
if (options && options.prompt) {
|
|
545
|
+
url += '&prompt=' + encodeURIComponent(options.prompt);
|
|
546
|
+
}
|
|
547
|
+
if (options && typeof options.maxAge === 'number') {
|
|
548
|
+
url += '&max_age=' + encodeURIComponent(options.maxAge);
|
|
549
|
+
}
|
|
550
|
+
if (options && options.loginHint) {
|
|
551
|
+
url += '&login_hint=' + encodeURIComponent(options.loginHint);
|
|
552
|
+
}
|
|
553
|
+
if (options && options.idpHint) {
|
|
554
|
+
url += '&kc_idp_hint=' + encodeURIComponent(options.idpHint);
|
|
555
|
+
}
|
|
556
|
+
if (options && options.action && options.action != 'register') {
|
|
557
|
+
url += '&kc_action=' + encodeURIComponent(options.action);
|
|
558
|
+
}
|
|
559
|
+
if (options && options.locale) {
|
|
560
|
+
url += '&ui_locales=' + encodeURIComponent(options.locale);
|
|
561
|
+
}
|
|
562
|
+
if (options && options.acr) {
|
|
563
|
+
var claimsParameter = buildClaimsParameter(options.acr);
|
|
564
|
+
url += '&claims=' + encodeURIComponent(claimsParameter);
|
|
565
|
+
}
|
|
566
|
+
if ((options && options.acrValues) || kc.acrValues) {
|
|
567
|
+
url += '&acr_values=' + encodeURIComponent(options.acrValues || kc.acrValues);
|
|
568
|
+
}
|
|
569
|
+
if (kc.pkceMethod) {
|
|
570
|
+
try {
|
|
571
|
+
const codeVerifier = generateCodeVerifier(96);
|
|
572
|
+
const pkceChallenge = await generatePkceChallenge(kc.pkceMethod, codeVerifier);
|
|
573
|
+
callbackState.pkceCodeVerifier = codeVerifier;
|
|
574
|
+
url += '&code_challenge=' + pkceChallenge;
|
|
575
|
+
url += '&code_challenge_method=' + kc.pkceMethod;
|
|
576
|
+
}
|
|
577
|
+
catch (error) {
|
|
578
|
+
throw new Error("Failed to generate PKCE challenge.", { cause: error });
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
callbackStorage.add(callbackState);
|
|
582
|
+
return url;
|
|
583
|
+
};
|
|
584
|
+
kc.logout = function (options) {
|
|
585
|
+
return adapter.logout(options);
|
|
789
586
|
};
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
}, {});
|
|
587
|
+
kc.createLogoutUrl = function (options) {
|
|
588
|
+
var _a;
|
|
589
|
+
const logoutMethod = (_a = options === null || options === void 0 ? void 0 : options.logoutMethod) !== null && _a !== void 0 ? _a : kc.logoutMethod;
|
|
590
|
+
if (logoutMethod === 'POST') {
|
|
591
|
+
return kc.endpoints.logout();
|
|
796
592
|
}
|
|
797
|
-
|
|
798
|
-
|
|
593
|
+
var url = kc.endpoints.logout()
|
|
594
|
+
+ '?client_id=' + encodeURIComponent(kc.clientId)
|
|
595
|
+
+ '&post_logout_redirect_uri=' + encodeURIComponent(adapter.redirectUri(options, false));
|
|
596
|
+
if (kc.idToken) {
|
|
597
|
+
url += '&id_token_hint=' + encodeURIComponent(kc.idToken);
|
|
799
598
|
}
|
|
599
|
+
return url;
|
|
800
600
|
};
|
|
801
|
-
|
|
802
|
-
return
|
|
803
|
-
options.push(optionName + '=' + cordovaOptions[optionName]);
|
|
804
|
-
return options;
|
|
805
|
-
}, []).join(',');
|
|
601
|
+
kc.register = function (options) {
|
|
602
|
+
return adapter.register(options);
|
|
806
603
|
};
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
if (userOptions && userOptions.prompt === 'none') {
|
|
811
|
-
cordovaOptions.hidden = 'yes';
|
|
604
|
+
kc.createRegisterUrl = async function (options) {
|
|
605
|
+
if (!options) {
|
|
606
|
+
options = {};
|
|
812
607
|
}
|
|
813
|
-
|
|
608
|
+
options.action = 'register';
|
|
609
|
+
return await kc.createLoginUrl(options);
|
|
814
610
|
};
|
|
815
|
-
|
|
816
|
-
|
|
611
|
+
kc.createAccountUrl = function (options) {
|
|
612
|
+
var realm = getRealmUrl();
|
|
613
|
+
var url = undefined;
|
|
614
|
+
if (typeof realm !== 'undefined') {
|
|
615
|
+
url = realm
|
|
616
|
+
+ '/account'
|
|
617
|
+
+ '?referrer=' + encodeURIComponent(kc.clientId)
|
|
618
|
+
+ '&referrer_uri=' + encodeURIComponent(adapter.redirectUri(options));
|
|
619
|
+
}
|
|
620
|
+
return url;
|
|
817
621
|
};
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
});
|
|
845
|
-
ref.addEventListener('loaderror', async (event) => {
|
|
846
|
-
if (!completed) {
|
|
847
|
-
if (event.url.indexOf(getCordovaRedirectUri()) === 0) {
|
|
848
|
-
const callback = __classPrivateFieldGet(this, _TideCloak_instances, "m", _TideCloak_parseCallback).call(this, event.url);
|
|
849
|
-
try {
|
|
850
|
-
await __classPrivateFieldGet(this, _TideCloak_instances, "m", _TideCloak_processCallback).call(this, callback);
|
|
851
|
-
resolve();
|
|
852
|
-
}
|
|
853
|
-
catch (error) {
|
|
854
|
-
reject(error);
|
|
855
|
-
}
|
|
856
|
-
closeBrowser();
|
|
857
|
-
completed = true;
|
|
858
|
-
}
|
|
859
|
-
else {
|
|
860
|
-
reject(new Error('Unable to process login.'));
|
|
861
|
-
closeBrowser();
|
|
862
|
-
}
|
|
863
|
-
}
|
|
864
|
-
});
|
|
865
|
-
ref.addEventListener('exit', function (event) {
|
|
866
|
-
if (!closed) {
|
|
867
|
-
reject(new Error('User closed the login window.'));
|
|
868
|
-
}
|
|
869
|
-
});
|
|
870
|
-
});
|
|
871
|
-
},
|
|
872
|
-
logout: async (options) => {
|
|
873
|
-
const logoutUrl = this.createLogoutUrl(options);
|
|
874
|
-
const ref = cordovaOpenWindowWrapper(logoutUrl, '_blank', 'location=no,hidden=yes,clearcache=yes');
|
|
875
|
-
let error = false;
|
|
876
|
-
ref.addEventListener('loadstart', (event) => {
|
|
877
|
-
if (event.url.indexOf(getCordovaRedirectUri()) === 0) {
|
|
878
|
-
ref.close();
|
|
622
|
+
kc.accountManagement = function () {
|
|
623
|
+
return adapter.accountManagement();
|
|
624
|
+
};
|
|
625
|
+
kc.hasRealmRole = function (role) {
|
|
626
|
+
var access = kc.realmAccess;
|
|
627
|
+
return !!access && access.roles.indexOf(role) >= 0;
|
|
628
|
+
};
|
|
629
|
+
kc.hasResourceRole = function (role, resource) {
|
|
630
|
+
if (!kc.resourceAccess) {
|
|
631
|
+
return false;
|
|
632
|
+
}
|
|
633
|
+
var access = kc.resourceAccess[resource || kc.clientId];
|
|
634
|
+
return !!access && access.roles.indexOf(role) >= 0;
|
|
635
|
+
};
|
|
636
|
+
kc.loadUserProfile = function () {
|
|
637
|
+
var url = getRealmUrl() + '/account';
|
|
638
|
+
var req = new XMLHttpRequest();
|
|
639
|
+
req.open('GET', url, true);
|
|
640
|
+
req.setRequestHeader('Accept', 'application/json');
|
|
641
|
+
req.setRequestHeader('Authorization', 'bearer ' + kc.token);
|
|
642
|
+
var promise = createPromise();
|
|
643
|
+
req.onreadystatechange = function () {
|
|
644
|
+
if (req.readyState == 4) {
|
|
645
|
+
if (req.status == 200) {
|
|
646
|
+
kc.profile = JSON.parse(req.responseText);
|
|
647
|
+
promise.setSuccess(kc.profile);
|
|
879
648
|
}
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
649
|
+
else {
|
|
650
|
+
promise.setError();
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
};
|
|
654
|
+
req.send();
|
|
655
|
+
return promise.promise;
|
|
656
|
+
};
|
|
657
|
+
kc.loadUserInfo = function () {
|
|
658
|
+
var url = kc.endpoints.userinfo();
|
|
659
|
+
var req = new XMLHttpRequest();
|
|
660
|
+
req.open('GET', url, true);
|
|
661
|
+
req.setRequestHeader('Accept', 'application/json');
|
|
662
|
+
req.setRequestHeader('Authorization', 'bearer ' + kc.token);
|
|
663
|
+
var promise = createPromise();
|
|
664
|
+
req.onreadystatechange = function () {
|
|
665
|
+
if (req.readyState == 4) {
|
|
666
|
+
if (req.status == 200) {
|
|
667
|
+
kc.userInfo = JSON.parse(req.responseText);
|
|
668
|
+
promise.setSuccess(kc.userInfo);
|
|
884
669
|
}
|
|
885
670
|
else {
|
|
886
|
-
|
|
887
|
-
ref.close();
|
|
671
|
+
promise.setError();
|
|
888
672
|
}
|
|
889
|
-
});
|
|
890
|
-
await new Promise((resolve, reject) => {
|
|
891
|
-
ref.addEventListener('exit', () => {
|
|
892
|
-
if (error) {
|
|
893
|
-
reject(new Error('User closed the login window.'));
|
|
894
|
-
}
|
|
895
|
-
else {
|
|
896
|
-
this.clearToken();
|
|
897
|
-
resolve();
|
|
898
|
-
}
|
|
899
|
-
});
|
|
900
|
-
});
|
|
901
|
-
},
|
|
902
|
-
register: async (options) => {
|
|
903
|
-
const registerUrl = await this.createRegisterUrl();
|
|
904
|
-
const cordovaOptions = createCordovaOptions(options);
|
|
905
|
-
const ref = cordovaOpenWindowWrapper(registerUrl, '_blank', cordovaOptions);
|
|
906
|
-
/** @type {Promise<void>} */
|
|
907
|
-
const promise = new Promise((resolve, reject) => {
|
|
908
|
-
ref.addEventListener('loadstart', async (event) => {
|
|
909
|
-
if (event.url.indexOf(getCordovaRedirectUri()) === 0) {
|
|
910
|
-
ref.close();
|
|
911
|
-
const oauth = __classPrivateFieldGet(this, _TideCloak_instances, "m", _TideCloak_parseCallback).call(this, event.url);
|
|
912
|
-
try {
|
|
913
|
-
await __classPrivateFieldGet(this, _TideCloak_instances, "m", _TideCloak_processCallback).call(this, oauth);
|
|
914
|
-
resolve();
|
|
915
|
-
}
|
|
916
|
-
catch (error) {
|
|
917
|
-
reject(error);
|
|
918
|
-
}
|
|
919
|
-
}
|
|
920
|
-
});
|
|
921
|
-
});
|
|
922
|
-
await promise;
|
|
923
|
-
},
|
|
924
|
-
accountManagement: async () => {
|
|
925
|
-
const accountUrl = this.createAccountUrl();
|
|
926
|
-
if (typeof accountUrl !== 'undefined') {
|
|
927
|
-
const ref = cordovaOpenWindowWrapper(accountUrl, '_blank', 'location=no');
|
|
928
|
-
ref.addEventListener('loadstart', function (event) {
|
|
929
|
-
if (event.url.indexOf(getCordovaRedirectUri()) === 0) {
|
|
930
|
-
ref.close();
|
|
931
|
-
}
|
|
932
|
-
});
|
|
933
673
|
}
|
|
934
|
-
|
|
935
|
-
|
|
674
|
+
};
|
|
675
|
+
req.send();
|
|
676
|
+
return promise.promise;
|
|
677
|
+
};
|
|
678
|
+
kc.isTokenExpired = function (minValidity) {
|
|
679
|
+
if (!kc.tokenParsed || (!kc.refreshToken && kc.flow != 'implicit')) {
|
|
680
|
+
throw 'Not authenticated';
|
|
681
|
+
}
|
|
682
|
+
if (kc.timeSkew == null) {
|
|
683
|
+
logInfo('[TIDECLOAK] Unable to determine if token is expired as timeskew is not set');
|
|
684
|
+
return true;
|
|
685
|
+
}
|
|
686
|
+
var expiresIn = kc.tokenParsed['exp'] - Math.ceil(new Date().getTime() / 1000) + kc.timeSkew;
|
|
687
|
+
if (minValidity) {
|
|
688
|
+
if (isNaN(minValidity)) {
|
|
689
|
+
throw 'Invalid minValidity';
|
|
936
690
|
}
|
|
937
|
-
|
|
938
|
-
redirectUri: () => {
|
|
939
|
-
return getCordovaRedirectUri();
|
|
691
|
+
expiresIn -= minValidity;
|
|
940
692
|
}
|
|
693
|
+
return expiresIn < 0;
|
|
941
694
|
};
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
resolve();
|
|
955
|
-
}
|
|
956
|
-
catch (error) {
|
|
957
|
-
reject(error);
|
|
958
|
-
}
|
|
959
|
-
});
|
|
960
|
-
window.cordova.plugins.browsertab.openUrl(loginUrl);
|
|
961
|
-
});
|
|
962
|
-
},
|
|
963
|
-
logout: async (options) => {
|
|
964
|
-
const logoutUrl = this.createLogoutUrl(options);
|
|
965
|
-
await new Promise((resolve) => {
|
|
966
|
-
universalLinks.subscribe('keycloak', () => {
|
|
967
|
-
universalLinks.unsubscribe('keycloak');
|
|
968
|
-
window.cordova.plugins.browsertab.close();
|
|
969
|
-
this.clearToken();
|
|
970
|
-
resolve();
|
|
971
|
-
});
|
|
972
|
-
window.cordova.plugins.browsertab.openUrl(logoutUrl);
|
|
973
|
-
});
|
|
974
|
-
},
|
|
975
|
-
register: async (options) => {
|
|
976
|
-
const registerUrl = await this.createRegisterUrl(options);
|
|
977
|
-
await new Promise((resolve, reject) => {
|
|
978
|
-
universalLinks.subscribe('keycloak', async (event) => {
|
|
979
|
-
universalLinks.unsubscribe('keycloak');
|
|
980
|
-
window.cordova.plugins.browsertab.close();
|
|
981
|
-
const oauth = __classPrivateFieldGet(this, _TideCloak_instances, "m", _TideCloak_parseCallback).call(this, event.url);
|
|
982
|
-
try {
|
|
983
|
-
await __classPrivateFieldGet(this, _TideCloak_instances, "m", _TideCloak_processCallback).call(this, oauth);
|
|
984
|
-
resolve();
|
|
985
|
-
}
|
|
986
|
-
catch (error) {
|
|
987
|
-
reject(error);
|
|
988
|
-
}
|
|
989
|
-
});
|
|
990
|
-
window.cordova.plugins.browsertab.openUrl(registerUrl);
|
|
991
|
-
});
|
|
992
|
-
},
|
|
993
|
-
accountManagement: async () => {
|
|
994
|
-
const accountUrl = this.createAccountUrl();
|
|
995
|
-
if (typeof accountUrl !== 'undefined') {
|
|
996
|
-
window.cordova.plugins.browsertab.openUrl(accountUrl);
|
|
997
|
-
}
|
|
998
|
-
else {
|
|
999
|
-
throw new Error('Not supported by the OIDC server');
|
|
695
|
+
kc.updateToken = function (minValidity) {
|
|
696
|
+
var promise = createPromise();
|
|
697
|
+
if (!kc.refreshToken) {
|
|
698
|
+
promise.setError();
|
|
699
|
+
return promise.promise;
|
|
700
|
+
}
|
|
701
|
+
minValidity = minValidity || 5;
|
|
702
|
+
var exec = function () {
|
|
703
|
+
var refreshToken = false;
|
|
704
|
+
if (minValidity == -1) {
|
|
705
|
+
refreshToken = true;
|
|
706
|
+
logInfo('[TIDECLOAK] Refreshing token: forced refresh');
|
|
1000
707
|
}
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
return options.redirectUri;
|
|
708
|
+
else if (!kc.tokenParsed || kc.isTokenExpired(minValidity)) {
|
|
709
|
+
refreshToken = true;
|
|
710
|
+
logInfo('[TIDECLOAK] Refreshing token: token expired');
|
|
1005
711
|
}
|
|
1006
|
-
|
|
1007
|
-
|
|
712
|
+
if (!refreshToken) {
|
|
713
|
+
promise.setSuccess(false);
|
|
1008
714
|
}
|
|
1009
715
|
else {
|
|
1010
|
-
|
|
716
|
+
var params = 'grant_type=refresh_token&' + 'refresh_token=' + kc.refreshToken;
|
|
717
|
+
var url = kc.endpoints.token();
|
|
718
|
+
refreshQueue.push(promise);
|
|
719
|
+
if (refreshQueue.length == 1) {
|
|
720
|
+
var req = new XMLHttpRequest();
|
|
721
|
+
req.open('POST', url, true);
|
|
722
|
+
req.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
|
|
723
|
+
req.withCredentials = true;
|
|
724
|
+
params += '&client_id=' + encodeURIComponent(kc.clientId);
|
|
725
|
+
var timeLocal = new Date().getTime();
|
|
726
|
+
req.onreadystatechange = function () {
|
|
727
|
+
if (req.readyState == 4) {
|
|
728
|
+
if (req.status == 200) {
|
|
729
|
+
logInfo('[TIDECLOAK] Token refreshed');
|
|
730
|
+
timeLocal = (timeLocal + new Date().getTime()) / 2;
|
|
731
|
+
var tokenResponse = JSON.parse(req.responseText);
|
|
732
|
+
setToken(tokenResponse['access_token'], tokenResponse['refresh_token'], tokenResponse['id_token'], timeLocal, tokenResponse['doken']);
|
|
733
|
+
kc.onAuthRefreshSuccess && kc.onAuthRefreshSuccess();
|
|
734
|
+
for (var p = refreshQueue.pop(); p != null; p = refreshQueue.pop()) {
|
|
735
|
+
p.setSuccess(true);
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
else {
|
|
739
|
+
logWarn('[TIDECLOAK] Failed to refresh token');
|
|
740
|
+
if (req.status == 400) {
|
|
741
|
+
kc.clearToken();
|
|
742
|
+
}
|
|
743
|
+
if (req.status == 500) {
|
|
744
|
+
// Check to see if error message tells us to reauthenticate the user
|
|
745
|
+
console.log("CHECKING REAUTH");
|
|
746
|
+
}
|
|
747
|
+
kc.onAuthRefreshError && kc.onAuthRefreshError();
|
|
748
|
+
for (var p = refreshQueue.pop(); p != null; p = refreshQueue.pop()) {
|
|
749
|
+
p.setError("Failed to refresh token: An unexpected HTTP error occurred while attempting to refresh the token.");
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
};
|
|
754
|
+
req.send(params);
|
|
755
|
+
}
|
|
1011
756
|
}
|
|
757
|
+
};
|
|
758
|
+
if (loginIframe.enable) {
|
|
759
|
+
var iframePromise = checkLoginIframe();
|
|
760
|
+
iframePromise.then(function () {
|
|
761
|
+
exec();
|
|
762
|
+
}).catch(function (error) {
|
|
763
|
+
promise.setError(error);
|
|
764
|
+
});
|
|
765
|
+
}
|
|
766
|
+
else {
|
|
767
|
+
exec();
|
|
1012
768
|
}
|
|
769
|
+
return promise.promise;
|
|
1013
770
|
};
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
771
|
+
kc.clearToken = function () {
|
|
772
|
+
if (kc.token) {
|
|
773
|
+
setToken(null, null, null);
|
|
774
|
+
kc.onAuthLogout && kc.onAuthLogout();
|
|
775
|
+
if (kc.loginRequired) {
|
|
776
|
+
kc.login();
|
|
777
|
+
}
|
|
778
|
+
}
|
|
779
|
+
};
|
|
780
|
+
// Add the checkThresholdRule function to the Heimdall instance.
|
|
781
|
+
// This function calls the generic threshold rule processor from the thresholdRules module.
|
|
782
|
+
kc.checkThresholdRule = function (key, idSubstring, ruleSettings, draftJson) {
|
|
783
|
+
// Process the threshold rules using the provided parameters and return the result.
|
|
784
|
+
return processThresholdRules(key, idSubstring, ruleSettings, draftJson);
|
|
785
|
+
};
|
|
786
|
+
kc.createCardanoTxDraft = function (txBody) {
|
|
787
|
+
const txBodyBytes = base64ToBytes(txBody);
|
|
788
|
+
return bytesToBase64(CreateTideMemory(txBodyBytes, txBodyBytes.length + 4));
|
|
789
|
+
};
|
|
790
|
+
kc.sign = async function (signModel, authFlow, draft, authorizers, ruleSetting, expiry) {
|
|
791
|
+
await kc.ensureTokenReady();
|
|
792
|
+
const signModelId = signModel.split(":");
|
|
793
|
+
if (signModelId.length !== 2 || !signModelId[0] || !signModelId[1]) {
|
|
794
|
+
throw "SignModel is not in the correct format. Expected format: 'ModelName:Version' (e.g. 'UserContext:1').";
|
|
795
|
+
}
|
|
796
|
+
const authFlowId = authFlow.split(":");
|
|
797
|
+
if (authFlowId.length !== 2 || !authFlowId[0] || !authFlowId[1]) {
|
|
798
|
+
throw "AuthFlow is not in the correct format. Expected format: 'ModelName:Version' (e.g. 'VRK:1').";
|
|
799
|
+
}
|
|
800
|
+
const sessKey = GenSessKey();
|
|
801
|
+
const gSessKey = GetPublic(sessKey);
|
|
802
|
+
const vvkInfo = await new NetworkClient(config.homeOrkUrl).GetKeyInfo(config.vendorId);
|
|
803
|
+
;
|
|
804
|
+
// Check user authenticated
|
|
805
|
+
if (!kc.tokenParsed) {
|
|
806
|
+
throw 'Not authenticated';
|
|
807
|
+
}
|
|
808
|
+
// Check config
|
|
809
|
+
if (!Array.isArray(authorizers)) {
|
|
810
|
+
throw 'Pass authorizers in an array!';
|
|
811
|
+
}
|
|
812
|
+
const signRequest = new BaseTideRequest(signModelId[0], signModel[1], authFlow, draft);
|
|
813
|
+
if (expiry)
|
|
814
|
+
signRequest.setCustomExpiry(expiry);
|
|
815
|
+
new AuthorizationBuilder(signRequest, authorizers, ruleSetting).addAuthorization();
|
|
816
|
+
const signingFlow = new dVVKSigningFlow_DEPRECATED(config.vendorId, vvkInfo.UserPublic, vvkInfo.OrkInfo, sessKey, gSessKey, getVoucherUrl());
|
|
817
|
+
const result = (await signingFlow.start(signRequest));
|
|
818
|
+
return result;
|
|
819
|
+
};
|
|
820
|
+
kc.signCardanoTx = async function (txBody, authorizers, ruleSettings, expiry) {
|
|
821
|
+
await kc.ensureTokenReady();
|
|
822
|
+
const sessKey = GenSessKey();
|
|
823
|
+
const gSessKey = GetPublic(sessKey);
|
|
824
|
+
const vvkInfo = await new NetworkClient(config.homeOrkUrl).GetKeyInfo(config.vendorId);
|
|
825
|
+
;
|
|
826
|
+
// Check user authenticated
|
|
827
|
+
if (!kc.tokenParsed) {
|
|
828
|
+
throw 'Not authenticated';
|
|
829
|
+
}
|
|
830
|
+
// Check config
|
|
831
|
+
if (!Array.isArray(authorizers)) {
|
|
832
|
+
throw 'Pass authorizers in an array!';
|
|
833
|
+
}
|
|
834
|
+
const cardanoSignRequest = new CardanoTxBodySignRequest("BlindSig:1");
|
|
835
|
+
cardanoSignRequest.setTxBody(txBody);
|
|
836
|
+
cardanoSignRequest.serializeDraft();
|
|
837
|
+
new AuthorizationBuilder(cardanoSignRequest, authorizers, ruleSettings).addAuthorization();
|
|
838
|
+
cardanoSignRequest.setCustomExpiry(expiry);
|
|
839
|
+
const txSigningFlow = new dVVKSigningFlow_DEPRECATED(config.vendorId, vvkInfo.UserPublic, vvkInfo.OrkInfo, sessKey, gSessKey, getVoucherUrl());
|
|
840
|
+
const result = (await txSigningFlow.start(cardanoSignRequest));
|
|
841
|
+
return bytesToBase64(result[0]);
|
|
842
|
+
};
|
|
843
|
+
kc.createRuleSettingsDraft = function (ruleSettings, previousRuleSetting, previousRuleSettingCert) {
|
|
844
|
+
const ruleReqDraft = new RuleSettingsSignRequest("Admin:1");
|
|
845
|
+
ruleReqDraft.setNewRuleSetting(StringToUint8Array(ruleSettings));
|
|
846
|
+
if (previousRuleSetting !== undefined && previousRuleSettingCert !== undefined) {
|
|
847
|
+
ruleReqDraft.setPreviousRuleSetting(StringToUint8Array(previousRuleSetting));
|
|
848
|
+
ruleReqDraft.setPreviousRuleSettingCert(base64ToBytes(previousRuleSettingCert));
|
|
849
|
+
}
|
|
850
|
+
return bytesToBase64(ruleReqDraft.getDraft());
|
|
851
|
+
};
|
|
852
|
+
function getRealmUrl() {
|
|
853
|
+
if (typeof kc.authServerUrl !== 'undefined') {
|
|
854
|
+
if (kc.authServerUrl.charAt(kc.authServerUrl.length - 1) == '/') {
|
|
855
|
+
return kc.authServerUrl + 'realms/' + encodeURIComponent(kc.realm);
|
|
856
|
+
}
|
|
857
|
+
else {
|
|
858
|
+
return kc.authServerUrl + '/realms/' + encodeURIComponent(kc.realm);
|
|
859
|
+
}
|
|
1030
860
|
}
|
|
1031
861
|
else {
|
|
1032
|
-
|
|
1033
|
-
this.realm = __classPrivateFieldGet(this, _TideCloak_config, "f").realm;
|
|
1034
|
-
__classPrivateFieldGet(this, _TideCloak_instances, "m", _TideCloak_setupEndpoints).call(this);
|
|
862
|
+
return undefined;
|
|
1035
863
|
}
|
|
1036
864
|
}
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
return __classPrivateFieldGet(this, _TideCloak_instances, "m", _TideCloak_getRealmUrl).call(this) + '/protocol/openid-connect/auth';
|
|
1041
|
-
},
|
|
1042
|
-
token: () => {
|
|
1043
|
-
return __classPrivateFieldGet(this, _TideCloak_instances, "m", _TideCloak_getRealmUrl).call(this) + '/protocol/openid-connect/token';
|
|
1044
|
-
},
|
|
1045
|
-
logout: () => {
|
|
1046
|
-
return __classPrivateFieldGet(this, _TideCloak_instances, "m", _TideCloak_getRealmUrl).call(this) + '/protocol/openid-connect/logout';
|
|
1047
|
-
},
|
|
1048
|
-
checkSessionIframe: () => {
|
|
1049
|
-
return __classPrivateFieldGet(this, _TideCloak_instances, "m", _TideCloak_getRealmUrl).call(this) + '/protocol/openid-connect/login-status-iframe.html';
|
|
1050
|
-
},
|
|
1051
|
-
thirdPartyCookiesIframe: () => {
|
|
1052
|
-
return __classPrivateFieldGet(this, _TideCloak_instances, "m", _TideCloak_getRealmUrl).call(this) + '/protocol/openid-connect/3p-cookies/step1.html';
|
|
1053
|
-
},
|
|
1054
|
-
register: () => {
|
|
1055
|
-
return __classPrivateFieldGet(this, _TideCloak_instances, "m", _TideCloak_getRealmUrl).call(this) + '/protocol/openid-connect/registrations';
|
|
1056
|
-
},
|
|
1057
|
-
userinfo: () => {
|
|
1058
|
-
return __classPrivateFieldGet(this, _TideCloak_instances, "m", _TideCloak_getRealmUrl).call(this) + '/protocol/openid-connect/userinfo';
|
|
865
|
+
function getOrigin() {
|
|
866
|
+
if (!window.location.origin) {
|
|
867
|
+
return window.location.protocol + "//" + window.location.hostname + (window.location.port ? ':' + window.location.port : '');
|
|
1059
868
|
}
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
/**
|
|
1063
|
-
* @param {string | OpenIdProviderMetadata} oidcProvider
|
|
1064
|
-
* @returns {Promise<void>}
|
|
1065
|
-
*/
|
|
1066
|
-
async function _TideCloak_loadOidcConfig(oidcProvider) {
|
|
1067
|
-
if (typeof oidcProvider === 'string') {
|
|
1068
|
-
const url = `${stripTrailingSlash(oidcProvider)}/.well-known/openid-configuration`;
|
|
1069
|
-
const openIdConfig = await fetchOpenIdConfig(url);
|
|
1070
|
-
__classPrivateFieldGet(this, _TideCloak_instances, "m", _TideCloak_setupOidcEndpoints).call(this, openIdConfig);
|
|
1071
|
-
}
|
|
1072
|
-
else {
|
|
1073
|
-
__classPrivateFieldGet(this, _TideCloak_instances, "m", _TideCloak_setupOidcEndpoints).call(this, oidcProvider);
|
|
1074
|
-
}
|
|
1075
|
-
}, _TideCloak_setupOidcEndpoints = function _TideCloak_setupOidcEndpoints(config) {
|
|
1076
|
-
this.endpoints = {
|
|
1077
|
-
authorize() {
|
|
1078
|
-
return config.authorization_endpoint;
|
|
1079
|
-
},
|
|
1080
|
-
token() {
|
|
1081
|
-
return config.token_endpoint;
|
|
1082
|
-
},
|
|
1083
|
-
logout() {
|
|
1084
|
-
if (!config.end_session_endpoint) {
|
|
1085
|
-
throw new Error('Not supported by the OIDC server');
|
|
1086
|
-
}
|
|
1087
|
-
return config.end_session_endpoint;
|
|
1088
|
-
},
|
|
1089
|
-
checkSessionIframe() {
|
|
1090
|
-
if (!config.check_session_iframe) {
|
|
1091
|
-
throw new Error('Not supported by the OIDC server');
|
|
1092
|
-
}
|
|
1093
|
-
return config.check_session_iframe;
|
|
1094
|
-
},
|
|
1095
|
-
register() {
|
|
1096
|
-
throw new Error('Redirection to "Register user" page not supported in standard OIDC mode');
|
|
1097
|
-
},
|
|
1098
|
-
userinfo() {
|
|
1099
|
-
if (!config.userinfo_endpoint) {
|
|
1100
|
-
throw new Error('Not supported by the OIDC server');
|
|
1101
|
-
}
|
|
1102
|
-
return config.userinfo_endpoint;
|
|
869
|
+
else {
|
|
870
|
+
return window.location.origin;
|
|
1103
871
|
}
|
|
1104
|
-
};
|
|
1105
|
-
}, _TideCloak_check3pCookiesSupported =
|
|
1106
|
-
/**
|
|
1107
|
-
* @returns {Promise<void>}
|
|
1108
|
-
*/
|
|
1109
|
-
async function _TideCloak_check3pCookiesSupported() {
|
|
1110
|
-
if ((!__classPrivateFieldGet(this, _TideCloak_loginIframe, "f").enable && !this.silentCheckSsoRedirectUri) || typeof this.endpoints.thirdPartyCookiesIframe !== 'function') {
|
|
1111
|
-
return;
|
|
1112
872
|
}
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
873
|
+
function processCallback(oauth, promise) {
|
|
874
|
+
var code = oauth.code;
|
|
875
|
+
var error = oauth.error;
|
|
876
|
+
var prompt = oauth.prompt;
|
|
877
|
+
var timeLocal = new Date().getTime();
|
|
878
|
+
if (oauth['kc_action_status']) {
|
|
879
|
+
kc.onActionUpdate && kc.onActionUpdate(oauth['kc_action_status'], oauth['kc_action']);
|
|
880
|
+
}
|
|
881
|
+
if (error) {
|
|
882
|
+
if (prompt != 'none') {
|
|
883
|
+
if (oauth.error_description && oauth.error_description === "authentication_expired") {
|
|
884
|
+
kc.login(oauth.loginOptions);
|
|
885
|
+
}
|
|
886
|
+
else {
|
|
887
|
+
var errorData = { error: error, error_description: oauth.error_description };
|
|
888
|
+
kc.onAuthError && kc.onAuthError(errorData);
|
|
889
|
+
promise && promise.setError(errorData);
|
|
890
|
+
}
|
|
1127
891
|
}
|
|
1128
|
-
|
|
1129
|
-
|
|
892
|
+
else {
|
|
893
|
+
promise && promise.setSuccess();
|
|
894
|
+
}
|
|
895
|
+
return;
|
|
896
|
+
}
|
|
897
|
+
else if ((kc.flow != 'standard') && (oauth.access_token || oauth.id_token)) {
|
|
898
|
+
authSuccess(oauth.access_token, null, oauth.id_token, true, oauth.doken);
|
|
899
|
+
}
|
|
900
|
+
if ((kc.flow != 'implicit') && code) {
|
|
901
|
+
var params = 'code=' + code + '&grant_type=authorization_code';
|
|
902
|
+
var url = kc.endpoints.token();
|
|
903
|
+
var req = new XMLHttpRequest();
|
|
904
|
+
req.open('POST', url, true);
|
|
905
|
+
req.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
|
|
906
|
+
params += '&client_id=' + encodeURIComponent(kc.clientId);
|
|
907
|
+
params += '&redirect_uri=' + oauth.redirectUri;
|
|
908
|
+
if (oauth.pkceCodeVerifier) {
|
|
909
|
+
params += '&code_verifier=' + oauth.pkceCodeVerifier;
|
|
910
|
+
}
|
|
911
|
+
req.withCredentials = true;
|
|
912
|
+
req.onreadystatechange = function () {
|
|
913
|
+
if (req.readyState == 4) {
|
|
914
|
+
if (req.status == 200) {
|
|
915
|
+
var tokenResponse = JSON.parse(req.responseText);
|
|
916
|
+
authSuccess(tokenResponse['access_token'], tokenResponse['refresh_token'], tokenResponse['id_token'], kc.flow === 'standard', tokenResponse['doken']); // added doken field
|
|
917
|
+
scheduleCheckIframe();
|
|
918
|
+
}
|
|
919
|
+
else {
|
|
920
|
+
if (req.status == 500) {
|
|
921
|
+
// Check to see if error message tells us to reauthenticate the user
|
|
922
|
+
console.log("CHECKING REAUTH");
|
|
923
|
+
}
|
|
924
|
+
kc.onAuthError && kc.onAuthError();
|
|
925
|
+
promise && promise.setError();
|
|
926
|
+
}
|
|
927
|
+
}
|
|
928
|
+
};
|
|
929
|
+
req.onerror = function () {
|
|
930
|
+
// Try to log the user in again
|
|
931
|
+
kc.login({
|
|
932
|
+
idpHint: 'tide',
|
|
933
|
+
prompt: 'login', // forces them to actually re-enter credentials
|
|
934
|
+
redirectUri: window.location.href // send them back to the exact same URL
|
|
935
|
+
});
|
|
936
|
+
};
|
|
937
|
+
req.send(params);
|
|
938
|
+
}
|
|
939
|
+
function authSuccess(accessToken, refreshToken, idToken, fulfillPromise, doken = null) {
|
|
940
|
+
timeLocal = (timeLocal + new Date().getTime()) / 2;
|
|
941
|
+
setToken(accessToken, refreshToken, idToken, timeLocal, doken);
|
|
942
|
+
if (useNonce && (kc.idTokenParsed && kc.idTokenParsed.nonce != oauth.storedNonce)) {
|
|
943
|
+
logInfo('[TIDECLOAK] Invalid nonce, clearing token');
|
|
944
|
+
kc.clearToken();
|
|
945
|
+
promise && promise.setError();
|
|
1130
946
|
}
|
|
1131
|
-
else
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
'For more information see: https://www.keycloak.org/securing-apps/javascript-adapter#_modern_browsers');
|
|
1136
|
-
__classPrivateFieldGet(this, _TideCloak_loginIframe, "f").enable = false;
|
|
1137
|
-
if (this.silentCheckSsoFallback) {
|
|
1138
|
-
this.silentCheckSsoRedirectUri = undefined;
|
|
947
|
+
else {
|
|
948
|
+
if (fulfillPromise) {
|
|
949
|
+
kc.onAuthSuccess && kc.onAuthSuccess();
|
|
950
|
+
promise && promise.setSuccess();
|
|
1139
951
|
}
|
|
1140
952
|
}
|
|
1141
|
-
|
|
1142
|
-
window.removeEventListener('message', messageCallback);
|
|
1143
|
-
resolve();
|
|
1144
|
-
};
|
|
1145
|
-
window.addEventListener('message', messageCallback, false);
|
|
1146
|
-
});
|
|
1147
|
-
return await applyTimeoutToPromise(promise, this.messageReceiveTimeout, 'Timeout when waiting for 3rd party check iframe message.');
|
|
1148
|
-
}, _TideCloak_processInit =
|
|
1149
|
-
/**
|
|
1150
|
-
* @param {KeycloakInitOptions} initOptions
|
|
1151
|
-
* @returns {Promise<void>}
|
|
1152
|
-
*/
|
|
1153
|
-
async function _TideCloak_processInit(initOptions) {
|
|
1154
|
-
var _a, _b, _c;
|
|
1155
|
-
const callback = __classPrivateFieldGet(this, _TideCloak_instances, "m", _TideCloak_parseCallback).call(this, window.location.href);
|
|
1156
|
-
if (callback === null || callback === void 0 ? void 0 : callback.redirectUri) {
|
|
1157
|
-
window.history.replaceState(window.history.state, '', callback.redirectUri);
|
|
1158
|
-
}
|
|
1159
|
-
if (callback && callback.valid) {
|
|
1160
|
-
await __classPrivateFieldGet(this, _TideCloak_instances, "m", _TideCloak_setupCheckLoginIframe).call(this);
|
|
1161
|
-
await __classPrivateFieldGet(this, _TideCloak_instances, "m", _TideCloak_processCallback).call(this, callback);
|
|
1162
|
-
return;
|
|
953
|
+
}
|
|
1163
954
|
}
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
955
|
+
function loadConfig() {
|
|
956
|
+
var promise = createPromise();
|
|
957
|
+
var configUrl;
|
|
958
|
+
if (typeof config === 'string') {
|
|
959
|
+
configUrl = config;
|
|
960
|
+
}
|
|
961
|
+
function setupOidcEndoints(oidcConfiguration) {
|
|
962
|
+
if (!oidcConfiguration) {
|
|
963
|
+
kc.endpoints = {
|
|
964
|
+
authorize: function () {
|
|
965
|
+
return getRealmUrl() + '/protocol/openid-connect/auth';
|
|
966
|
+
},
|
|
967
|
+
token: function () {
|
|
968
|
+
return getRealmUrl() + '/protocol/openid-connect/token';
|
|
969
|
+
},
|
|
970
|
+
logout: function () {
|
|
971
|
+
return getRealmUrl() + '/protocol/openid-connect/logout';
|
|
972
|
+
},
|
|
973
|
+
checkSessionIframe: function () {
|
|
974
|
+
return getRealmUrl() + '/protocol/openid-connect/login-status-iframe.html';
|
|
975
|
+
},
|
|
976
|
+
thirdPartyCookiesIframe: function () {
|
|
977
|
+
return getRealmUrl() + '/protocol/openid-connect/3p-cookies/step1.html';
|
|
978
|
+
},
|
|
979
|
+
register: function () {
|
|
980
|
+
return getRealmUrl() + '/protocol/openid-connect/registrations';
|
|
981
|
+
},
|
|
982
|
+
userinfo: function () {
|
|
983
|
+
return getRealmUrl() + '/protocol/openid-connect/userinfo';
|
|
984
|
+
}
|
|
985
|
+
};
|
|
986
|
+
}
|
|
987
|
+
else {
|
|
988
|
+
kc.endpoints = {
|
|
989
|
+
authorize: function () {
|
|
990
|
+
return oidcConfiguration.authorization_endpoint;
|
|
991
|
+
},
|
|
992
|
+
token: function () {
|
|
993
|
+
return oidcConfiguration.token_endpoint;
|
|
994
|
+
},
|
|
995
|
+
logout: function () {
|
|
996
|
+
if (!oidcConfiguration.end_session_endpoint) {
|
|
997
|
+
throw "Not supported by the OIDC server";
|
|
998
|
+
}
|
|
999
|
+
return oidcConfiguration.end_session_endpoint;
|
|
1000
|
+
},
|
|
1001
|
+
checkSessionIframe: function () {
|
|
1002
|
+
if (!oidcConfiguration.check_session_iframe) {
|
|
1003
|
+
throw "Not supported by the OIDC server";
|
|
1004
|
+
}
|
|
1005
|
+
return oidcConfiguration.check_session_iframe;
|
|
1006
|
+
},
|
|
1007
|
+
register: function () {
|
|
1008
|
+
throw 'Redirection to "Register user" page not supported in standard OIDC mode';
|
|
1009
|
+
},
|
|
1010
|
+
userinfo: function () {
|
|
1011
|
+
if (!oidcConfiguration.userinfo_endpoint) {
|
|
1012
|
+
throw "Not supported by the OIDC server";
|
|
1013
|
+
}
|
|
1014
|
+
return oidcConfiguration.userinfo_endpoint;
|
|
1015
|
+
}
|
|
1016
|
+
};
|
|
1017
|
+
}
|
|
1170
1018
|
}
|
|
1171
|
-
if (
|
|
1172
|
-
|
|
1019
|
+
if (configUrl) {
|
|
1020
|
+
var req = new XMLHttpRequest();
|
|
1021
|
+
req.open('GET', configUrl, true);
|
|
1022
|
+
req.setRequestHeader('Accept', 'application/json');
|
|
1023
|
+
req.onreadystatechange = function () {
|
|
1024
|
+
if (req.readyState == 4) {
|
|
1025
|
+
if (req.status == 200 || fileLoaded(req)) {
|
|
1026
|
+
var config = JSON.parse(req.responseText);
|
|
1027
|
+
kc.authServerUrl = config['auth-server-url'];
|
|
1028
|
+
kc.realm = config['realm'];
|
|
1029
|
+
kc.clientId = config['resource'];
|
|
1030
|
+
setupOidcEndoints(null);
|
|
1031
|
+
promise.setSuccess();
|
|
1032
|
+
}
|
|
1033
|
+
else {
|
|
1034
|
+
promise.setError();
|
|
1035
|
+
}
|
|
1036
|
+
}
|
|
1037
|
+
};
|
|
1038
|
+
req.send();
|
|
1173
1039
|
}
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1040
|
+
else {
|
|
1041
|
+
kc.clientId = config.clientId;
|
|
1042
|
+
var oidcProvider = config['oidcProvider'];
|
|
1043
|
+
if (!oidcProvider) {
|
|
1044
|
+
kc.authServerUrl = config.url;
|
|
1045
|
+
kc.realm = config.realm;
|
|
1046
|
+
setupOidcEndoints(null);
|
|
1047
|
+
promise.setSuccess();
|
|
1048
|
+
}
|
|
1049
|
+
else {
|
|
1050
|
+
if (typeof oidcProvider === 'string') {
|
|
1051
|
+
var oidcProviderConfigUrl;
|
|
1052
|
+
if (oidcProvider.charAt(oidcProvider.length - 1) == '/') {
|
|
1053
|
+
oidcProviderConfigUrl = oidcProvider + '.well-known/openid-configuration';
|
|
1184
1054
|
}
|
|
1055
|
+
else {
|
|
1056
|
+
oidcProviderConfigUrl = oidcProvider + '/.well-known/openid-configuration';
|
|
1057
|
+
}
|
|
1058
|
+
var req = new XMLHttpRequest();
|
|
1059
|
+
req.open('GET', oidcProviderConfigUrl, true);
|
|
1060
|
+
req.setRequestHeader('Accept', 'application/json');
|
|
1061
|
+
req.onreadystatechange = function () {
|
|
1062
|
+
if (req.readyState == 4) {
|
|
1063
|
+
if (req.status == 200 || fileLoaded(req)) {
|
|
1064
|
+
var oidcProviderConfig = JSON.parse(req.responseText);
|
|
1065
|
+
setupOidcEndoints(oidcProviderConfig);
|
|
1066
|
+
promise.setSuccess();
|
|
1067
|
+
}
|
|
1068
|
+
else {
|
|
1069
|
+
promise.setError();
|
|
1070
|
+
}
|
|
1071
|
+
}
|
|
1072
|
+
};
|
|
1073
|
+
req.send();
|
|
1185
1074
|
}
|
|
1186
1075
|
else {
|
|
1187
|
-
|
|
1076
|
+
setupOidcEndoints(oidcProvider);
|
|
1077
|
+
promise.setSuccess();
|
|
1188
1078
|
}
|
|
1189
|
-
break;
|
|
1190
|
-
case 'login-required':
|
|
1191
|
-
await doLogin(true);
|
|
1192
|
-
break;
|
|
1193
|
-
default:
|
|
1194
|
-
throw new Error('Invalid value for onLoad');
|
|
1195
|
-
}
|
|
1196
|
-
};
|
|
1197
|
-
if (initOptions.token && initOptions.refreshToken) {
|
|
1198
|
-
__classPrivateFieldGet(this, _TideCloak_instances, "m", _TideCloak_setToken).call(this, initOptions.token, initOptions.refreshToken, initOptions.idToken);
|
|
1199
|
-
if (__classPrivateFieldGet(this, _TideCloak_loginIframe, "f").enable) {
|
|
1200
|
-
await __classPrivateFieldGet(this, _TideCloak_instances, "m", _TideCloak_setupCheckLoginIframe).call(this);
|
|
1201
|
-
const unchanged = await __classPrivateFieldGet(this, _TideCloak_instances, "m", _TideCloak_checkLoginIframe).call(this);
|
|
1202
|
-
if (unchanged) {
|
|
1203
|
-
(_a = this.onAuthSuccess) === null || _a === void 0 ? void 0 : _a.call(this);
|
|
1204
|
-
__classPrivateFieldGet(this, _TideCloak_instances, "m", _TideCloak_scheduleCheckIframe).call(this);
|
|
1205
1079
|
}
|
|
1206
1080
|
}
|
|
1081
|
+
return promise.promise;
|
|
1082
|
+
}
|
|
1083
|
+
function fileLoaded(xhr) {
|
|
1084
|
+
return xhr.status == 0 && xhr.responseText && xhr.responseURL.startsWith('file:');
|
|
1085
|
+
}
|
|
1086
|
+
function setToken(token, refreshToken, idToken, timeLocal, doken = null) {
|
|
1087
|
+
if (kc.tokenTimeoutHandle) {
|
|
1088
|
+
clearTimeout(kc.tokenTimeoutHandle);
|
|
1089
|
+
kc.tokenTimeoutHandle = null;
|
|
1090
|
+
}
|
|
1091
|
+
if (refreshToken) {
|
|
1092
|
+
kc.refreshToken = refreshToken;
|
|
1093
|
+
kc.refreshTokenParsed = decodeToken(refreshToken);
|
|
1094
|
+
}
|
|
1207
1095
|
else {
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1096
|
+
delete kc.refreshToken;
|
|
1097
|
+
delete kc.refreshTokenParsed;
|
|
1098
|
+
}
|
|
1099
|
+
if (idToken) {
|
|
1100
|
+
kc.idToken = idToken;
|
|
1101
|
+
kc.idTokenParsed = decodeToken(idToken);
|
|
1102
|
+
}
|
|
1103
|
+
else {
|
|
1104
|
+
delete kc.idToken;
|
|
1105
|
+
delete kc.idTokenParsed;
|
|
1106
|
+
}
|
|
1107
|
+
if (token) {
|
|
1108
|
+
kc.token = token;
|
|
1109
|
+
kc.tokenParsed = decodeToken(token);
|
|
1110
|
+
kc.sessionId = kc.tokenParsed.sid;
|
|
1111
|
+
kc.authenticated = true;
|
|
1112
|
+
kc.subject = kc.tokenParsed.sub;
|
|
1113
|
+
kc.realmAccess = kc.tokenParsed.realm_access;
|
|
1114
|
+
kc.resourceAccess = kc.tokenParsed.resource_access;
|
|
1115
|
+
if (timeLocal) {
|
|
1116
|
+
kc.timeSkew = Math.floor(timeLocal / 1000) - kc.tokenParsed.iat;
|
|
1211
1117
|
}
|
|
1212
|
-
|
|
1213
|
-
(
|
|
1214
|
-
if (
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1118
|
+
if (kc.timeSkew != null) {
|
|
1119
|
+
logInfo('[TIDECLOAK] Estimated time difference between browser and server is ' + kc.timeSkew + ' seconds');
|
|
1120
|
+
if (kc.onTokenExpired) {
|
|
1121
|
+
var expiresIn = (kc.tokenParsed['exp'] - (new Date().getTime() / 1000) + kc.timeSkew) * 1000;
|
|
1122
|
+
logInfo('[TIDECLOAK] Token expires in ' + Math.round(expiresIn / 1000) + ' s');
|
|
1123
|
+
if (expiresIn <= 0) {
|
|
1124
|
+
kc.onTokenExpired();
|
|
1125
|
+
}
|
|
1126
|
+
else {
|
|
1127
|
+
kc.tokenTimeoutHandle = setTimeout(kc.onTokenExpired, expiresIn);
|
|
1128
|
+
}
|
|
1219
1129
|
}
|
|
1220
1130
|
}
|
|
1221
1131
|
}
|
|
1132
|
+
else {
|
|
1133
|
+
delete kc.token;
|
|
1134
|
+
delete kc.tokenParsed;
|
|
1135
|
+
delete kc.subject;
|
|
1136
|
+
delete kc.realmAccess;
|
|
1137
|
+
delete kc.resourceAccess;
|
|
1138
|
+
kc.authenticated = false;
|
|
1139
|
+
}
|
|
1140
|
+
if (doken) {
|
|
1141
|
+
kc.doken = doken;
|
|
1142
|
+
kc.dokenParsed = decodeToken(doken);
|
|
1143
|
+
// update heimdall's doken too
|
|
1144
|
+
if (kc.requestEnclave)
|
|
1145
|
+
kc.requestEnclave.updateDoken(kc.doken);
|
|
1146
|
+
}
|
|
1147
|
+
else {
|
|
1148
|
+
delete kc.doken;
|
|
1149
|
+
}
|
|
1222
1150
|
}
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
}
|
|
1227
|
-
|
|
1228
|
-
* @returns {Promise<void>}
|
|
1229
|
-
*/
|
|
1230
|
-
async function _TideCloak_setupCheckLoginIframe() {
|
|
1231
|
-
if (!__classPrivateFieldGet(this, _TideCloak_loginIframe, "f").enable || __classPrivateFieldGet(this, _TideCloak_loginIframe, "f").iframe) {
|
|
1232
|
-
return;
|
|
1151
|
+
function createUUID() {
|
|
1152
|
+
if (typeof crypto === "undefined" || typeof crypto.randomUUID === "undefined") {
|
|
1153
|
+
throw new Error("Web Crypto API is not available.");
|
|
1154
|
+
}
|
|
1155
|
+
return crypto.randomUUID();
|
|
1233
1156
|
}
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
iframe.setAttribute('sandbox', 'allow-storage-access-by-user-activation allow-scripts allow-same-origin');
|
|
1238
|
-
iframe.setAttribute('title', 'keycloak-session-iframe');
|
|
1239
|
-
iframe.style.display = 'none';
|
|
1240
|
-
document.body.appendChild(iframe);
|
|
1241
|
-
/**
|
|
1242
|
-
* @param {MessageEvent} event
|
|
1243
|
-
*/
|
|
1244
|
-
const messageCallback = (event) => {
|
|
1245
|
-
var _a;
|
|
1246
|
-
if (event.origin !== __classPrivateFieldGet(this, _TideCloak_loginIframe, "f").iframeOrigin || ((_a = __classPrivateFieldGet(this, _TideCloak_loginIframe, "f").iframe) === null || _a === void 0 ? void 0 : _a.contentWindow) !== event.source) {
|
|
1157
|
+
function parseCallback(url) {
|
|
1158
|
+
var oauth = parseCallbackUrl(url);
|
|
1159
|
+
if (!oauth) {
|
|
1247
1160
|
return;
|
|
1248
1161
|
}
|
|
1249
|
-
|
|
1250
|
-
|
|
1162
|
+
var oauthState = callbackStorage.get(oauth.state);
|
|
1163
|
+
if (oauthState) {
|
|
1164
|
+
oauth.valid = true;
|
|
1165
|
+
oauth.redirectUri = oauthState.redirectUri;
|
|
1166
|
+
oauth.storedNonce = oauthState.nonce;
|
|
1167
|
+
oauth.prompt = oauthState.prompt;
|
|
1168
|
+
oauth.pkceCodeVerifier = oauthState.pkceCodeVerifier;
|
|
1169
|
+
oauth.loginOptions = oauthState.loginOptions;
|
|
1170
|
+
}
|
|
1171
|
+
return oauth;
|
|
1172
|
+
}
|
|
1173
|
+
function parseCallbackUrl(url) {
|
|
1174
|
+
var supportedParams;
|
|
1175
|
+
switch (kc.flow) {
|
|
1176
|
+
case 'standard':
|
|
1177
|
+
supportedParams = ['code', 'state', 'session_state', 'kc_action_status', 'kc_action', 'iss'];
|
|
1178
|
+
break;
|
|
1179
|
+
case 'implicit':
|
|
1180
|
+
supportedParams = ['access_token', 'token_type', 'id_token', 'state', 'session_state', 'expires_in', 'kc_action_status', 'kc_action', 'iss'];
|
|
1181
|
+
break;
|
|
1182
|
+
case 'hybrid':
|
|
1183
|
+
supportedParams = ['access_token', 'token_type', 'id_token', 'code', 'state', 'session_state', 'expires_in', 'kc_action_status', 'kc_action', 'iss'];
|
|
1184
|
+
break;
|
|
1251
1185
|
}
|
|
1252
|
-
|
|
1253
|
-
|
|
1186
|
+
supportedParams.push('error');
|
|
1187
|
+
supportedParams.push('error_description');
|
|
1188
|
+
supportedParams.push('error_uri');
|
|
1189
|
+
var queryIndex = url.indexOf('?');
|
|
1190
|
+
var fragmentIndex = url.indexOf('#');
|
|
1191
|
+
var newUrl;
|
|
1192
|
+
var parsed;
|
|
1193
|
+
if (kc.responseMode === 'query' && queryIndex !== -1) {
|
|
1194
|
+
newUrl = url.substring(0, queryIndex);
|
|
1195
|
+
parsed = parseCallbackParams(url.substring(queryIndex + 1, fragmentIndex !== -1 ? fragmentIndex : url.length), supportedParams);
|
|
1196
|
+
if (parsed.paramsString !== '') {
|
|
1197
|
+
newUrl += '?' + parsed.paramsString;
|
|
1198
|
+
}
|
|
1199
|
+
if (fragmentIndex !== -1) {
|
|
1200
|
+
newUrl += url.substring(fragmentIndex);
|
|
1201
|
+
}
|
|
1254
1202
|
}
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
if (
|
|
1259
|
-
|
|
1203
|
+
else if (kc.responseMode === 'fragment' && fragmentIndex !== -1) {
|
|
1204
|
+
newUrl = url.substring(0, fragmentIndex);
|
|
1205
|
+
parsed = parseCallbackParams(url.substring(fragmentIndex + 1), supportedParams);
|
|
1206
|
+
if (parsed.paramsString !== '') {
|
|
1207
|
+
newUrl += '#' + parsed.paramsString;
|
|
1260
1208
|
}
|
|
1261
|
-
|
|
1262
|
-
|
|
1209
|
+
}
|
|
1210
|
+
if (parsed && parsed.oauthParams) {
|
|
1211
|
+
if (kc.flow === 'standard' || kc.flow === 'hybrid') {
|
|
1212
|
+
if ((parsed.oauthParams.code || parsed.oauthParams.error) && parsed.oauthParams.state) {
|
|
1213
|
+
parsed.oauthParams.newUrl = newUrl;
|
|
1214
|
+
return parsed.oauthParams;
|
|
1215
|
+
}
|
|
1216
|
+
}
|
|
1217
|
+
else if (kc.flow === 'implicit') {
|
|
1218
|
+
if ((parsed.oauthParams.access_token || parsed.oauthParams.error) && parsed.oauthParams.state) {
|
|
1219
|
+
parsed.oauthParams.newUrl = newUrl;
|
|
1220
|
+
return parsed.oauthParams;
|
|
1221
|
+
}
|
|
1263
1222
|
}
|
|
1264
1223
|
}
|
|
1265
|
-
}
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1224
|
+
}
|
|
1225
|
+
function parseCallbackParams(paramsString, supportedParams) {
|
|
1226
|
+
var p = paramsString.split('&');
|
|
1227
|
+
var result = {
|
|
1228
|
+
paramsString: '',
|
|
1229
|
+
oauthParams: {}
|
|
1230
|
+
};
|
|
1231
|
+
for (var i = 0; i < p.length; i++) {
|
|
1232
|
+
var split = p[i].indexOf("=");
|
|
1233
|
+
var key = p[i].slice(0, split);
|
|
1234
|
+
if (supportedParams.indexOf(key) !== -1) {
|
|
1235
|
+
result.oauthParams[key] = p[i].slice(split + 1);
|
|
1273
1236
|
}
|
|
1274
1237
|
else {
|
|
1275
|
-
|
|
1238
|
+
if (result.paramsString !== '') {
|
|
1239
|
+
result.paramsString += '&';
|
|
1240
|
+
}
|
|
1241
|
+
result.paramsString += p[i];
|
|
1242
|
+
}
|
|
1243
|
+
}
|
|
1244
|
+
return result;
|
|
1245
|
+
}
|
|
1246
|
+
function createPromise() {
|
|
1247
|
+
// Need to create a native Promise which also preserves the
|
|
1248
|
+
// interface of the custom promise type previously used by the API
|
|
1249
|
+
var p = {
|
|
1250
|
+
setSuccess: function (result) {
|
|
1251
|
+
p.resolve(result);
|
|
1252
|
+
},
|
|
1253
|
+
setError: function (result) {
|
|
1254
|
+
p.reject(result);
|
|
1276
1255
|
}
|
|
1277
|
-
|
|
1256
|
+
};
|
|
1257
|
+
p.promise = new Promise(function (resolve, reject) {
|
|
1258
|
+
p.resolve = resolve;
|
|
1259
|
+
p.reject = reject;
|
|
1260
|
+
});
|
|
1261
|
+
return p;
|
|
1262
|
+
}
|
|
1263
|
+
// Function to extend existing native Promise with timeout
|
|
1264
|
+
function applyTimeoutToPromise(promise, timeout, errorMessage) {
|
|
1265
|
+
var timeoutHandle = null;
|
|
1266
|
+
var timeoutPromise = new Promise(function (resolve, reject) {
|
|
1267
|
+
timeoutHandle = setTimeout(function () {
|
|
1268
|
+
reject({ "error": errorMessage || "Promise is not settled within timeout of " + timeout + "ms" });
|
|
1269
|
+
}, timeout);
|
|
1270
|
+
});
|
|
1271
|
+
return Promise.race([promise, timeoutPromise]).finally(function () {
|
|
1272
|
+
clearTimeout(timeoutHandle);
|
|
1278
1273
|
});
|
|
1279
|
-
});
|
|
1280
|
-
await promise;
|
|
1281
|
-
}, _TideCloak_checkLoginIframe =
|
|
1282
|
-
/**
|
|
1283
|
-
* @returns {Promise<boolean | undefined>}
|
|
1284
|
-
*/
|
|
1285
|
-
async function _TideCloak_checkLoginIframe() {
|
|
1286
|
-
if (!__classPrivateFieldGet(this, _TideCloak_loginIframe, "f").iframe || !__classPrivateFieldGet(this, _TideCloak_loginIframe, "f").iframeOrigin) {
|
|
1287
|
-
return;
|
|
1288
1274
|
}
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
*/
|
|
1306
|
-
async function _TideCloak_checkSsoSilently() {
|
|
1307
|
-
const iframe = document.createElement('iframe');
|
|
1308
|
-
const src = await this.createLoginUrl({ prompt: 'none', redirectUri: this.silentCheckSsoRedirectUri });
|
|
1309
|
-
iframe.setAttribute('src', src);
|
|
1310
|
-
iframe.setAttribute('sandbox', 'allow-storage-access-by-user-activation allow-scripts allow-same-origin');
|
|
1311
|
-
iframe.setAttribute('title', 'keycloak-silent-check-sso');
|
|
1312
|
-
iframe.style.display = 'none';
|
|
1313
|
-
document.body.appendChild(iframe);
|
|
1314
|
-
return await new Promise((resolve, reject) => {
|
|
1315
|
-
/**
|
|
1316
|
-
* @param {MessageEvent} event
|
|
1317
|
-
*/
|
|
1318
|
-
const messageCallback = async (event) => {
|
|
1319
|
-
if (event.origin !== window.location.origin || iframe.contentWindow !== event.source) {
|
|
1320
|
-
return;
|
|
1321
|
-
}
|
|
1322
|
-
const oauth = __classPrivateFieldGet(this, _TideCloak_instances, "m", _TideCloak_parseCallback).call(this, event.data);
|
|
1323
|
-
try {
|
|
1324
|
-
await __classPrivateFieldGet(this, _TideCloak_instances, "m", _TideCloak_processCallback).call(this, oauth);
|
|
1325
|
-
resolve();
|
|
1275
|
+
function setupCheckLoginIframe() {
|
|
1276
|
+
var promise = createPromise();
|
|
1277
|
+
if (!loginIframe.enable) {
|
|
1278
|
+
promise.setSuccess();
|
|
1279
|
+
return promise.promise;
|
|
1280
|
+
}
|
|
1281
|
+
if (loginIframe.iframe) {
|
|
1282
|
+
promise.setSuccess();
|
|
1283
|
+
return promise.promise;
|
|
1284
|
+
}
|
|
1285
|
+
var iframe = document.createElement('iframe');
|
|
1286
|
+
loginIframe.iframe = iframe;
|
|
1287
|
+
iframe.onload = function () {
|
|
1288
|
+
var authUrl = kc.endpoints.authorize();
|
|
1289
|
+
if (authUrl.charAt(0) === '/') {
|
|
1290
|
+
loginIframe.iframeOrigin = getOrigin();
|
|
1326
1291
|
}
|
|
1327
|
-
|
|
1328
|
-
|
|
1292
|
+
else {
|
|
1293
|
+
loginIframe.iframeOrigin = authUrl.substring(0, authUrl.indexOf('/', 8));
|
|
1329
1294
|
}
|
|
1330
|
-
|
|
1331
|
-
window.removeEventListener('message', messageCallback);
|
|
1295
|
+
promise.setSuccess();
|
|
1332
1296
|
};
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
oauth.valid = true;
|
|
1343
|
-
oauth.redirectUri = oauthState.redirectUri;
|
|
1344
|
-
oauth.storedNonce = oauthState.nonce;
|
|
1345
|
-
oauth.prompt = oauthState.prompt;
|
|
1346
|
-
oauth.pkceCodeVerifier = oauthState.pkceCodeVerifier;
|
|
1347
|
-
oauth.loginOptions = oauthState.loginOptions;
|
|
1348
|
-
}
|
|
1349
|
-
return oauth;
|
|
1350
|
-
}, _TideCloak_parseCallbackUrl = function _TideCloak_parseCallbackUrl(urlString) {
|
|
1351
|
-
let supportedParams = [];
|
|
1352
|
-
switch (this.flow) {
|
|
1353
|
-
case 'standard':
|
|
1354
|
-
supportedParams = ['code', 'state', 'session_state', 'kc_action_status', 'kc_action', 'iss', 'doken'];
|
|
1355
|
-
break;
|
|
1356
|
-
case 'implicit':
|
|
1357
|
-
supportedParams = ['access_token', 'token_type', 'id_token', 'state', 'session_state', 'expires_in', 'kc_action_status', 'kc_action', 'iss', 'doken'];
|
|
1358
|
-
break;
|
|
1359
|
-
case 'hybrid':
|
|
1360
|
-
supportedParams = ['access_token', 'token_type', 'id_token', 'code', 'state', 'session_state', 'expires_in', 'kc_action_status', 'kc_action', 'iss', 'doken'];
|
|
1361
|
-
break;
|
|
1362
|
-
}
|
|
1363
|
-
supportedParams.push('error');
|
|
1364
|
-
supportedParams.push('error_description');
|
|
1365
|
-
supportedParams.push('error_uri');
|
|
1366
|
-
const url = new URL(urlString);
|
|
1367
|
-
let redirectUri = '';
|
|
1368
|
-
let parsed;
|
|
1369
|
-
if (this.responseMode === 'query' && url.searchParams.size > 0) {
|
|
1370
|
-
parsed = __classPrivateFieldGet(this, _TideCloak_instances, "m", _TideCloak_parseCallbackParams).call(this, url.search, supportedParams);
|
|
1371
|
-
url.search = parsed.paramsString;
|
|
1372
|
-
redirectUri = url.toString();
|
|
1373
|
-
}
|
|
1374
|
-
else if (this.responseMode === 'fragment' && url.hash.length > 0) {
|
|
1375
|
-
parsed = __classPrivateFieldGet(this, _TideCloak_instances, "m", _TideCloak_parseCallbackParams).call(this, url.hash.substring(1), supportedParams);
|
|
1376
|
-
url.hash = '';
|
|
1377
|
-
redirectUri = url.toString();
|
|
1378
|
-
}
|
|
1379
|
-
if (parsed === null || parsed === void 0 ? void 0 : parsed.oauthParams) {
|
|
1380
|
-
if (this.flow === 'standard' || this.flow === 'hybrid') {
|
|
1381
|
-
if ((parsed.oauthParams.code || parsed.oauthParams.error) && parsed.oauthParams.state) {
|
|
1382
|
-
parsed.oauthParams.redirectUri = redirectUri;
|
|
1383
|
-
return parsed.oauthParams;
|
|
1297
|
+
var src = kc.endpoints.checkSessionIframe();
|
|
1298
|
+
iframe.setAttribute('src', src);
|
|
1299
|
+
iframe.setAttribute('sandbox', 'allow-storage-access-by-user-activation allow-scripts allow-same-origin');
|
|
1300
|
+
iframe.setAttribute('title', 'keycloak-session-iframe');
|
|
1301
|
+
iframe.style.display = 'none';
|
|
1302
|
+
document.body.appendChild(iframe);
|
|
1303
|
+
var messageCallback = function (event) {
|
|
1304
|
+
if ((event.origin !== loginIframe.iframeOrigin) || (loginIframe.iframe.contentWindow !== event.source)) {
|
|
1305
|
+
return;
|
|
1384
1306
|
}
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
if ((parsed.oauthParams.access_token || parsed.oauthParams.error) && parsed.oauthParams.state) {
|
|
1388
|
-
parsed.oauthParams.redirectUri = redirectUri;
|
|
1389
|
-
return parsed.oauthParams;
|
|
1307
|
+
if (!(event.data == 'unchanged' || event.data == 'changed' || event.data == 'error')) {
|
|
1308
|
+
return;
|
|
1390
1309
|
}
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
}, _TideCloak_parseCallbackParams = function _TideCloak_parseCallbackParams(paramsString, supportedParams) {
|
|
1394
|
-
const params = new URLSearchParams(paramsString);
|
|
1395
|
-
/** @type {Record<string, string>} */
|
|
1396
|
-
const oauthParams = {};
|
|
1397
|
-
for (const [key, value] of Array.from(params.entries())) {
|
|
1398
|
-
if (supportedParams.includes(key)) {
|
|
1399
|
-
oauthParams[key] = value;
|
|
1400
|
-
params.delete(key);
|
|
1401
|
-
}
|
|
1402
|
-
}
|
|
1403
|
-
return {
|
|
1404
|
-
paramsString: params.toString(),
|
|
1405
|
-
oauthParams
|
|
1406
|
-
};
|
|
1407
|
-
}, _TideCloak_processCallback = async function _TideCloak_processCallback(oauth) {
|
|
1408
|
-
var _a, _b, _c, _d;
|
|
1409
|
-
const { code, error, prompt, doken } = oauth;
|
|
1410
|
-
let timeLocal = new Date().getTime();
|
|
1411
|
-
/**
|
|
1412
|
-
* @param {string} accessToken
|
|
1413
|
-
* @param {string=} refreshToken
|
|
1414
|
-
* @param {string=} idToken
|
|
1415
|
-
* @param {string=} dokenValue
|
|
1416
|
-
*/
|
|
1417
|
-
const authSuccess = (accessToken, refreshToken, idToken, dokenValue) => {
|
|
1418
|
-
timeLocal = (timeLocal + new Date().getTime()) / 2;
|
|
1419
|
-
__classPrivateFieldGet(this, _TideCloak_instances, "m", _TideCloak_setToken).call(this, accessToken, refreshToken, idToken, timeLocal, dokenValue);
|
|
1420
|
-
if (__classPrivateFieldGet(this, _TideCloak_useNonce, "f") && (this.idTokenParsed && this.idTokenParsed.nonce !== oauth.storedNonce)) {
|
|
1421
|
-
__classPrivateFieldGet(this, _TideCloak_logInfo, "f").call(this, '[TIDECLOAK] Invalid nonce, clearing token');
|
|
1422
|
-
this.clearToken();
|
|
1423
|
-
throw new Error('Invalid nonce.');
|
|
1424
|
-
}
|
|
1425
|
-
};
|
|
1426
|
-
if (oauth.kc_action_status) {
|
|
1427
|
-
this.onActionUpdate && this.onActionUpdate(oauth.kc_action_status, oauth.kc_action);
|
|
1428
|
-
}
|
|
1429
|
-
if (error) {
|
|
1430
|
-
if (prompt !== 'none') {
|
|
1431
|
-
if (oauth.error_description && oauth.error_description === 'authentication_expired') {
|
|
1432
|
-
await this.login(oauth.loginOptions);
|
|
1310
|
+
if (event.data != 'unchanged') {
|
|
1311
|
+
kc.clearToken();
|
|
1433
1312
|
}
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1313
|
+
var callbacks = loginIframe.callbackList.splice(0, loginIframe.callbackList.length);
|
|
1314
|
+
for (var i = callbacks.length - 1; i >= 0; --i) {
|
|
1315
|
+
var promise = callbacks[i];
|
|
1316
|
+
if (event.data == 'error') {
|
|
1317
|
+
promise.setError();
|
|
1318
|
+
}
|
|
1319
|
+
else {
|
|
1320
|
+
promise.setSuccess(event.data == 'unchanged');
|
|
1321
|
+
}
|
|
1322
|
+
}
|
|
1323
|
+
};
|
|
1324
|
+
window.addEventListener('message', messageCallback, false);
|
|
1325
|
+
return promise.promise;
|
|
1326
|
+
}
|
|
1327
|
+
function scheduleCheckIframe() {
|
|
1328
|
+
if (loginIframe.enable) {
|
|
1329
|
+
if (kc.token) {
|
|
1330
|
+
setTimeout(function () {
|
|
1331
|
+
checkLoginIframe().then(function (unchanged) {
|
|
1332
|
+
if (unchanged) {
|
|
1333
|
+
scheduleCheckIframe();
|
|
1334
|
+
}
|
|
1335
|
+
});
|
|
1336
|
+
}, loginIframe.interval * 1000);
|
|
1438
1337
|
}
|
|
1439
1338
|
}
|
|
1440
|
-
return;
|
|
1441
1339
|
}
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
(
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
if (this.flow === 'standard') {
|
|
1451
|
-
(_c = this.onAuthSuccess) === null || _c === void 0 ? void 0 : _c.call(this);
|
|
1340
|
+
function checkLoginIframe() {
|
|
1341
|
+
var promise = createPromise();
|
|
1342
|
+
if (loginIframe.iframe && loginIframe.iframeOrigin) {
|
|
1343
|
+
var msg = kc.clientId + ' ' + (kc.sessionId ? kc.sessionId : '');
|
|
1344
|
+
loginIframe.callbackList.push(promise);
|
|
1345
|
+
var origin = loginIframe.iframeOrigin;
|
|
1346
|
+
if (loginIframe.callbackList.length == 1) {
|
|
1347
|
+
loginIframe.iframe.contentWindow.postMessage(msg, origin);
|
|
1452
1348
|
}
|
|
1453
|
-
__classPrivateFieldGet(this, _TideCloak_instances, "m", _TideCloak_scheduleCheckIframe).call(this);
|
|
1454
1349
|
}
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1350
|
+
else {
|
|
1351
|
+
promise.setSuccess();
|
|
1352
|
+
}
|
|
1353
|
+
return promise.promise;
|
|
1354
|
+
}
|
|
1355
|
+
function check3pCookiesSupported() {
|
|
1356
|
+
var promise = createPromise();
|
|
1357
|
+
if ((loginIframe.enable || kc.silentCheckSsoRedirectUri) && typeof kc.endpoints.thirdPartyCookiesIframe === 'function') {
|
|
1358
|
+
var iframe = document.createElement('iframe');
|
|
1359
|
+
iframe.setAttribute('src', kc.endpoints.thirdPartyCookiesIframe());
|
|
1360
|
+
iframe.setAttribute('sandbox', 'allow-storage-access-by-user-activation allow-scripts allow-same-origin');
|
|
1361
|
+
iframe.setAttribute('title', 'keycloak-3p-check-iframe');
|
|
1362
|
+
iframe.style.display = 'none';
|
|
1363
|
+
document.body.appendChild(iframe);
|
|
1364
|
+
var messageCallback = function (event) {
|
|
1365
|
+
if (iframe.contentWindow !== event.source) {
|
|
1366
|
+
return;
|
|
1367
|
+
}
|
|
1368
|
+
if (event.data !== "supported" && event.data !== "unsupported") {
|
|
1369
|
+
return;
|
|
1370
|
+
}
|
|
1371
|
+
else if (event.data === "unsupported") {
|
|
1372
|
+
logWarn("[TIDECLOAK] Your browser is blocking access to 3rd-party cookies, this means:\n\n" +
|
|
1373
|
+
" - It is not possible to retrieve tokens without redirecting to the TideCloak server (a.k.a. no support for silent authentication).\n" +
|
|
1374
|
+
" - It is not possible to automatically detect changes to the session status (such as the user logging out in another tab).\n\n" +
|
|
1375
|
+
"For more information see: https://www.keycloak.org/securing-apps/javascript-adapter#_modern_browsers");
|
|
1376
|
+
loginIframe.enable = false;
|
|
1377
|
+
if (kc.silentCheckSsoFallback) {
|
|
1378
|
+
kc.silentCheckSsoRedirectUri = false;
|
|
1379
|
+
}
|
|
1380
|
+
}
|
|
1381
|
+
document.body.removeChild(iframe);
|
|
1382
|
+
window.removeEventListener("message", messageCallback);
|
|
1383
|
+
promise.setSuccess();
|
|
1384
|
+
};
|
|
1385
|
+
window.addEventListener('message', messageCallback, false);
|
|
1458
1386
|
}
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
if (__classPrivateFieldGet(this, _TideCloak_loginIframe, "f").enable && this.token) {
|
|
1462
|
-
await waitForTimeout(__classPrivateFieldGet(this, _TideCloak_loginIframe, "f").interval * 1000);
|
|
1463
|
-
const unchanged = await __classPrivateFieldGet(this, _TideCloak_instances, "m", _TideCloak_checkLoginIframe).call(this);
|
|
1464
|
-
if (unchanged) {
|
|
1465
|
-
await __classPrivateFieldGet(this, _TideCloak_instances, "m", _TideCloak_scheduleCheckIframe).call(this);
|
|
1387
|
+
else {
|
|
1388
|
+
promise.setSuccess();
|
|
1466
1389
|
}
|
|
1390
|
+
return applyTimeoutToPromise(promise.promise, kc.messageReceiveTimeout, "Timeout when waiting for 3rd party check iframe message.");
|
|
1467
1391
|
}
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1392
|
+
function loadAdapter(type) {
|
|
1393
|
+
if (!type || type == 'default') {
|
|
1394
|
+
return {
|
|
1395
|
+
login: async function (options) {
|
|
1396
|
+
window.location.assign(await kc.createLoginUrl(options));
|
|
1397
|
+
return createPromise().promise;
|
|
1398
|
+
},
|
|
1399
|
+
logout: async function (options) {
|
|
1400
|
+
var _a;
|
|
1401
|
+
const logoutMethod = (_a = options === null || options === void 0 ? void 0 : options.logoutMethod) !== null && _a !== void 0 ? _a : kc.logoutMethod;
|
|
1402
|
+
if (logoutMethod === "GET") {
|
|
1403
|
+
window.location.replace(kc.createLogoutUrl(options));
|
|
1404
|
+
return;
|
|
1405
|
+
}
|
|
1406
|
+
// Create form to send POST request.
|
|
1407
|
+
const form = document.createElement("form");
|
|
1408
|
+
form.setAttribute("method", "POST");
|
|
1409
|
+
form.setAttribute("action", kc.createLogoutUrl(options));
|
|
1410
|
+
form.style.display = "none";
|
|
1411
|
+
// Add data to form as hidden input fields.
|
|
1412
|
+
const data = {
|
|
1413
|
+
id_token_hint: kc.idToken,
|
|
1414
|
+
client_id: kc.clientId,
|
|
1415
|
+
post_logout_redirect_uri: adapter.redirectUri(options, false)
|
|
1416
|
+
};
|
|
1417
|
+
for (const [name, value] of Object.entries(data)) {
|
|
1418
|
+
const input = document.createElement("input");
|
|
1419
|
+
input.setAttribute("type", "hidden");
|
|
1420
|
+
input.setAttribute("name", name);
|
|
1421
|
+
input.setAttribute("value", value);
|
|
1422
|
+
form.appendChild(input);
|
|
1423
|
+
}
|
|
1424
|
+
// Append form to page and submit it to perform logout and redirect.
|
|
1425
|
+
document.body.appendChild(form);
|
|
1426
|
+
form.submit();
|
|
1427
|
+
},
|
|
1428
|
+
register: async function (options) {
|
|
1429
|
+
window.location.assign(await kc.createRegisterUrl(options));
|
|
1430
|
+
return createPromise().promise;
|
|
1431
|
+
},
|
|
1432
|
+
accountManagement: function () {
|
|
1433
|
+
var accountUrl = kc.createAccountUrl();
|
|
1434
|
+
if (typeof accountUrl !== 'undefined') {
|
|
1435
|
+
window.location.href = accountUrl;
|
|
1436
|
+
}
|
|
1437
|
+
else {
|
|
1438
|
+
throw "Not supported by the OIDC server";
|
|
1439
|
+
}
|
|
1440
|
+
return createPromise().promise;
|
|
1441
|
+
},
|
|
1442
|
+
redirectUri: function (options, encodeHash) {
|
|
1443
|
+
if (arguments.length == 1) {
|
|
1444
|
+
encodeHash = true;
|
|
1445
|
+
}
|
|
1446
|
+
if (options && options.redirectUri) {
|
|
1447
|
+
return options.redirectUri;
|
|
1448
|
+
}
|
|
1449
|
+
else if (kc.redirectUri) {
|
|
1450
|
+
return kc.redirectUri;
|
|
1451
|
+
}
|
|
1452
|
+
else {
|
|
1453
|
+
return location.href;
|
|
1454
|
+
}
|
|
1455
|
+
}
|
|
1456
|
+
};
|
|
1457
|
+
}
|
|
1458
|
+
if (type == 'cordova') {
|
|
1459
|
+
loginIframe.enable = false;
|
|
1460
|
+
var cordovaOpenWindowWrapper = function (loginUrl, target, options) {
|
|
1461
|
+
if (window.cordova && window.cordova.InAppBrowser) {
|
|
1462
|
+
// Use inappbrowser for IOS and Android if available
|
|
1463
|
+
return window.cordova.InAppBrowser.open(loginUrl, target, options);
|
|
1515
1464
|
}
|
|
1516
1465
|
else {
|
|
1517
|
-
|
|
1466
|
+
return window.open(loginUrl, target, options);
|
|
1518
1467
|
}
|
|
1519
|
-
}
|
|
1468
|
+
};
|
|
1469
|
+
var shallowCloneCordovaOptions = function (userOptions) {
|
|
1470
|
+
if (userOptions && userOptions.cordovaOptions) {
|
|
1471
|
+
return Object.keys(userOptions.cordovaOptions).reduce(function (options, optionName) {
|
|
1472
|
+
options[optionName] = userOptions.cordovaOptions[optionName];
|
|
1473
|
+
return options;
|
|
1474
|
+
}, {});
|
|
1475
|
+
}
|
|
1476
|
+
else {
|
|
1477
|
+
return {};
|
|
1478
|
+
}
|
|
1479
|
+
};
|
|
1480
|
+
var formatCordovaOptions = function (cordovaOptions) {
|
|
1481
|
+
return Object.keys(cordovaOptions).reduce(function (options, optionName) {
|
|
1482
|
+
options.push(optionName + "=" + cordovaOptions[optionName]);
|
|
1483
|
+
return options;
|
|
1484
|
+
}, []).join(",");
|
|
1485
|
+
};
|
|
1486
|
+
var createCordovaOptions = function (userOptions) {
|
|
1487
|
+
var cordovaOptions = shallowCloneCordovaOptions(userOptions);
|
|
1488
|
+
cordovaOptions.location = 'no';
|
|
1489
|
+
if (userOptions && userOptions.prompt == 'none') {
|
|
1490
|
+
cordovaOptions.hidden = 'yes';
|
|
1491
|
+
}
|
|
1492
|
+
return formatCordovaOptions(cordovaOptions);
|
|
1493
|
+
};
|
|
1494
|
+
var getCordovaRedirectUri = function () {
|
|
1495
|
+
return kc.redirectUri || 'http://localhost';
|
|
1496
|
+
};
|
|
1497
|
+
return {
|
|
1498
|
+
login: async function (options) {
|
|
1499
|
+
var promise = createPromise();
|
|
1500
|
+
var cordovaOptions = createCordovaOptions(options);
|
|
1501
|
+
var loginUrl = await kc.createLoginUrl(options);
|
|
1502
|
+
var ref = cordovaOpenWindowWrapper(loginUrl, '_blank', cordovaOptions);
|
|
1503
|
+
var completed = false;
|
|
1504
|
+
var closed = false;
|
|
1505
|
+
var closeBrowser = function () {
|
|
1506
|
+
closed = true;
|
|
1507
|
+
ref.close();
|
|
1508
|
+
};
|
|
1509
|
+
ref.addEventListener('loadstart', function (event) {
|
|
1510
|
+
if (event.url.indexOf(getCordovaRedirectUri()) == 0) {
|
|
1511
|
+
var callback = parseCallback(event.url);
|
|
1512
|
+
processCallback(callback, promise);
|
|
1513
|
+
closeBrowser();
|
|
1514
|
+
completed = true;
|
|
1515
|
+
}
|
|
1516
|
+
});
|
|
1517
|
+
ref.addEventListener('loaderror', function (event) {
|
|
1518
|
+
if (!completed) {
|
|
1519
|
+
if (event.url.indexOf(getCordovaRedirectUri()) == 0) {
|
|
1520
|
+
var callback = parseCallback(event.url);
|
|
1521
|
+
processCallback(callback, promise);
|
|
1522
|
+
closeBrowser();
|
|
1523
|
+
completed = true;
|
|
1524
|
+
}
|
|
1525
|
+
else {
|
|
1526
|
+
promise.setError();
|
|
1527
|
+
closeBrowser();
|
|
1528
|
+
}
|
|
1529
|
+
}
|
|
1530
|
+
});
|
|
1531
|
+
ref.addEventListener('exit', function (event) {
|
|
1532
|
+
if (!closed) {
|
|
1533
|
+
promise.setError({
|
|
1534
|
+
reason: "closed_by_user"
|
|
1535
|
+
});
|
|
1536
|
+
}
|
|
1537
|
+
});
|
|
1538
|
+
return promise.promise;
|
|
1539
|
+
},
|
|
1540
|
+
logout: function (options) {
|
|
1541
|
+
var promise = createPromise();
|
|
1542
|
+
var logoutUrl = kc.createLogoutUrl(options);
|
|
1543
|
+
var ref = cordovaOpenWindowWrapper(logoutUrl, '_blank', 'location=no,hidden=yes,clearcache=yes');
|
|
1544
|
+
var error;
|
|
1545
|
+
ref.addEventListener('loadstart', function (event) {
|
|
1546
|
+
if (event.url.indexOf(getCordovaRedirectUri()) == 0) {
|
|
1547
|
+
ref.close();
|
|
1548
|
+
}
|
|
1549
|
+
});
|
|
1550
|
+
ref.addEventListener('loaderror', function (event) {
|
|
1551
|
+
if (event.url.indexOf(getCordovaRedirectUri()) == 0) {
|
|
1552
|
+
ref.close();
|
|
1553
|
+
}
|
|
1554
|
+
else {
|
|
1555
|
+
error = true;
|
|
1556
|
+
ref.close();
|
|
1557
|
+
}
|
|
1558
|
+
});
|
|
1559
|
+
ref.addEventListener('exit', function (event) {
|
|
1560
|
+
if (error) {
|
|
1561
|
+
promise.setError();
|
|
1562
|
+
}
|
|
1563
|
+
else {
|
|
1564
|
+
kc.clearToken();
|
|
1565
|
+
promise.setSuccess();
|
|
1566
|
+
}
|
|
1567
|
+
});
|
|
1568
|
+
return promise.promise;
|
|
1569
|
+
},
|
|
1570
|
+
register: async function (options) {
|
|
1571
|
+
var promise = createPromise();
|
|
1572
|
+
var registerUrl = await kc.createRegisterUrl();
|
|
1573
|
+
var cordovaOptions = createCordovaOptions(options);
|
|
1574
|
+
var ref = cordovaOpenWindowWrapper(registerUrl, '_blank', cordovaOptions);
|
|
1575
|
+
ref.addEventListener('loadstart', function (event) {
|
|
1576
|
+
if (event.url.indexOf(getCordovaRedirectUri()) == 0) {
|
|
1577
|
+
ref.close();
|
|
1578
|
+
var oauth = parseCallback(event.url);
|
|
1579
|
+
processCallback(oauth, promise);
|
|
1580
|
+
}
|
|
1581
|
+
});
|
|
1582
|
+
return promise.promise;
|
|
1583
|
+
},
|
|
1584
|
+
accountManagement: function () {
|
|
1585
|
+
var accountUrl = kc.createAccountUrl();
|
|
1586
|
+
if (typeof accountUrl !== 'undefined') {
|
|
1587
|
+
var ref = cordovaOpenWindowWrapper(accountUrl, '_blank', 'location=no');
|
|
1588
|
+
ref.addEventListener('loadstart', function (event) {
|
|
1589
|
+
if (event.url.indexOf(getCordovaRedirectUri()) == 0) {
|
|
1590
|
+
ref.close();
|
|
1591
|
+
}
|
|
1592
|
+
});
|
|
1593
|
+
}
|
|
1594
|
+
else {
|
|
1595
|
+
throw "Not supported by the OIDC server";
|
|
1596
|
+
}
|
|
1597
|
+
},
|
|
1598
|
+
redirectUri: function (options) {
|
|
1599
|
+
return getCordovaRedirectUri();
|
|
1600
|
+
}
|
|
1601
|
+
};
|
|
1520
1602
|
}
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1603
|
+
if (type == 'cordova-native') {
|
|
1604
|
+
loginIframe.enable = false;
|
|
1605
|
+
return {
|
|
1606
|
+
login: async function (options) {
|
|
1607
|
+
var promise = createPromise();
|
|
1608
|
+
var loginUrl = await kc.createLoginUrl(options);
|
|
1609
|
+
universalLinks.subscribe('keycloak', function (event) {
|
|
1610
|
+
universalLinks.unsubscribe('keycloak');
|
|
1611
|
+
window.cordova.plugins.browsertab.close();
|
|
1612
|
+
var oauth = parseCallback(event.url);
|
|
1613
|
+
processCallback(oauth, promise);
|
|
1614
|
+
});
|
|
1615
|
+
window.cordova.plugins.browsertab.openUrl(loginUrl);
|
|
1616
|
+
return promise.promise;
|
|
1617
|
+
},
|
|
1618
|
+
logout: function (options) {
|
|
1619
|
+
var promise = createPromise();
|
|
1620
|
+
var logoutUrl = kc.createLogoutUrl(options);
|
|
1621
|
+
universalLinks.subscribe('keycloak', function (event) {
|
|
1622
|
+
universalLinks.unsubscribe('keycloak');
|
|
1623
|
+
window.cordova.plugins.browsertab.close();
|
|
1624
|
+
kc.clearToken();
|
|
1625
|
+
promise.setSuccess();
|
|
1626
|
+
});
|
|
1627
|
+
window.cordova.plugins.browsertab.openUrl(logoutUrl);
|
|
1628
|
+
return promise.promise;
|
|
1629
|
+
},
|
|
1630
|
+
register: async function (options) {
|
|
1631
|
+
var promise = createPromise();
|
|
1632
|
+
var registerUrl = await kc.createRegisterUrl(options);
|
|
1633
|
+
universalLinks.subscribe('keycloak', function (event) {
|
|
1634
|
+
universalLinks.unsubscribe('keycloak');
|
|
1635
|
+
window.cordova.plugins.browsertab.close();
|
|
1636
|
+
var oauth = parseCallback(event.url);
|
|
1637
|
+
processCallback(oauth, promise);
|
|
1638
|
+
});
|
|
1639
|
+
window.cordova.plugins.browsertab.openUrl(registerUrl);
|
|
1640
|
+
return promise.promise;
|
|
1641
|
+
},
|
|
1642
|
+
accountManagement: function () {
|
|
1643
|
+
var accountUrl = kc.createAccountUrl();
|
|
1644
|
+
if (typeof accountUrl !== 'undefined') {
|
|
1645
|
+
window.cordova.plugins.browsertab.openUrl(accountUrl);
|
|
1646
|
+
}
|
|
1647
|
+
else {
|
|
1648
|
+
throw "Not supported by the OIDC server";
|
|
1649
|
+
}
|
|
1650
|
+
},
|
|
1651
|
+
redirectUri: function (options) {
|
|
1652
|
+
if (options && options.redirectUri) {
|
|
1653
|
+
return options.redirectUri;
|
|
1654
|
+
}
|
|
1655
|
+
else if (kc.redirectUri) {
|
|
1656
|
+
return kc.redirectUri;
|
|
1657
|
+
}
|
|
1658
|
+
else {
|
|
1659
|
+
return "http://localhost";
|
|
1660
|
+
}
|
|
1661
|
+
}
|
|
1662
|
+
};
|
|
1536
1663
|
}
|
|
1664
|
+
throw 'invalid adapter type: ' + type;
|
|
1537
1665
|
}
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
this.requestEnclave.updateDoken(undefined);
|
|
1666
|
+
const STORAGE_KEY_PREFIX = 'kc-callback-';
|
|
1667
|
+
var LocalStorage = function () {
|
|
1668
|
+
if (!(this instanceof LocalStorage)) {
|
|
1669
|
+
return new LocalStorage();
|
|
1543
1670
|
}
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1671
|
+
localStorage.setItem('kc-test', 'test');
|
|
1672
|
+
localStorage.removeItem('kc-test');
|
|
1673
|
+
var cs = this;
|
|
1674
|
+
/**
|
|
1675
|
+
* Clears all values from local storage that are no longer valid.
|
|
1676
|
+
*/
|
|
1677
|
+
function clearInvalidValues() {
|
|
1678
|
+
const currentTime = Date.now();
|
|
1679
|
+
for (const [key, value] of getStoredEntries()) {
|
|
1680
|
+
// Attempt to parse the expiry time from the value.
|
|
1681
|
+
const expiry = parseExpiry(value);
|
|
1682
|
+
// Discard the value if it is malformed or expired.
|
|
1683
|
+
if (expiry === null || expiry < currentTime) {
|
|
1684
|
+
localStorage.removeItem(key);
|
|
1685
|
+
}
|
|
1686
|
+
}
|
|
1554
1687
|
}
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
if (typeof crypto === 'undefined' || typeof crypto.randomUUID === 'undefined') {
|
|
1563
|
-
throw new Error('Web Crypto API is not available.');
|
|
1564
|
-
}
|
|
1565
|
-
return crypto.randomUUID();
|
|
1566
|
-
}
|
|
1567
|
-
/**
|
|
1568
|
-
* @param {Acr} requestedAcr
|
|
1569
|
-
* @returns {string}
|
|
1570
|
-
*/
|
|
1571
|
-
function buildClaimsParameter(requestedAcr) {
|
|
1572
|
-
return JSON.stringify({
|
|
1573
|
-
id_token: {
|
|
1574
|
-
acr: requestedAcr
|
|
1688
|
+
/**
|
|
1689
|
+
* Clears all known values from local storage.
|
|
1690
|
+
*/
|
|
1691
|
+
function clearAllValues() {
|
|
1692
|
+
for (const [key] of getStoredEntries()) {
|
|
1693
|
+
localStorage.removeItem(key);
|
|
1694
|
+
}
|
|
1575
1695
|
}
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
}
|
|
1602
|
-
/**
|
|
1603
|
-
* @param {number} len
|
|
1604
|
-
* @param {string} alphabet
|
|
1605
|
-
* @returns {string}
|
|
1606
|
-
*/
|
|
1607
|
-
function generateRandomString(len, alphabet) {
|
|
1608
|
-
const randomData = generateRandomData(len);
|
|
1609
|
-
const chars = new Array(len);
|
|
1610
|
-
for (let i = 0; i < len; i++) {
|
|
1611
|
-
chars[i] = alphabet.charCodeAt(randomData[i] % alphabet.length);
|
|
1612
|
-
}
|
|
1613
|
-
return String.fromCharCode.apply(null, chars);
|
|
1614
|
-
}
|
|
1615
|
-
/**
|
|
1616
|
-
* @param {number} len
|
|
1617
|
-
* @returns {Uint8Array<ArrayBuffer>}
|
|
1618
|
-
*/
|
|
1619
|
-
function generateRandomData(len) {
|
|
1620
|
-
if (typeof crypto === 'undefined' || typeof crypto.getRandomValues === 'undefined') {
|
|
1621
|
-
throw new Error('Web Crypto API is not available.');
|
|
1622
|
-
}
|
|
1623
|
-
return crypto.getRandomValues(new Uint8Array(len));
|
|
1624
|
-
}
|
|
1625
|
-
/**
|
|
1626
|
-
* Function to extend existing native Promise with timeout
|
|
1627
|
-
*
|
|
1628
|
-
* @template T
|
|
1629
|
-
* @param {Promise<T>} promise
|
|
1630
|
-
* @param {number} timeout
|
|
1631
|
-
* @param {string} errorMessage
|
|
1632
|
-
* @returns {Promise<T>}
|
|
1633
|
-
*/
|
|
1634
|
-
function applyTimeoutToPromise(promise, timeout, errorMessage) {
|
|
1635
|
-
/** @type {number} */
|
|
1636
|
-
let timeoutHandle;
|
|
1637
|
-
const timeoutPromise = new Promise(function (resolve, reject) {
|
|
1638
|
-
timeoutHandle = window.setTimeout(function () {
|
|
1639
|
-
reject(new Error(errorMessage || 'Promise is not settled within timeout of ' + timeout + 'ms'));
|
|
1640
|
-
}, timeout);
|
|
1641
|
-
});
|
|
1642
|
-
return Promise.race([promise, timeoutPromise]).finally(function () {
|
|
1643
|
-
clearTimeout(timeoutHandle);
|
|
1644
|
-
});
|
|
1645
|
-
}
|
|
1646
|
-
/**
|
|
1647
|
-
* @returns {CallbackStorage}
|
|
1648
|
-
*/
|
|
1649
|
-
function createCallbackStorage() {
|
|
1650
|
-
try {
|
|
1651
|
-
return new LocalStorage();
|
|
1652
|
-
}
|
|
1653
|
-
catch (err) {
|
|
1654
|
-
return new CookieStorage();
|
|
1655
|
-
}
|
|
1656
|
-
}
|
|
1657
|
-
const STORAGE_KEY_PREFIX = 'kc-callback-';
|
|
1658
|
-
/**
|
|
1659
|
-
* @typedef {Object} CallbackState
|
|
1660
|
-
* @property {string} state
|
|
1661
|
-
* @property {string} nonce
|
|
1662
|
-
* @property {string} redirectUri
|
|
1663
|
-
* @property {KeycloakLoginOptions} [loginOptions]
|
|
1664
|
-
* @property {KeycloakLoginOptions['prompt']} [prompt]
|
|
1665
|
-
* @property {string} [pkceCodeVerifier]
|
|
1666
|
-
*/
|
|
1667
|
-
/**
|
|
1668
|
-
* @typedef {Object} CallbackStorage
|
|
1669
|
-
* @property {(state?: string) => CallbackState | null} get
|
|
1670
|
-
* @property {(state: CallbackState) => void} add
|
|
1671
|
-
*/
|
|
1672
|
-
/**
|
|
1673
|
-
* @implements {CallbackStorage}
|
|
1674
|
-
*/
|
|
1675
|
-
class LocalStorage {
|
|
1676
|
-
constructor() {
|
|
1677
|
-
_LocalStorage_instances.add(this);
|
|
1678
|
-
globalThis.localStorage.setItem('kc-test', 'test');
|
|
1679
|
-
globalThis.localStorage.removeItem('kc-test');
|
|
1680
|
-
}
|
|
1681
|
-
/**
|
|
1682
|
-
* @param {string} [state]
|
|
1683
|
-
* @returns {CallbackState | null}
|
|
1684
|
-
*/
|
|
1685
|
-
get(state) {
|
|
1686
|
-
if (!state) {
|
|
1696
|
+
/**
|
|
1697
|
+
* Gets all entries stored in local storage that are known to be managed by this class.
|
|
1698
|
+
* @returns {Array<[string, unknown]>} An array of key-value pairs.
|
|
1699
|
+
*/
|
|
1700
|
+
function getStoredEntries() {
|
|
1701
|
+
return Object.entries(localStorage).filter(([key]) => key.startsWith(STORAGE_KEY_PREFIX));
|
|
1702
|
+
}
|
|
1703
|
+
/**
|
|
1704
|
+
* Parses the expiry time from a value stored in local storage.
|
|
1705
|
+
* @param {unknown} value
|
|
1706
|
+
* @returns {number | null} The expiry time in milliseconds, or `null` if the value is malformed.
|
|
1707
|
+
*/
|
|
1708
|
+
function parseExpiry(value) {
|
|
1709
|
+
let parsedValue;
|
|
1710
|
+
// Attempt to parse the value as JSON.
|
|
1711
|
+
try {
|
|
1712
|
+
parsedValue = JSON.parse(value);
|
|
1713
|
+
}
|
|
1714
|
+
catch (error) {
|
|
1715
|
+
return null;
|
|
1716
|
+
}
|
|
1717
|
+
// Attempt to extract the 'expires' property.
|
|
1718
|
+
if (isObject(parsedValue) && 'expires' in parsedValue && typeof parsedValue.expires === 'number') {
|
|
1719
|
+
return parsedValue.expires;
|
|
1720
|
+
}
|
|
1687
1721
|
return null;
|
|
1688
1722
|
}
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1723
|
+
cs.get = function (state) {
|
|
1724
|
+
if (!state) {
|
|
1725
|
+
return;
|
|
1726
|
+
}
|
|
1727
|
+
var key = STORAGE_KEY_PREFIX + state;
|
|
1728
|
+
var value = localStorage.getItem(key);
|
|
1729
|
+
if (value) {
|
|
1730
|
+
localStorage.removeItem(key);
|
|
1731
|
+
value = JSON.parse(value);
|
|
1732
|
+
}
|
|
1733
|
+
clearInvalidValues();
|
|
1734
|
+
return value;
|
|
1735
|
+
};
|
|
1736
|
+
cs.add = function (state) {
|
|
1737
|
+
clearInvalidValues();
|
|
1738
|
+
const key = STORAGE_KEY_PREFIX + state.state;
|
|
1739
|
+
const value = JSON.stringify({
|
|
1740
|
+
...state,
|
|
1741
|
+
// Set the expiry time to 1 hour from now.
|
|
1742
|
+
expires: Date.now() + (60 * 60 * 1000)
|
|
1743
|
+
});
|
|
1744
|
+
try {
|
|
1745
|
+
localStorage.setItem(key, value);
|
|
1746
|
+
}
|
|
1747
|
+
catch (error) {
|
|
1748
|
+
// If the storage is full, clear all known values and try again.
|
|
1749
|
+
clearAllValues();
|
|
1750
|
+
localStorage.setItem(key, value);
|
|
1751
|
+
}
|
|
1752
|
+
};
|
|
1753
|
+
};
|
|
1754
|
+
var CookieStorage = function () {
|
|
1755
|
+
if (!(this instanceof CookieStorage)) {
|
|
1756
|
+
return new CookieStorage();
|
|
1695
1757
|
}
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
}
|
|
1758
|
+
var cs = this;
|
|
1759
|
+
cs.get = function (state) {
|
|
1760
|
+
if (!state) {
|
|
1761
|
+
return;
|
|
1762
|
+
}
|
|
1763
|
+
var value = getCookie(STORAGE_KEY_PREFIX + state);
|
|
1764
|
+
setCookie(STORAGE_KEY_PREFIX + state, '', cookieExpiration(-100));
|
|
1765
|
+
if (value) {
|
|
1766
|
+
return JSON.parse(value);
|
|
1767
|
+
}
|
|
1768
|
+
};
|
|
1769
|
+
cs.add = function (state) {
|
|
1770
|
+
setCookie(STORAGE_KEY_PREFIX + state.state, JSON.stringify(state), cookieExpiration(60));
|
|
1771
|
+
};
|
|
1772
|
+
cs.removeItem = function (key) {
|
|
1773
|
+
setCookie(key, '', cookieExpiration(-100));
|
|
1774
|
+
};
|
|
1775
|
+
var cookieExpiration = function (minutes) {
|
|
1776
|
+
var exp = new Date();
|
|
1777
|
+
exp.setTime(exp.getTime() + (minutes * 60 * 1000));
|
|
1778
|
+
return exp;
|
|
1779
|
+
};
|
|
1780
|
+
var getCookie = function (key) {
|
|
1781
|
+
var name = key + '=';
|
|
1782
|
+
var ca = document.cookie.split(';');
|
|
1783
|
+
for (var i = 0; i < ca.length; i++) {
|
|
1784
|
+
var c = ca[i];
|
|
1785
|
+
while (c.charAt(0) == ' ') {
|
|
1786
|
+
c = c.substring(1);
|
|
1787
|
+
}
|
|
1788
|
+
if (c.indexOf(name) == 0) {
|
|
1789
|
+
return c.substring(name.length, c.length);
|
|
1790
|
+
}
|
|
1791
|
+
}
|
|
1792
|
+
return '';
|
|
1793
|
+
};
|
|
1794
|
+
var setCookie = function (key, value, expirationDate) {
|
|
1795
|
+
var cookie = key + '=' + value + '; '
|
|
1796
|
+
+ 'expires=' + expirationDate.toUTCString() + '; ';
|
|
1797
|
+
document.cookie = cookie;
|
|
1798
|
+
};
|
|
1799
|
+
};
|
|
1800
|
+
function createCallbackStorage() {
|
|
1710
1801
|
try {
|
|
1711
|
-
|
|
1712
|
-
}
|
|
1713
|
-
catch (error) {
|
|
1714
|
-
// If the storage is full, clear all known values and try again.
|
|
1715
|
-
__classPrivateFieldGet(this, _LocalStorage_instances, "m", _LocalStorage_clearAllValues).call(this);
|
|
1716
|
-
globalThis.localStorage.setItem(key, value);
|
|
1717
|
-
}
|
|
1718
|
-
}
|
|
1719
|
-
;
|
|
1720
|
-
}
|
|
1721
|
-
_LocalStorage_instances = new WeakSet(), _LocalStorage_clearInvalidValues = function _LocalStorage_clearInvalidValues() {
|
|
1722
|
-
const currentTime = Date.now();
|
|
1723
|
-
for (const [key, value] of __classPrivateFieldGet(this, _LocalStorage_instances, "m", _LocalStorage_getStoredEntries).call(this)) {
|
|
1724
|
-
// Attempt to parse the expiry time from the value.
|
|
1725
|
-
const expiry = __classPrivateFieldGet(this, _LocalStorage_instances, "m", _LocalStorage_parseExpiry).call(this, value);
|
|
1726
|
-
// Discard the value if it is malformed or expired.
|
|
1727
|
-
if (expiry === null || expiry < currentTime) {
|
|
1728
|
-
globalThis.localStorage.removeItem(key);
|
|
1729
|
-
}
|
|
1730
|
-
}
|
|
1731
|
-
}, _LocalStorage_clearAllValues = function _LocalStorage_clearAllValues() {
|
|
1732
|
-
for (const [key] of __classPrivateFieldGet(this, _LocalStorage_instances, "m", _LocalStorage_getStoredEntries).call(this)) {
|
|
1733
|
-
globalThis.localStorage.removeItem(key);
|
|
1734
|
-
}
|
|
1735
|
-
}, _LocalStorage_getStoredEntries = function _LocalStorage_getStoredEntries() {
|
|
1736
|
-
return Object.entries(globalThis.localStorage).filter(([key]) => key.startsWith(STORAGE_KEY_PREFIX));
|
|
1737
|
-
}, _LocalStorage_parseExpiry = function _LocalStorage_parseExpiry(value) {
|
|
1738
|
-
let parsedValue;
|
|
1739
|
-
// Attempt to parse the value as JSON.
|
|
1740
|
-
try {
|
|
1741
|
-
parsedValue = JSON.parse(value);
|
|
1742
|
-
}
|
|
1743
|
-
catch (error) {
|
|
1744
|
-
return null;
|
|
1745
|
-
}
|
|
1746
|
-
// Attempt to extract the 'expires' property.
|
|
1747
|
-
if (isObject(parsedValue) && 'expires' in parsedValue && typeof parsedValue.expires === 'number') {
|
|
1748
|
-
return parsedValue.expires;
|
|
1749
|
-
}
|
|
1750
|
-
return null;
|
|
1751
|
-
};
|
|
1752
|
-
/**
|
|
1753
|
-
* @implements {CallbackStorage}
|
|
1754
|
-
*/
|
|
1755
|
-
class CookieStorage {
|
|
1756
|
-
constructor() {
|
|
1757
|
-
_CookieStorage_instances.add(this);
|
|
1758
|
-
}
|
|
1759
|
-
/**
|
|
1760
|
-
* @param {string} [state]
|
|
1761
|
-
* @returns {CallbackState | null}
|
|
1762
|
-
*/
|
|
1763
|
-
get(state) {
|
|
1764
|
-
if (!state) {
|
|
1765
|
-
return null;
|
|
1802
|
+
return new LocalStorage();
|
|
1766
1803
|
}
|
|
1767
|
-
|
|
1768
|
-
__classPrivateFieldGet(this, _CookieStorage_instances, "m", _CookieStorage_setCookie).call(this, STORAGE_KEY_PREFIX + state, '', __classPrivateFieldGet(this, _CookieStorage_instances, "m", _CookieStorage_cookieExpiration).call(this, -100));
|
|
1769
|
-
if (value) {
|
|
1770
|
-
return JSON.parse(value);
|
|
1804
|
+
catch (err) {
|
|
1771
1805
|
}
|
|
1772
|
-
return
|
|
1806
|
+
return new CookieStorage();
|
|
1773
1807
|
}
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1808
|
+
function createLogger(fn) {
|
|
1809
|
+
return function () {
|
|
1810
|
+
if (kc.enableLogging) {
|
|
1811
|
+
fn.apply(console, Array.prototype.slice.call(arguments));
|
|
1812
|
+
}
|
|
1813
|
+
};
|
|
1779
1814
|
}
|
|
1780
1815
|
}
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
const ca = document.cookie.split(';');
|
|
1784
|
-
for (let i = 0; i < ca.length; i++) {
|
|
1785
|
-
let c = ca[i];
|
|
1786
|
-
while (c.charAt(0) === ' ') {
|
|
1787
|
-
c = c.substring(1);
|
|
1788
|
-
}
|
|
1789
|
-
if (c.indexOf(name) === 0) {
|
|
1790
|
-
return c.substring(name.length, c.length);
|
|
1791
|
-
}
|
|
1792
|
-
}
|
|
1793
|
-
return '';
|
|
1794
|
-
}, _CookieStorage_setCookie = function _CookieStorage_setCookie(key, value, expirationDate) {
|
|
1795
|
-
const cookie = key + '=' + value + '; ' +
|
|
1796
|
-
'expires=' + expirationDate.toUTCString() + '; ';
|
|
1797
|
-
document.cookie = cookie;
|
|
1798
|
-
}, _CookieStorage_cookieExpiration = function _CookieStorage_cookieExpiration(minutes) {
|
|
1799
|
-
const exp = new Date();
|
|
1800
|
-
exp.setTime(exp.getTime() + (minutes * 60 * 1000));
|
|
1801
|
-
return exp;
|
|
1802
|
-
};
|
|
1816
|
+
export default TideCloak;
|
|
1817
|
+
export { RequestEnclave, ApprovalEnclave } from "heimdall-tide";
|
|
1803
1818
|
/**
|
|
1804
|
-
* @param {
|
|
1819
|
+
* @param {ArrayBuffer} bytes
|
|
1805
1820
|
* @see https://developer.mozilla.org/en-US/docs/Glossary/Base64#the_unicode_problem
|
|
1806
1821
|
*/
|
|
1807
1822
|
function bytesToBase64(bytes) {
|
|
@@ -1811,30 +1826,19 @@ function bytesToBase64(bytes) {
|
|
|
1811
1826
|
/**
|
|
1812
1827
|
* @param {string} base64
|
|
1813
1828
|
* @returns {Uint8Array}
|
|
1829
|
+
* @see https://developer.mozilla.org/en-US/docs/Glossary/Base64#the_unicode_problem
|
|
1814
1830
|
*/
|
|
1815
1831
|
function base64ToBytes(base64) {
|
|
1832
|
+
// Decode to “binary” JS string where each char’s code point 0–255 is one byte
|
|
1816
1833
|
const binString = atob(base64);
|
|
1817
1834
|
const len = binString.length;
|
|
1818
1835
|
const bytes = new Uint8Array(len);
|
|
1819
1836
|
for (let i = 0; i < len; i++) {
|
|
1837
|
+
// codePointAt is safe here because each char was originally from 0–255
|
|
1820
1838
|
bytes[i] = binString.codePointAt(i);
|
|
1821
1839
|
}
|
|
1822
1840
|
return bytes;
|
|
1823
1841
|
}
|
|
1824
|
-
/**
|
|
1825
|
-
* @param {string} string
|
|
1826
|
-
*/
|
|
1827
|
-
function StringToUint8Array(string) {
|
|
1828
|
-
const enc = new TextEncoder();
|
|
1829
|
-
return enc.encode(string);
|
|
1830
|
-
}
|
|
1831
|
-
/**
|
|
1832
|
-
* @param {Uint8Array} bytes
|
|
1833
|
-
*/
|
|
1834
|
-
function StringFromUint8Array(bytes) {
|
|
1835
|
-
const decoder = new TextDecoder('utf-8');
|
|
1836
|
-
return decoder.decode(bytes);
|
|
1837
|
-
}
|
|
1838
1842
|
/**
|
|
1839
1843
|
* @param {string} message
|
|
1840
1844
|
* @see https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest#basic_example
|
|
@@ -1842,32 +1846,31 @@ function StringFromUint8Array(bytes) {
|
|
|
1842
1846
|
async function sha256Digest(message) {
|
|
1843
1847
|
const encoder = new TextEncoder();
|
|
1844
1848
|
const data = encoder.encode(message);
|
|
1845
|
-
if (typeof crypto ===
|
|
1846
|
-
throw new Error(
|
|
1849
|
+
if (typeof crypto === "undefined" || typeof crypto.subtle === "undefined") {
|
|
1850
|
+
throw new Error("Web Crypto API is not available.");
|
|
1847
1851
|
}
|
|
1848
|
-
return await crypto.subtle.digest(
|
|
1852
|
+
return await crypto.subtle.digest("SHA-256", data);
|
|
1849
1853
|
}
|
|
1850
1854
|
/**
|
|
1851
1855
|
* @param {string} token
|
|
1852
|
-
* @returns {KeycloakTokenParsed}
|
|
1853
1856
|
*/
|
|
1854
1857
|
function decodeToken(token) {
|
|
1855
|
-
const [, payload] = token.split(
|
|
1856
|
-
if (typeof payload !==
|
|
1857
|
-
throw new Error(
|
|
1858
|
+
const [header, payload] = token.split(".");
|
|
1859
|
+
if (typeof payload !== "string") {
|
|
1860
|
+
throw new Error("Unable to decode token, payload not found.");
|
|
1858
1861
|
}
|
|
1859
1862
|
let decoded;
|
|
1860
1863
|
try {
|
|
1861
1864
|
decoded = base64UrlDecode(payload);
|
|
1862
1865
|
}
|
|
1863
1866
|
catch (error) {
|
|
1864
|
-
throw new Error(
|
|
1867
|
+
throw new Error("Unable to decode token, payload is not a valid Base64URL value.", { cause: error });
|
|
1865
1868
|
}
|
|
1866
1869
|
try {
|
|
1867
1870
|
return JSON.parse(decoded);
|
|
1868
1871
|
}
|
|
1869
1872
|
catch (error) {
|
|
1870
|
-
throw new Error(
|
|
1873
|
+
throw new Error("Unable to decode token, payload is not a valid JSON value.", { cause: error });
|
|
1871
1874
|
}
|
|
1872
1875
|
}
|
|
1873
1876
|
/**
|
|
@@ -1875,19 +1878,19 @@ function decodeToken(token) {
|
|
|
1875
1878
|
*/
|
|
1876
1879
|
function base64UrlDecode(input) {
|
|
1877
1880
|
let output = input
|
|
1878
|
-
.replaceAll(
|
|
1879
|
-
.replaceAll(
|
|
1881
|
+
.replaceAll("-", "+")
|
|
1882
|
+
.replaceAll("_", "/");
|
|
1880
1883
|
switch (output.length % 4) {
|
|
1881
1884
|
case 0:
|
|
1882
1885
|
break;
|
|
1883
1886
|
case 2:
|
|
1884
|
-
output +=
|
|
1887
|
+
output += "==";
|
|
1885
1888
|
break;
|
|
1886
1889
|
case 3:
|
|
1887
|
-
output +=
|
|
1890
|
+
output += "=";
|
|
1888
1891
|
break;
|
|
1889
1892
|
default:
|
|
1890
|
-
throw new Error(
|
|
1893
|
+
throw new Error("Input is not of the correct length.");
|
|
1891
1894
|
}
|
|
1892
1895
|
try {
|
|
1893
1896
|
return b64DecodeUnicode(output);
|
|
@@ -1903,9 +1906,9 @@ function b64DecodeUnicode(input) {
|
|
|
1903
1906
|
return decodeURIComponent(atob(input).replace(/(.)/g, (m, p) => {
|
|
1904
1907
|
let code = p.charCodeAt(0).toString(16).toUpperCase();
|
|
1905
1908
|
if (code.length < 2) {
|
|
1906
|
-
code =
|
|
1909
|
+
code = "0" + code;
|
|
1907
1910
|
}
|
|
1908
|
-
return
|
|
1911
|
+
return "%" + code;
|
|
1909
1912
|
}));
|
|
1910
1913
|
}
|
|
1911
1914
|
/**
|
|
@@ -1915,152 +1918,8 @@ function b64DecodeUnicode(input) {
|
|
|
1915
1918
|
function isObject(input) {
|
|
1916
1919
|
return typeof input === 'object' && input !== null;
|
|
1917
1920
|
}
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
* @property {string} auth-server-url The URL of the authentication server.
|
|
1921
|
-
* @property {string} realm The name of the realm.
|
|
1922
|
-
* @property {string} resource The name of the resource, usually the client ID.
|
|
1923
|
-
*/
|
|
1924
|
-
/**
|
|
1925
|
-
* Fetch the adapter configuration from the given URL.
|
|
1926
|
-
* @param {string} url
|
|
1927
|
-
* @returns {Promise<JsonConfig>}
|
|
1928
|
-
*/
|
|
1929
|
-
async function fetchJsonConfig(url) {
|
|
1930
|
-
return await fetchJSON(url);
|
|
1931
|
-
}
|
|
1932
|
-
/**
|
|
1933
|
-
* Fetch the OpenID configuration from the given URL.
|
|
1934
|
-
* @param {string} url
|
|
1935
|
-
* @returns {Promise<OpenIdProviderMetadata>}
|
|
1936
|
-
*/
|
|
1937
|
-
async function fetchOpenIdConfig(url) {
|
|
1938
|
-
return await fetchJSON(url);
|
|
1921
|
+
export function getHumanReadableObject(modelId, data, expiry) {
|
|
1922
|
+
return ModelRegistry.getHumanReadableModelBuilder(modelId, data, expiry).getHumanReadableObject();
|
|
1939
1923
|
}
|
|
1940
|
-
|
|
1941
|
-
* @typedef {Object} AccessTokenResponse The successful token response from the authorization server, based on the {@link https://datatracker.ietf.org/doc/html/rfc6749#section-5.1 OAuth 2.0 Authorization Framework specification}.
|
|
1942
|
-
* @property {string} access_token The access token issued by the authorization server.
|
|
1943
|
-
* @property {string} token_type The type of the token issued by the authorization server.
|
|
1944
|
-
* @property {number} [expires_in] The lifetime in seconds of the access token.
|
|
1945
|
-
* @property {string} [refresh_token] The refresh token issued by the authorization server.
|
|
1946
|
-
* @property {string} [id_token] The ID token issued by the authorization server, if requested.
|
|
1947
|
-
* @property {string} [scope] The scope of the access token.
|
|
1948
|
-
*/
|
|
1949
|
-
/**
|
|
1950
|
-
* Fetch the access token from the given URL.
|
|
1951
|
-
* @param {string} url
|
|
1952
|
-
* @param {string} code
|
|
1953
|
-
* @param {string} clientId
|
|
1954
|
-
* @param {string} redirectUri
|
|
1955
|
-
* @param {string} [pkceCodeVerifier]
|
|
1956
|
-
* @returns {Promise<AccessTokenResponse>}
|
|
1957
|
-
*/
|
|
1958
|
-
async function fetchAccessToken(url, code, clientId, redirectUri, pkceCodeVerifier) {
|
|
1959
|
-
const body = new URLSearchParams([
|
|
1960
|
-
['code', code],
|
|
1961
|
-
['grant_type', 'authorization_code'],
|
|
1962
|
-
['client_id', clientId],
|
|
1963
|
-
['redirect_uri', stripHash(redirectUri)]
|
|
1964
|
-
]);
|
|
1965
|
-
if (pkceCodeVerifier) {
|
|
1966
|
-
body.append('code_verifier', pkceCodeVerifier);
|
|
1967
|
-
}
|
|
1968
|
-
return await fetchJSON(url, {
|
|
1969
|
-
method: 'POST',
|
|
1970
|
-
credentials: 'include',
|
|
1971
|
-
body
|
|
1972
|
-
});
|
|
1973
|
-
}
|
|
1974
|
-
/**
|
|
1975
|
-
* Fetch the refresh token from the given URL.
|
|
1976
|
-
* @param {string} url
|
|
1977
|
-
* @param {string} refreshToken
|
|
1978
|
-
* @param {string} clientId
|
|
1979
|
-
* @returns {Promise<AccessTokenResponse>}
|
|
1980
|
-
*/
|
|
1981
|
-
async function fetchRefreshToken(url, refreshToken, clientId) {
|
|
1982
|
-
const body = new URLSearchParams([
|
|
1983
|
-
['grant_type', 'refresh_token'],
|
|
1984
|
-
['refresh_token', refreshToken],
|
|
1985
|
-
['client_id', clientId]
|
|
1986
|
-
]);
|
|
1987
|
-
return await fetchJSON(url, {
|
|
1988
|
-
method: 'POST',
|
|
1989
|
-
credentials: 'include',
|
|
1990
|
-
body
|
|
1991
|
-
});
|
|
1992
|
-
}
|
|
1993
|
-
/**
|
|
1994
|
-
* @template [T=unknown]
|
|
1995
|
-
* @param {string} url
|
|
1996
|
-
* @param {RequestInit} init
|
|
1997
|
-
* @returns {Promise<T>}
|
|
1998
|
-
*/
|
|
1999
|
-
async function fetchJSON(url, init = {}) {
|
|
2000
|
-
const headers = new Headers(init.headers);
|
|
2001
|
-
headers.set('Accept', CONTENT_TYPE_JSON);
|
|
2002
|
-
const response = await fetchWithErrorHandling(url, {
|
|
2003
|
-
...init,
|
|
2004
|
-
headers
|
|
2005
|
-
});
|
|
2006
|
-
return await response.json();
|
|
2007
|
-
}
|
|
2008
|
-
/**
|
|
2009
|
-
* @param {string} url
|
|
2010
|
-
* @param {RequestInit} [init]
|
|
2011
|
-
* @returns {Promise<Response>}
|
|
2012
|
-
*/
|
|
2013
|
-
async function fetchWithErrorHandling(url, init) {
|
|
2014
|
-
const response = await fetch(url, init);
|
|
2015
|
-
if (!response.ok) {
|
|
2016
|
-
throw new NetworkError('Server responded with an invalid status.', { response });
|
|
2017
|
-
}
|
|
2018
|
-
return response;
|
|
2019
|
-
}
|
|
2020
|
-
/**
|
|
2021
|
-
* @param {string} [token]
|
|
2022
|
-
* @returns {[string, string]}
|
|
2023
|
-
*/
|
|
2024
|
-
function buildAuthorizationHeader(token) {
|
|
2025
|
-
if (!token) {
|
|
2026
|
-
throw new Error('Unable to build authorization header, token is not set, make sure the user is authenticated.');
|
|
2027
|
-
}
|
|
2028
|
-
return ['Authorization', `bearer ${token}`];
|
|
2029
|
-
}
|
|
2030
|
-
/**
|
|
2031
|
-
* @param {string} url
|
|
2032
|
-
* @returns {string}
|
|
2033
|
-
*/
|
|
2034
|
-
function stripTrailingSlash(url) {
|
|
2035
|
-
return url.endsWith('/') ? url.slice(0, -1) : url;
|
|
2036
|
-
}
|
|
2037
|
-
/**
|
|
2038
|
-
* @param {string} url
|
|
2039
|
-
* @returns {string}
|
|
2040
|
-
*/
|
|
2041
|
-
function stripHash(url) {
|
|
2042
|
-
const parsedUrl = new URL(url);
|
|
2043
|
-
parsedUrl.hash = '';
|
|
2044
|
-
return parsedUrl.toString();
|
|
2045
|
-
}
|
|
2046
|
-
/**
|
|
2047
|
-
* @typedef {Object} NetworkErrorOptionsProperties
|
|
2048
|
-
* @property {Response} response
|
|
2049
|
-
* @typedef {ErrorOptions & NetworkErrorOptionsProperties} NetworkErrorOptions
|
|
2050
|
-
*/
|
|
2051
|
-
export class NetworkError extends Error {
|
|
2052
|
-
/**
|
|
2053
|
-
* @param {string} message
|
|
2054
|
-
* @param {NetworkErrorOptions} options
|
|
2055
|
-
*/
|
|
2056
|
-
constructor(message, options) {
|
|
2057
|
-
super(message, options);
|
|
2058
|
-
this.response = options.response;
|
|
2059
|
-
}
|
|
2060
|
-
}
|
|
2061
|
-
/**
|
|
2062
|
-
* @param {number} delay
|
|
2063
|
-
* @returns {Promise<void>}
|
|
2064
|
-
*/
|
|
2065
|
-
const waitForTimeout = (delay) => new Promise((resolve) => setTimeout(resolve, delay));
|
|
1924
|
+
export { bytesToBase64, base64ToBytes } from "../modules/tide-js/Cryptide/Serialization.js";
|
|
2066
1925
|
//# sourceMappingURL=tidecloak.js.map
|