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