@ghentcdh/authentication-vue 0.2.2 → 0.3.0
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/index.mjs +1116 -819
- package/package.json +1 -1
package/index.mjs
CHANGED
|
@@ -1,428 +1,552 @@
|
|
|
1
|
-
import { ref as
|
|
2
|
-
const
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
1
|
+
import { ref as P, markRaw as I, watch as L, inject as C } from "vue";
|
|
2
|
+
const T = "GHENTCDH_AUTHENTICATION", R = "application/json";
|
|
3
|
+
class x {
|
|
4
|
+
/** @type {Pick<PromiseWithResolvers<boolean>, 'resolve' | 'reject'>[]} */
|
|
5
|
+
#r = [];
|
|
6
|
+
/** @type {KeycloakAdapter} */
|
|
7
|
+
#t;
|
|
8
|
+
/** @type {boolean} */
|
|
9
|
+
#o = !0;
|
|
10
|
+
/** @type {CallbackStorage} */
|
|
11
|
+
#l;
|
|
12
|
+
#n = this.#b(console.info);
|
|
13
|
+
#u = this.#b(console.warn);
|
|
14
|
+
/** @type {LoginIframe} */
|
|
15
|
+
#e = {
|
|
15
16
|
enable: !0,
|
|
16
17
|
callbackList: [],
|
|
17
18
|
interval: 5
|
|
18
19
|
};
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
/** @type {KeycloakConfig} config */
|
|
21
|
+
#i;
|
|
22
|
+
didInitialize = !1;
|
|
23
|
+
authenticated = !1;
|
|
24
|
+
loginRequired = !1;
|
|
25
|
+
/** @type {KeycloakResponseMode} */
|
|
26
|
+
responseMode = "fragment";
|
|
27
|
+
/** @type {KeycloakResponseType} */
|
|
28
|
+
responseType = "code";
|
|
29
|
+
/** @type {KeycloakFlow} */
|
|
30
|
+
flow = "standard";
|
|
31
|
+
/** @type {number?} */
|
|
32
|
+
timeSkew = null;
|
|
33
|
+
/** @type {string=} */
|
|
34
|
+
redirectUri;
|
|
35
|
+
/** @type {string=} */
|
|
36
|
+
silentCheckSsoRedirectUri;
|
|
37
|
+
/** @type {boolean} */
|
|
38
|
+
silentCheckSsoFallback = !0;
|
|
39
|
+
/** @type {KeycloakPkceMethod} */
|
|
40
|
+
pkceMethod = "S256";
|
|
41
|
+
enableLogging = !1;
|
|
42
|
+
/** @type {'GET' | 'POST'} */
|
|
43
|
+
logoutMethod = "GET";
|
|
44
|
+
/** @type {string=} */
|
|
45
|
+
scope;
|
|
46
|
+
messageReceiveTimeout = 1e4;
|
|
47
|
+
/** @type {string=} */
|
|
48
|
+
idToken;
|
|
49
|
+
/** @type {KeycloakTokenParsed=} */
|
|
50
|
+
idTokenParsed;
|
|
51
|
+
/** @type {string=} */
|
|
52
|
+
token;
|
|
53
|
+
/** @type {KeycloakTokenParsed=} */
|
|
54
|
+
tokenParsed;
|
|
55
|
+
/** @type {string=} */
|
|
56
|
+
refreshToken;
|
|
57
|
+
/** @type {KeycloakTokenParsed=} */
|
|
58
|
+
refreshTokenParsed;
|
|
59
|
+
/** @type {string=} */
|
|
60
|
+
clientId;
|
|
61
|
+
/** @type {string=} */
|
|
62
|
+
sessionId;
|
|
63
|
+
/** @type {string=} */
|
|
64
|
+
subject;
|
|
65
|
+
/** @type {string=} */
|
|
66
|
+
authServerUrl;
|
|
67
|
+
/** @type {string=} */
|
|
68
|
+
realm;
|
|
69
|
+
/** @type {KeycloakRoles=} */
|
|
70
|
+
realmAccess;
|
|
71
|
+
/** @type {KeycloakResourceAccess=} */
|
|
72
|
+
resourceAccess;
|
|
73
|
+
/** @type {KeycloakProfile=} */
|
|
74
|
+
profile;
|
|
75
|
+
/** @type {{}=} */
|
|
76
|
+
userInfo;
|
|
77
|
+
/** @type {Endpoints} */
|
|
78
|
+
endpoints;
|
|
79
|
+
/** @type {number=} */
|
|
80
|
+
tokenTimeoutHandle;
|
|
81
|
+
/** @type {() => void=} */
|
|
82
|
+
onAuthSuccess;
|
|
83
|
+
/** @type {(errorData?: KeycloakError) => void=} */
|
|
84
|
+
onAuthError;
|
|
85
|
+
/** @type {() => void=} */
|
|
86
|
+
onAuthRefreshSuccess;
|
|
87
|
+
/** @type {() => void=} */
|
|
88
|
+
onAuthRefreshError;
|
|
89
|
+
/** @type {() => void=} */
|
|
90
|
+
onTokenExpired;
|
|
91
|
+
/** @type {() => void=} */
|
|
92
|
+
onAuthLogout;
|
|
93
|
+
/** @type {(authenticated: boolean) => void=} */
|
|
94
|
+
onReady;
|
|
95
|
+
/** @type {(status: 'success' | 'cancelled' | 'error', action: string) => void=} */
|
|
96
|
+
onActionUpdate;
|
|
97
|
+
/**
|
|
98
|
+
* @param {KeycloakConfig} config
|
|
99
|
+
*/
|
|
100
|
+
constructor(e) {
|
|
101
|
+
if (typeof e != "string" && !v(e))
|
|
102
|
+
throw new Error("The 'Keycloak' constructor must be provided with a configuration object, or a URL to a JSON configuration file.");
|
|
103
|
+
if (v(e)) {
|
|
104
|
+
const t = "oidcProvider" in e ? ["clientId"] : ["url", "realm", "clientId"];
|
|
105
|
+
for (const r of t)
|
|
106
|
+
if (!(r in e))
|
|
107
|
+
throw new Error(`The configuration object is missing the required '${r}' property.`);
|
|
108
|
+
}
|
|
109
|
+
globalThis.isSecureContext || this.#u(
|
|
110
|
+
`[KEYCLOAK] Keycloak JS must be used in a 'secure context' to function properly as it relies on browser APIs that are otherwise not available.
|
|
23
111
|
Continuing to run your application insecurely will lead to unexpected behavior and breakage.
|
|
24
112
|
|
|
25
113
|
For more information see: https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts`
|
|
26
|
-
|
|
27
|
-
|
|
114
|
+
), this.#i = e;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* @param {KeycloakInitOptions} initOptions
|
|
118
|
+
* @returns {Promise<boolean>}
|
|
119
|
+
*/
|
|
120
|
+
init = async (e = {}) => {
|
|
121
|
+
if (this.didInitialize)
|
|
28
122
|
throw new Error("A 'Keycloak' instance can only be initialized once.");
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
if (t.
|
|
32
|
-
if (
|
|
33
|
-
|
|
123
|
+
this.didInitialize = !0, this.#l = z();
|
|
124
|
+
const t = ["default", "cordova", "cordova-native"];
|
|
125
|
+
if (typeof e.adapter == "string" && t.includes(e.adapter) ? this.#t = this.#f(e.adapter) : typeof e.adapter == "object" ? this.#t = e.adapter : "Cordova" in window || "cordova" in window ? this.#t = this.#f("cordova") : this.#t = this.#f("default"), typeof e.useNonce < "u" && (this.#o = e.useNonce), typeof e.checkLoginIframe < "u" && (this.#e.enable = e.checkLoginIframe), e.checkLoginIframeInterval && (this.#e.interval = e.checkLoginIframeInterval), e.onLoad === "login-required" && (this.loginRequired = !0), e.responseMode)
|
|
126
|
+
if (e.responseMode === "query" || e.responseMode === "fragment")
|
|
127
|
+
this.responseMode = e.responseMode;
|
|
34
128
|
else
|
|
35
|
-
throw "Invalid value for responseMode";
|
|
36
|
-
if (
|
|
37
|
-
switch (
|
|
129
|
+
throw new Error("Invalid value for responseMode");
|
|
130
|
+
if (e.flow) {
|
|
131
|
+
switch (e.flow) {
|
|
38
132
|
case "standard":
|
|
39
|
-
|
|
133
|
+
this.responseType = "code";
|
|
40
134
|
break;
|
|
41
135
|
case "implicit":
|
|
42
|
-
|
|
136
|
+
this.responseType = "id_token token";
|
|
43
137
|
break;
|
|
44
138
|
case "hybrid":
|
|
45
|
-
|
|
139
|
+
this.responseType = "code id_token token";
|
|
46
140
|
break;
|
|
47
141
|
default:
|
|
48
|
-
throw "Invalid value for flow";
|
|
142
|
+
throw new Error("Invalid value for flow");
|
|
49
143
|
}
|
|
50
|
-
|
|
144
|
+
this.flow = e.flow;
|
|
145
|
+
}
|
|
146
|
+
if (typeof e.timeSkew == "number" && (this.timeSkew = e.timeSkew), e.redirectUri && (this.redirectUri = e.redirectUri), e.silentCheckSsoRedirectUri && (this.silentCheckSsoRedirectUri = e.silentCheckSsoRedirectUri), typeof e.silentCheckSsoFallback == "boolean" && (this.silentCheckSsoFallback = e.silentCheckSsoFallback), typeof e.pkceMethod < "u") {
|
|
147
|
+
if (e.pkceMethod !== "S256" && e.pkceMethod !== !1)
|
|
148
|
+
throw new TypeError(`Invalid value for pkceMethod', expected 'S256' or false but got ${e.pkceMethod}.`);
|
|
149
|
+
this.pkceMethod = e.pkceMethod;
|
|
51
150
|
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
151
|
+
return typeof e.enableLogging == "boolean" && (this.enableLogging = e.enableLogging), e.logoutMethod === "POST" && (this.logoutMethod = "POST"), typeof e.scope == "string" && (this.scope = e.scope), typeof e.messageReceiveTimeout == "number" && e.messageReceiveTimeout > 0 && (this.messageReceiveTimeout = e.messageReceiveTimeout), await this.#S(), await this.#E(), await this.#C(e), this.onReady?.(this.authenticated), this.authenticated;
|
|
152
|
+
};
|
|
153
|
+
/**
|
|
154
|
+
* @param {"default" | "cordova" | "cordova-native"} type
|
|
155
|
+
* @returns {KeycloakAdapter}
|
|
156
|
+
*/
|
|
157
|
+
#f(e) {
|
|
158
|
+
if (e === "default")
|
|
159
|
+
return this.#v();
|
|
160
|
+
if (e === "cordova")
|
|
161
|
+
return this.#e.enable = !1, this.#T();
|
|
162
|
+
if (e === "cordova-native")
|
|
163
|
+
return this.#e.enable = !1, this.#U();
|
|
164
|
+
throw new Error("invalid adapter type: " + e);
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* @returns {KeycloakAdapter}
|
|
168
|
+
*/
|
|
169
|
+
#v() {
|
|
170
|
+
const e = (t) => t?.redirectUri || this.redirectUri || globalThis.location.href;
|
|
171
|
+
return {
|
|
172
|
+
login: async (t) => (window.location.assign(await this.createLoginUrl(t)), await new Promise(() => {
|
|
173
|
+
})),
|
|
174
|
+
logout: async (t) => {
|
|
175
|
+
if ((t?.logoutMethod ?? this.logoutMethod) === "GET") {
|
|
176
|
+
window.location.replace(this.createLogoutUrl(t));
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
const o = document.createElement("form");
|
|
180
|
+
o.setAttribute("method", "POST"), o.setAttribute("action", this.createLogoutUrl(t)), o.style.display = "none";
|
|
181
|
+
const s = {
|
|
182
|
+
id_token_hint: this.idToken,
|
|
183
|
+
client_id: this.clientId,
|
|
184
|
+
post_logout_redirect_uri: e(t)
|
|
185
|
+
};
|
|
186
|
+
for (const [n, a] of Object.entries(s)) {
|
|
187
|
+
const c = document.createElement("input");
|
|
188
|
+
c.setAttribute("type", "hidden"), c.setAttribute("name", n), c.setAttribute(
|
|
189
|
+
"value",
|
|
190
|
+
/** @type {string} */
|
|
191
|
+
a
|
|
192
|
+
), o.appendChild(c);
|
|
193
|
+
}
|
|
194
|
+
document.body.appendChild(o), o.submit();
|
|
195
|
+
},
|
|
196
|
+
register: async (t) => (window.location.assign(await this.createRegisterUrl(t)), await new Promise(() => {
|
|
197
|
+
})),
|
|
198
|
+
accountManagement: async () => {
|
|
199
|
+
const t = this.createAccountUrl();
|
|
200
|
+
if (typeof t < "u")
|
|
201
|
+
window.location.href = t;
|
|
202
|
+
else
|
|
203
|
+
throw new Error("Not supported by the OIDC server");
|
|
204
|
+
return await new Promise(() => {
|
|
205
|
+
});
|
|
206
|
+
},
|
|
207
|
+
redirectUri: e
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* @returns {KeycloakAdapter}
|
|
212
|
+
*/
|
|
213
|
+
#T() {
|
|
214
|
+
const e = (n, a, c) => window.cordova && window.cordova.InAppBrowser ? window.cordova.InAppBrowser.open(n, a, c) : window.open(n, a, c), t = (n) => n && n.cordovaOptions ? Object.keys(n.cordovaOptions).reduce((a, c) => (a[c] = n.cordovaOptions[c], a), {}) : {}, r = (n) => Object.keys(n).reduce((a, c) => (a.push(c + "=" + n[c]), a), []).join(","), o = (n) => {
|
|
215
|
+
const a = t(n);
|
|
216
|
+
return a.location = "no", n && n.prompt === "none" && (a.hidden = "yes"), r(a);
|
|
217
|
+
}, s = () => this.redirectUri || "http://localhost";
|
|
218
|
+
return {
|
|
219
|
+
login: async (n) => {
|
|
220
|
+
const a = o(n), c = await this.createLoginUrl(n), l = e(c, "_blank", a);
|
|
221
|
+
let d = !1, h = !1;
|
|
222
|
+
function f() {
|
|
223
|
+
h = !0, l.close();
|
|
224
|
+
}
|
|
225
|
+
return await new Promise((p, w) => {
|
|
226
|
+
l.addEventListener("loadstart", async (u) => {
|
|
227
|
+
if (u.url.indexOf(s()) === 0) {
|
|
228
|
+
const m = this.#a(u.url);
|
|
229
|
+
try {
|
|
230
|
+
await this.#c(m), p();
|
|
231
|
+
} catch (y) {
|
|
232
|
+
w(y);
|
|
233
|
+
}
|
|
234
|
+
f(), d = !0;
|
|
235
|
+
}
|
|
236
|
+
}), l.addEventListener("loaderror", async (u) => {
|
|
237
|
+
if (!d)
|
|
238
|
+
if (u.url.indexOf(s()) === 0) {
|
|
239
|
+
const m = this.#a(u.url);
|
|
240
|
+
try {
|
|
241
|
+
await this.#c(m), p();
|
|
242
|
+
} catch (y) {
|
|
243
|
+
w(y);
|
|
244
|
+
}
|
|
245
|
+
f(), d = !0;
|
|
246
|
+
} else
|
|
247
|
+
w(new Error("Unable to process login.")), f();
|
|
248
|
+
}), l.addEventListener("exit", function(u) {
|
|
249
|
+
h || w(new Error("User closed the login window."));
|
|
250
|
+
});
|
|
251
|
+
});
|
|
252
|
+
},
|
|
253
|
+
logout: async (n) => {
|
|
254
|
+
const a = this.createLogoutUrl(n), c = e(a, "_blank", "location=no,hidden=yes,clearcache=yes");
|
|
255
|
+
let l = !1;
|
|
256
|
+
c.addEventListener("loadstart", (d) => {
|
|
257
|
+
d.url.indexOf(s()) === 0 && c.close();
|
|
258
|
+
}), c.addEventListener("loaderror", (d) => {
|
|
259
|
+
d.url.indexOf(s()) === 0 || (l = !0), c.close();
|
|
260
|
+
}), await new Promise((d, h) => {
|
|
261
|
+
c.addEventListener("exit", () => {
|
|
262
|
+
l ? h(new Error("User closed the login window.")) : (this.clearToken(), d());
|
|
263
|
+
});
|
|
264
|
+
});
|
|
265
|
+
},
|
|
266
|
+
register: async (n) => {
|
|
267
|
+
const a = await this.createRegisterUrl(), c = o(n), l = e(a, "_blank", c);
|
|
268
|
+
await new Promise((h, f) => {
|
|
269
|
+
l.addEventListener("loadstart", async (p) => {
|
|
270
|
+
if (p.url.indexOf(s()) === 0) {
|
|
271
|
+
l.close();
|
|
272
|
+
const w = this.#a(p.url);
|
|
273
|
+
try {
|
|
274
|
+
await this.#c(w), h();
|
|
275
|
+
} catch (u) {
|
|
276
|
+
f(u);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
});
|
|
280
|
+
});
|
|
281
|
+
},
|
|
282
|
+
accountManagement: async () => {
|
|
283
|
+
const n = this.createAccountUrl();
|
|
284
|
+
if (typeof n < "u") {
|
|
285
|
+
const a = e(n, "_blank", "location=no");
|
|
286
|
+
a.addEventListener("loadstart", function(c) {
|
|
287
|
+
c.url.indexOf(s()) === 0 && a.close();
|
|
288
|
+
});
|
|
289
|
+
} else
|
|
290
|
+
throw new Error("Not supported by the OIDC server");
|
|
291
|
+
},
|
|
292
|
+
redirectUri: () => s()
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* @returns {KeycloakAdapter}
|
|
297
|
+
*/
|
|
298
|
+
#U() {
|
|
299
|
+
return {
|
|
300
|
+
login: async (e) => {
|
|
301
|
+
const t = await this.createLoginUrl(e);
|
|
302
|
+
await new Promise((r, o) => {
|
|
303
|
+
universalLinks.subscribe("keycloak", async (s) => {
|
|
304
|
+
universalLinks.unsubscribe("keycloak"), window.cordova.plugins.browsertab.close();
|
|
305
|
+
const n = this.#a(s.url);
|
|
306
|
+
try {
|
|
307
|
+
await this.#c(n), r();
|
|
308
|
+
} catch (a) {
|
|
309
|
+
o(a);
|
|
310
|
+
}
|
|
311
|
+
}), window.cordova.plugins.browsertab.openUrl(t);
|
|
312
|
+
});
|
|
313
|
+
},
|
|
314
|
+
logout: async (e) => {
|
|
315
|
+
const t = this.createLogoutUrl(e);
|
|
316
|
+
await new Promise((r) => {
|
|
317
|
+
universalLinks.subscribe("keycloak", () => {
|
|
318
|
+
universalLinks.unsubscribe("keycloak"), window.cordova.plugins.browsertab.close(), this.clearToken(), r();
|
|
319
|
+
}), window.cordova.plugins.browsertab.openUrl(t);
|
|
320
|
+
});
|
|
321
|
+
},
|
|
322
|
+
register: async (e) => {
|
|
323
|
+
const t = await this.createRegisterUrl(e);
|
|
324
|
+
await new Promise((r, o) => {
|
|
325
|
+
universalLinks.subscribe("keycloak", async (s) => {
|
|
326
|
+
universalLinks.unsubscribe("keycloak"), window.cordova.plugins.browsertab.close();
|
|
327
|
+
const n = this.#a(s.url);
|
|
328
|
+
try {
|
|
329
|
+
await this.#c(n), r();
|
|
330
|
+
} catch (a) {
|
|
331
|
+
o(a);
|
|
332
|
+
}
|
|
333
|
+
}), window.cordova.plugins.browsertab.openUrl(t);
|
|
334
|
+
});
|
|
335
|
+
},
|
|
336
|
+
accountManagement: async () => {
|
|
337
|
+
const e = this.createAccountUrl();
|
|
338
|
+
if (typeof e < "u")
|
|
339
|
+
window.cordova.plugins.browsertab.openUrl(e);
|
|
340
|
+
else
|
|
341
|
+
throw new Error("Not supported by the OIDC server");
|
|
342
|
+
},
|
|
343
|
+
redirectUri: (e) => e && e.redirectUri ? e.redirectUri : this.redirectUri ? this.redirectUri : "http://localhost"
|
|
344
|
+
};
|
|
345
|
+
}
|
|
346
|
+
/**
|
|
347
|
+
* @returns {Promise<void>}
|
|
348
|
+
*/
|
|
349
|
+
async #S() {
|
|
350
|
+
if (typeof this.#i == "string") {
|
|
351
|
+
const e = await Y(this.#i);
|
|
352
|
+
this.authServerUrl = e["auth-server-url"], this.realm = e.realm, this.clientId = e.resource, this.#g();
|
|
353
|
+
} else
|
|
354
|
+
this.clientId = this.#i.clientId, "oidcProvider" in this.#i ? await this.#_(this.#i.oidcProvider) : (this.authServerUrl = this.#i.url, this.realm = this.#i.realm, this.#g());
|
|
355
|
+
}
|
|
356
|
+
/**
|
|
357
|
+
* @returns {void}
|
|
358
|
+
*/
|
|
359
|
+
#g() {
|
|
360
|
+
this.endpoints = {
|
|
361
|
+
authorize: () => this.#s() + "/protocol/openid-connect/auth",
|
|
362
|
+
token: () => this.#s() + "/protocol/openid-connect/token",
|
|
363
|
+
logout: () => this.#s() + "/protocol/openid-connect/logout",
|
|
364
|
+
checkSessionIframe: () => this.#s() + "/protocol/openid-connect/login-status-iframe.html",
|
|
365
|
+
thirdPartyCookiesIframe: () => this.#s() + "/protocol/openid-connect/3p-cookies/step1.html",
|
|
366
|
+
register: () => this.#s() + "/protocol/openid-connect/registrations",
|
|
367
|
+
userinfo: () => this.#s() + "/protocol/openid-connect/userinfo"
|
|
368
|
+
};
|
|
369
|
+
}
|
|
370
|
+
/**
|
|
371
|
+
* @param {string | OpenIdProviderMetadata} oidcProvider
|
|
372
|
+
* @returns {Promise<void>}
|
|
373
|
+
*/
|
|
374
|
+
async #_(e) {
|
|
375
|
+
if (typeof e == "string") {
|
|
376
|
+
const t = `${E(e)}/.well-known/openid-configuration`, r = await V(t);
|
|
377
|
+
this.#k(r);
|
|
56
378
|
} else
|
|
57
|
-
e
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
379
|
+
this.#k(e);
|
|
380
|
+
}
|
|
381
|
+
/**
|
|
382
|
+
* @param {OpenIdProviderMetadata} config
|
|
383
|
+
* @returns {void}
|
|
384
|
+
*/
|
|
385
|
+
#k(e) {
|
|
386
|
+
this.endpoints = {
|
|
387
|
+
authorize() {
|
|
388
|
+
return e.authorization_endpoint;
|
|
389
|
+
},
|
|
390
|
+
token() {
|
|
391
|
+
return e.token_endpoint;
|
|
392
|
+
},
|
|
393
|
+
logout() {
|
|
394
|
+
if (!e.end_session_endpoint)
|
|
395
|
+
throw new Error("Not supported by the OIDC server");
|
|
396
|
+
return e.end_session_endpoint;
|
|
397
|
+
},
|
|
398
|
+
checkSessionIframe() {
|
|
399
|
+
if (!e.check_session_iframe)
|
|
400
|
+
throw new Error("Not supported by the OIDC server");
|
|
401
|
+
return e.check_session_iframe;
|
|
402
|
+
},
|
|
403
|
+
register() {
|
|
404
|
+
throw new Error('Redirection to "Register user" page not supported in standard OIDC mode');
|
|
405
|
+
},
|
|
406
|
+
userinfo() {
|
|
407
|
+
if (!e.userinfo_endpoint)
|
|
408
|
+
throw new Error("Not supported by the OIDC server");
|
|
409
|
+
return e.userinfo_endpoint;
|
|
410
|
+
}
|
|
411
|
+
};
|
|
412
|
+
}
|
|
413
|
+
/**
|
|
414
|
+
* @returns {Promise<void>}
|
|
415
|
+
*/
|
|
416
|
+
async #E() {
|
|
417
|
+
if (!this.#e.enable && !this.silentCheckSsoRedirectUri || typeof this.endpoints.thirdPartyCookiesIframe != "function")
|
|
418
|
+
return;
|
|
419
|
+
const e = document.createElement("iframe");
|
|
420
|
+
e.setAttribute("src", this.endpoints.thirdPartyCookiesIframe()), e.setAttribute("sandbox", "allow-storage-access-by-user-activation allow-scripts allow-same-origin"), e.setAttribute("title", "keycloak-3p-check-iframe"), e.style.display = "none", document.body.appendChild(e);
|
|
421
|
+
const t = new Promise((r) => {
|
|
422
|
+
const o = (s) => {
|
|
423
|
+
e.contentWindow === s.source && (s.data !== "supported" && s.data !== "unsupported" || (s.data === "unsupported" && (this.#u(
|
|
424
|
+
`[KEYCLOAK] Your browser is blocking access to 3rd-party cookies, this means:
|
|
425
|
+
|
|
426
|
+
- It is not possible to retrieve tokens without redirecting to the Keycloak server (a.k.a. no support for silent authentication).
|
|
427
|
+
- It is not possible to automatically detect changes to the session status (such as the user logging out in another tab).
|
|
428
|
+
|
|
429
|
+
For more information see: https://www.keycloak.org/securing-apps/javascript-adapter#_modern_browsers`
|
|
430
|
+
), this.#e.enable = !1, this.silentCheckSsoFallback && (this.silentCheckSsoRedirectUri = void 0)), document.body.removeChild(e), window.removeEventListener("message", o), r()));
|
|
431
|
+
};
|
|
432
|
+
window.addEventListener("message", o, !1);
|
|
64
433
|
});
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
window.addEventListener("message", S);
|
|
83
|
-
}, p = {};
|
|
84
|
-
switch (r.onLoad) {
|
|
434
|
+
return await j(t, this.messageReceiveTimeout, "Timeout when waiting for 3rd party check iframe message.");
|
|
435
|
+
}
|
|
436
|
+
/**
|
|
437
|
+
* @param {KeycloakInitOptions} initOptions
|
|
438
|
+
* @returns {Promise<void>}
|
|
439
|
+
*/
|
|
440
|
+
async #C(e) {
|
|
441
|
+
const t = this.#a(window.location.href);
|
|
442
|
+
if (t?.newUrl && window.history.replaceState(window.history.state, "", t.newUrl), t && t.valid) {
|
|
443
|
+
await this.#p(), await this.#c(t);
|
|
444
|
+
return;
|
|
445
|
+
}
|
|
446
|
+
const r = async (s) => {
|
|
447
|
+
const n = {};
|
|
448
|
+
s || (n.prompt = "none"), e.locale && (n.locale = e.locale), await this.login(n);
|
|
449
|
+
}, o = async () => {
|
|
450
|
+
switch (e.onLoad) {
|
|
85
451
|
case "check-sso":
|
|
86
|
-
|
|
87
|
-
P().then(function(d) {
|
|
88
|
-
d ? s.setSuccess() : e.silentCheckSsoRedirectUri ? u() : o(!1);
|
|
89
|
-
}).catch(function(d) {
|
|
90
|
-
s.setError(d);
|
|
91
|
-
});
|
|
92
|
-
}) : e.silentCheckSsoRedirectUri ? u() : o(!1);
|
|
452
|
+
this.#e.enable ? (await this.#p(), await this.#d() || (this.silentCheckSsoRedirectUri ? await this.#m() : await r(!1))) : this.silentCheckSsoRedirectUri ? await this.#m() : await r(!1);
|
|
93
453
|
break;
|
|
94
454
|
case "login-required":
|
|
95
|
-
|
|
455
|
+
await r(!0);
|
|
96
456
|
break;
|
|
97
457
|
default:
|
|
98
|
-
throw "Invalid value for onLoad";
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
function n() {
|
|
102
|
-
var o = E(window.location.href);
|
|
103
|
-
if (o && window.history.replaceState(window.history.state, null, o.newUrl), o && o.valid)
|
|
104
|
-
return H().then(function() {
|
|
105
|
-
A(o, s);
|
|
106
|
-
}).catch(function(u) {
|
|
107
|
-
s.setError(u);
|
|
108
|
-
});
|
|
109
|
-
r.token && r.refreshToken ? (x(r.token, r.refreshToken, r.idToken), h.enable ? H().then(function() {
|
|
110
|
-
P().then(function(u) {
|
|
111
|
-
u ? (e.onAuthSuccess && e.onAuthSuccess(), s.setSuccess(), K()) : s.setSuccess();
|
|
112
|
-
}).catch(function(u) {
|
|
113
|
-
s.setError(u);
|
|
114
|
-
});
|
|
115
|
-
}) : e.updateToken(-1).then(function() {
|
|
116
|
-
e.onAuthSuccess && e.onAuthSuccess(), s.setSuccess();
|
|
117
|
-
}).catch(function(u) {
|
|
118
|
-
e.onAuthError && e.onAuthError(), r.onLoad ? c() : s.setError(u);
|
|
119
|
-
})) : r.onLoad ? c() : s.setSuccess();
|
|
120
|
-
}
|
|
121
|
-
return a.then(function() {
|
|
122
|
-
te().then(n).catch(function(o) {
|
|
123
|
-
i.setError(o);
|
|
124
|
-
});
|
|
125
|
-
}), a.catch(function(o) {
|
|
126
|
-
i.setError(o);
|
|
127
|
-
}), i.promise;
|
|
128
|
-
}, e.login = function(r) {
|
|
129
|
-
return f.login(r);
|
|
130
|
-
};
|
|
131
|
-
function R(r) {
|
|
132
|
-
if (typeof crypto > "u" || typeof crypto.getRandomValues > "u")
|
|
133
|
-
throw new Error("Web Crypto API is not available.");
|
|
134
|
-
return crypto.getRandomValues(new Uint8Array(r));
|
|
135
|
-
}
|
|
136
|
-
function C(r) {
|
|
137
|
-
return v(r, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
|
|
138
|
-
}
|
|
139
|
-
function v(r, t) {
|
|
140
|
-
for (var i = R(r), s = new Array(r), a = 0; a < r; a++)
|
|
141
|
-
s[a] = t.charCodeAt(i[a] % t.length);
|
|
142
|
-
return String.fromCharCode.apply(null, s);
|
|
143
|
-
}
|
|
144
|
-
async function M(r, t) {
|
|
145
|
-
if (r !== "S256")
|
|
146
|
-
throw new TypeError(`Invalid value for 'pkceMethod', expected 'S256' but got '${r}'.`);
|
|
147
|
-
const i = new Uint8Array(await ce(t));
|
|
148
|
-
return ie(i).replace(/\+/g, "-").replace(/\//g, "_").replace(/\=/g, "");
|
|
149
|
-
}
|
|
150
|
-
function N(r) {
|
|
151
|
-
var t = {
|
|
152
|
-
id_token: {
|
|
153
|
-
acr: r
|
|
458
|
+
throw new Error("Invalid value for onLoad");
|
|
154
459
|
}
|
|
155
460
|
};
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
r && r.action == "register" ? c = e.endpoints.register() : c = e.endpoints.authorize();
|
|
168
|
-
var n = r && r.scope || e.scope;
|
|
169
|
-
n ? n.indexOf("openid") === -1 && (n = "openid " + n) : n = "openid";
|
|
170
|
-
var o = c + "?client_id=" + encodeURIComponent(e.clientId) + "&redirect_uri=" + encodeURIComponent(s) + "&state=" + encodeURIComponent(t) + "&response_mode=" + encodeURIComponent(e.responseMode) + "&response_type=" + encodeURIComponent(e.responseType) + "&scope=" + encodeURIComponent(n);
|
|
171
|
-
if (y && (o = o + "&nonce=" + encodeURIComponent(i)), r && r.prompt && (o += "&prompt=" + encodeURIComponent(r.prompt)), r && typeof r.maxAge == "number" && (o += "&max_age=" + encodeURIComponent(r.maxAge)), r && r.loginHint && (o += "&login_hint=" + encodeURIComponent(r.loginHint)), r && r.idpHint && (o += "&kc_idp_hint=" + encodeURIComponent(r.idpHint)), r && r.action && r.action != "register" && (o += "&kc_action=" + encodeURIComponent(r.action)), r && r.locale && (o += "&ui_locales=" + encodeURIComponent(r.locale)), r && r.acr) {
|
|
172
|
-
var u = N(r.acr);
|
|
173
|
-
o += "&claims=" + encodeURIComponent(u);
|
|
174
|
-
}
|
|
175
|
-
if ((r && r.acrValues || e.acrValues) && (o += "&acr_values=" + encodeURIComponent(r.acrValues || e.acrValues)), e.pkceMethod)
|
|
176
|
-
try {
|
|
177
|
-
const p = C(96), d = await M(e.pkceMethod, p);
|
|
178
|
-
a.pkceCodeVerifier = p, o += "&code_challenge=" + d, o += "&code_challenge_method=" + e.pkceMethod;
|
|
179
|
-
} catch (p) {
|
|
180
|
-
throw new Error("Failed to generate PKCE challenge.", { cause: p });
|
|
181
|
-
}
|
|
182
|
-
return m.add(a), o;
|
|
183
|
-
}, e.logout = function(r) {
|
|
184
|
-
return f.logout(r);
|
|
185
|
-
}, e.createLogoutUrl = function(r) {
|
|
186
|
-
if (((r == null ? void 0 : r.logoutMethod) ?? e.logoutMethod) === "POST")
|
|
187
|
-
return e.endpoints.logout();
|
|
188
|
-
var i = e.endpoints.logout() + "?client_id=" + encodeURIComponent(e.clientId) + "&post_logout_redirect_uri=" + encodeURIComponent(f.redirectUri(r, !1));
|
|
189
|
-
return e.idToken && (i += "&id_token_hint=" + encodeURIComponent(e.idToken)), i;
|
|
190
|
-
}, e.register = function(r) {
|
|
191
|
-
return f.register(r);
|
|
192
|
-
}, e.createRegisterUrl = async function(r) {
|
|
193
|
-
return r || (r = {}), r.action = "register", await e.createLoginUrl(r);
|
|
194
|
-
}, e.createAccountUrl = function(r) {
|
|
195
|
-
var t = _(), i = void 0;
|
|
196
|
-
return typeof t < "u" && (i = t + "/account?referrer=" + encodeURIComponent(e.clientId) + "&referrer_uri=" + encodeURIComponent(f.redirectUri(r))), i;
|
|
197
|
-
}, e.accountManagement = function() {
|
|
198
|
-
return f.accountManagement();
|
|
199
|
-
}, e.hasRealmRole = function(r) {
|
|
200
|
-
var t = e.realmAccess;
|
|
201
|
-
return !!t && t.roles.indexOf(r) >= 0;
|
|
202
|
-
}, e.hasResourceRole = function(r, t) {
|
|
203
|
-
if (!e.resourceAccess)
|
|
204
|
-
return !1;
|
|
205
|
-
var i = e.resourceAccess[t || e.clientId];
|
|
206
|
-
return !!i && i.roles.indexOf(r) >= 0;
|
|
207
|
-
}, e.loadUserProfile = function() {
|
|
208
|
-
var r = _() + "/account", t = new XMLHttpRequest();
|
|
209
|
-
t.open("GET", r, !0), t.setRequestHeader("Accept", "application/json"), t.setRequestHeader("Authorization", "bearer " + e.token);
|
|
210
|
-
var i = w();
|
|
211
|
-
return t.onreadystatechange = function() {
|
|
212
|
-
t.readyState == 4 && (t.status == 200 ? (e.profile = JSON.parse(t.responseText), i.setSuccess(e.profile)) : i.setError());
|
|
213
|
-
}, t.send(), i.promise;
|
|
214
|
-
}, e.loadUserInfo = function() {
|
|
215
|
-
var r = e.endpoints.userinfo(), t = new XMLHttpRequest();
|
|
216
|
-
t.open("GET", r, !0), t.setRequestHeader("Accept", "application/json"), t.setRequestHeader("Authorization", "bearer " + e.token);
|
|
217
|
-
var i = w();
|
|
218
|
-
return t.onreadystatechange = function() {
|
|
219
|
-
t.readyState == 4 && (t.status == 200 ? (e.userInfo = JSON.parse(t.responseText), i.setSuccess(e.userInfo)) : i.setError());
|
|
220
|
-
}, t.send(), i.promise;
|
|
221
|
-
}, e.isTokenExpired = function(r) {
|
|
222
|
-
if (!e.tokenParsed || !e.refreshToken && e.flow != "implicit")
|
|
223
|
-
throw "Not authenticated";
|
|
224
|
-
if (e.timeSkew == null)
|
|
225
|
-
return b("[KEYCLOAK] Unable to determine if token is expired as timeskew is not set"), !0;
|
|
226
|
-
var t = e.tokenParsed.exp - Math.ceil((/* @__PURE__ */ new Date()).getTime() / 1e3) + e.timeSkew;
|
|
227
|
-
if (r) {
|
|
228
|
-
if (isNaN(r))
|
|
229
|
-
throw "Invalid minValidity";
|
|
230
|
-
t -= r;
|
|
231
|
-
}
|
|
232
|
-
return t < 0;
|
|
233
|
-
}, e.updateToken = function(r) {
|
|
234
|
-
var t = w();
|
|
235
|
-
if (!e.refreshToken)
|
|
236
|
-
return t.setError(), t.promise;
|
|
237
|
-
r = r || 5;
|
|
238
|
-
var i = function() {
|
|
239
|
-
var a = !1;
|
|
240
|
-
if (r == -1 ? (a = !0, b("[KEYCLOAK] Refreshing token: forced refresh")) : (!e.tokenParsed || e.isTokenExpired(r)) && (a = !0, b("[KEYCLOAK] Refreshing token: token expired")), !a)
|
|
241
|
-
t.setSuccess(!1);
|
|
242
|
-
else {
|
|
243
|
-
var c = "grant_type=refresh_token&refresh_token=" + e.refreshToken, n = e.endpoints.token();
|
|
244
|
-
if (k.push(t), k.length == 1) {
|
|
245
|
-
var o = new XMLHttpRequest();
|
|
246
|
-
o.open("POST", n, !0), o.setRequestHeader("Content-type", "application/x-www-form-urlencoded"), o.withCredentials = !0, c += "&client_id=" + encodeURIComponent(e.clientId);
|
|
247
|
-
var u = (/* @__PURE__ */ new Date()).getTime();
|
|
248
|
-
o.onreadystatechange = function() {
|
|
249
|
-
if (o.readyState == 4)
|
|
250
|
-
if (o.status == 200) {
|
|
251
|
-
b("[KEYCLOAK] Token refreshed"), u = (u + (/* @__PURE__ */ new Date()).getTime()) / 2;
|
|
252
|
-
var p = JSON.parse(o.responseText);
|
|
253
|
-
x(p.access_token, p.refresh_token, p.id_token, u), e.onAuthRefreshSuccess && e.onAuthRefreshSuccess();
|
|
254
|
-
for (var d = k.pop(); d != null; d = k.pop())
|
|
255
|
-
d.setSuccess(!0);
|
|
256
|
-
} else {
|
|
257
|
-
T("[KEYCLOAK] Failed to refresh token"), o.status == 400 && e.clearToken(), e.onAuthRefreshError && e.onAuthRefreshError();
|
|
258
|
-
for (var d = k.pop(); d != null; d = k.pop())
|
|
259
|
-
d.setError("Failed to refresh token: An unexpected HTTP error occurred while attempting to refresh the token.");
|
|
260
|
-
}
|
|
261
|
-
}, o.send(c);
|
|
461
|
+
if (e.token && e.refreshToken)
|
|
462
|
+
if (this.#h(e.token, e.refreshToken, e.idToken), this.#e.enable)
|
|
463
|
+
await this.#p(), await this.#d() && (this.onAuthSuccess?.(), this.#w());
|
|
464
|
+
else
|
|
465
|
+
try {
|
|
466
|
+
await this.updateToken(-1), this.onAuthSuccess?.();
|
|
467
|
+
} catch (s) {
|
|
468
|
+
if (this.onAuthError?.(), e.onLoad)
|
|
469
|
+
await o();
|
|
470
|
+
else
|
|
471
|
+
throw s;
|
|
262
472
|
}
|
|
263
|
-
|
|
473
|
+
else e.onLoad && await o();
|
|
474
|
+
}
|
|
475
|
+
/**
|
|
476
|
+
* @returns {Promise<void>}
|
|
477
|
+
*/
|
|
478
|
+
async #p() {
|
|
479
|
+
if (!this.#e.enable || this.#e.iframe)
|
|
480
|
+
return;
|
|
481
|
+
const e = document.createElement("iframe");
|
|
482
|
+
this.#e.iframe = e, e.setAttribute("src", this.endpoints.checkSessionIframe()), e.setAttribute("sandbox", "allow-storage-access-by-user-activation allow-scripts allow-same-origin"), e.setAttribute("title", "keycloak-session-iframe"), e.style.display = "none", document.body.appendChild(e);
|
|
483
|
+
const t = (o) => {
|
|
484
|
+
if (o.origin !== this.#e.iframeOrigin || this.#e.iframe?.contentWindow !== o.source || !(o.data === "unchanged" || o.data === "changed" || o.data === "error"))
|
|
485
|
+
return;
|
|
486
|
+
o.data !== "unchanged" && this.clearToken();
|
|
487
|
+
const s = this.#e.callbackList;
|
|
488
|
+
this.#e.callbackList = [];
|
|
489
|
+
for (const n of s.reverse())
|
|
490
|
+
o.data === "error" ? n(new Error("Error while checking login iframe")) : n(null, o.data === "unchanged");
|
|
264
491
|
};
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
}).catch(function(a) {
|
|
270
|
-
t.setError(a);
|
|
492
|
+
window.addEventListener("message", t, !1), await new Promise((o) => {
|
|
493
|
+
e.addEventListener("load", () => {
|
|
494
|
+
const s = this.endpoints.authorize();
|
|
495
|
+
s.startsWith("/") ? this.#e.iframeOrigin = globalThis.location.origin : this.#e.iframeOrigin = new URL(s).origin, o();
|
|
271
496
|
});
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
if (typeof e.authServerUrl < "u")
|
|
280
|
-
return e.authServerUrl.charAt(e.authServerUrl.length - 1) == "/" ? e.authServerUrl + "realms/" + encodeURIComponent(e.realm) : e.authServerUrl + "/realms/" + encodeURIComponent(e.realm);
|
|
281
|
-
}
|
|
282
|
-
function Q() {
|
|
283
|
-
return window.location.origin ? window.location.origin : window.location.protocol + "//" + window.location.hostname + (window.location.port ? ":" + window.location.port : "");
|
|
284
|
-
}
|
|
285
|
-
function A(r, t) {
|
|
286
|
-
var i = r.code, s = r.error, a = r.prompt, c = (/* @__PURE__ */ new Date()).getTime();
|
|
287
|
-
if (r.kc_action_status && e.onActionUpdate && e.onActionUpdate(r.kc_action_status, r.kc_action), s) {
|
|
288
|
-
if (a != "none")
|
|
289
|
-
if (r.error_description && r.error_description === "authentication_expired")
|
|
290
|
-
e.login(r.loginOptions);
|
|
291
|
-
else {
|
|
292
|
-
var n = { error: s, error_description: r.error_description };
|
|
293
|
-
e.onAuthError && e.onAuthError(n), t && t.setError(n);
|
|
294
|
-
}
|
|
295
|
-
else
|
|
296
|
-
t && t.setSuccess();
|
|
497
|
+
});
|
|
498
|
+
}
|
|
499
|
+
/**
|
|
500
|
+
* @returns {Promise<boolean | undefined>}
|
|
501
|
+
*/
|
|
502
|
+
async #d() {
|
|
503
|
+
if (!this.#e.iframe || !this.#e.iframeOrigin)
|
|
297
504
|
return;
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
} else
|
|
307
|
-
e.onAuthError && e.onAuthError(), t && t.setError();
|
|
308
|
-
}, p.send(o);
|
|
309
|
-
}
|
|
310
|
-
function d(g, S, I, U) {
|
|
311
|
-
c = (c + (/* @__PURE__ */ new Date()).getTime()) / 2, x(g, S, I, c), y && e.idTokenParsed && e.idTokenParsed.nonce != r.storedNonce ? (b("[KEYCLOAK] Invalid nonce, clearing token"), e.clearToken(), t && t.setError()) : U && (e.onAuthSuccess && e.onAuthSuccess(), t && t.setSuccess());
|
|
312
|
-
}
|
|
505
|
+
const e = `${this.clientId} ${this.sessionId ? this.sessionId : ""}`, t = this.#e.iframeOrigin;
|
|
506
|
+
return await new Promise((o, s) => {
|
|
507
|
+
const n = (a, c) => a ? s(a) : o(
|
|
508
|
+
/** @type {boolean} */
|
|
509
|
+
c
|
|
510
|
+
);
|
|
511
|
+
this.#e.callbackList.push(n), this.#e.callbackList.length === 1 && this.#e.iframe?.contentWindow?.postMessage(e, t);
|
|
512
|
+
});
|
|
313
513
|
}
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
return n.end_session_endpoint;
|
|
329
|
-
},
|
|
330
|
-
checkSessionIframe: function() {
|
|
331
|
-
if (!n.check_session_iframe)
|
|
332
|
-
throw "Not supported by the OIDC server";
|
|
333
|
-
return n.check_session_iframe;
|
|
334
|
-
},
|
|
335
|
-
register: function() {
|
|
336
|
-
throw 'Redirection to "Register user" page not supported in standard OIDC mode';
|
|
337
|
-
},
|
|
338
|
-
userinfo: function() {
|
|
339
|
-
if (!n.userinfo_endpoint)
|
|
340
|
-
throw "Not supported by the OIDC server";
|
|
341
|
-
return n.userinfo_endpoint;
|
|
342
|
-
}
|
|
343
|
-
} : e.endpoints = {
|
|
344
|
-
authorize: function() {
|
|
345
|
-
return _() + "/protocol/openid-connect/auth";
|
|
346
|
-
},
|
|
347
|
-
token: function() {
|
|
348
|
-
return _() + "/protocol/openid-connect/token";
|
|
349
|
-
},
|
|
350
|
-
logout: function() {
|
|
351
|
-
return _() + "/protocol/openid-connect/logout";
|
|
352
|
-
},
|
|
353
|
-
checkSessionIframe: function() {
|
|
354
|
-
return _() + "/protocol/openid-connect/login-status-iframe.html";
|
|
355
|
-
},
|
|
356
|
-
thirdPartyCookiesIframe: function() {
|
|
357
|
-
return _() + "/protocol/openid-connect/3p-cookies/step1.html";
|
|
358
|
-
},
|
|
359
|
-
register: function() {
|
|
360
|
-
return _() + "/protocol/openid-connect/registrations";
|
|
361
|
-
},
|
|
362
|
-
userinfo: function() {
|
|
363
|
-
return _() + "/protocol/openid-connect/userinfo";
|
|
514
|
+
/**
|
|
515
|
+
* @returns {Promise<void>}
|
|
516
|
+
*/
|
|
517
|
+
async #m() {
|
|
518
|
+
const e = document.createElement("iframe"), t = await this.createLoginUrl({ prompt: "none", redirectUri: this.silentCheckSsoRedirectUri });
|
|
519
|
+
return e.setAttribute("src", t), e.setAttribute("sandbox", "allow-storage-access-by-user-activation allow-scripts allow-same-origin"), e.setAttribute("title", "keycloak-silent-check-sso"), e.style.display = "none", document.body.appendChild(e), await new Promise((r, o) => {
|
|
520
|
+
const s = async (n) => {
|
|
521
|
+
if (n.origin !== window.location.origin || e.contentWindow !== n.source)
|
|
522
|
+
return;
|
|
523
|
+
const a = this.#a(n.data);
|
|
524
|
+
try {
|
|
525
|
+
await this.#c(a), r();
|
|
526
|
+
} catch (c) {
|
|
527
|
+
o(c);
|
|
364
528
|
}
|
|
529
|
+
document.body.removeChild(e), window.removeEventListener("message", s);
|
|
365
530
|
};
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
var s = new XMLHttpRequest();
|
|
369
|
-
s.open("GET", t, !0), s.setRequestHeader("Accept", "application/json"), s.onreadystatechange = function() {
|
|
370
|
-
if (s.readyState == 4)
|
|
371
|
-
if (s.status == 200 || G(s)) {
|
|
372
|
-
var n = JSON.parse(s.responseText);
|
|
373
|
-
e.authServerUrl = n["auth-server-url"], e.realm = n.realm, e.clientId = n.resource, i(null), r.setSuccess();
|
|
374
|
-
} else
|
|
375
|
-
r.setError();
|
|
376
|
-
}, s.send();
|
|
377
|
-
} else {
|
|
378
|
-
e.clientId = l.clientId;
|
|
379
|
-
var a = l.oidcProvider;
|
|
380
|
-
if (!a)
|
|
381
|
-
e.authServerUrl = l.url, e.realm = l.realm, i(null), r.setSuccess();
|
|
382
|
-
else if (typeof a == "string") {
|
|
383
|
-
var c;
|
|
384
|
-
a.charAt(a.length - 1) == "/" ? c = a + ".well-known/openid-configuration" : c = a + "/.well-known/openid-configuration";
|
|
385
|
-
var s = new XMLHttpRequest();
|
|
386
|
-
s.open("GET", c, !0), s.setRequestHeader("Accept", "application/json"), s.onreadystatechange = function() {
|
|
387
|
-
if (s.readyState == 4)
|
|
388
|
-
if (s.status == 200 || G(s)) {
|
|
389
|
-
var o = JSON.parse(s.responseText);
|
|
390
|
-
i(o), r.setSuccess();
|
|
391
|
-
} else
|
|
392
|
-
r.setError();
|
|
393
|
-
}, s.send();
|
|
394
|
-
} else
|
|
395
|
-
i(a), r.setSuccess();
|
|
396
|
-
}
|
|
397
|
-
return r.promise;
|
|
398
|
-
}
|
|
399
|
-
function G(r) {
|
|
400
|
-
return r.status == 0 && r.responseText && r.responseURL.startsWith("file:");
|
|
531
|
+
window.addEventListener("message", s);
|
|
532
|
+
});
|
|
401
533
|
}
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
function q() {
|
|
412
|
-
if (typeof crypto > "u" || typeof crypto.randomUUID > "u")
|
|
413
|
-
throw new Error("Web Crypto API is not available.");
|
|
414
|
-
return crypto.randomUUID();
|
|
415
|
-
}
|
|
416
|
-
function E(r) {
|
|
417
|
-
var t = ee(r);
|
|
418
|
-
if (t) {
|
|
419
|
-
var i = m.get(t.state);
|
|
420
|
-
return i && (t.valid = !0, t.redirectUri = i.redirectUri, t.storedNonce = i.nonce, t.prompt = i.prompt, t.pkceCodeVerifier = i.pkceCodeVerifier, t.loginOptions = i.loginOptions), t;
|
|
421
|
-
}
|
|
534
|
+
/**
|
|
535
|
+
* @param {string} url
|
|
536
|
+
*/
|
|
537
|
+
#a(e) {
|
|
538
|
+
const t = this.#A(e);
|
|
539
|
+
if (!t)
|
|
540
|
+
return;
|
|
541
|
+
const r = this.#l.get(t.state);
|
|
542
|
+
return r && (t.valid = !0, t.redirectUri = r.redirectUri, t.storedNonce = r.nonce, t.prompt = r.prompt, t.pkceCodeVerifier = r.pkceCodeVerifier, t.loginOptions = r.loginOptions), t;
|
|
422
543
|
}
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
544
|
+
/**
|
|
545
|
+
* @param {string} urlString
|
|
546
|
+
*/
|
|
547
|
+
#A(e) {
|
|
548
|
+
let t = [];
|
|
549
|
+
switch (this.flow) {
|
|
426
550
|
case "standard":
|
|
427
551
|
t = ["code", "state", "session_state", "kc_action_status", "kc_action", "iss"];
|
|
428
552
|
break;
|
|
@@ -434,379 +558,497 @@ For more information see: https://developer.mozilla.org/en-US/docs/Web/Security/
|
|
|
434
558
|
break;
|
|
435
559
|
}
|
|
436
560
|
t.push("error"), t.push("error_description"), t.push("error_uri");
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
}
|
|
446
|
-
function B(r, t) {
|
|
447
|
-
for (var i = r.split("&"), s = {
|
|
448
|
-
paramsString: "",
|
|
449
|
-
oauthParams: {}
|
|
450
|
-
}, a = 0; a < i.length; a++) {
|
|
451
|
-
var c = i[a].indexOf("="), n = i[a].slice(0, c);
|
|
452
|
-
t.indexOf(n) !== -1 ? s.oauthParams[n] = i[a].slice(c + 1) : (s.paramsString !== "" && (s.paramsString += "&"), s.paramsString += i[a]);
|
|
561
|
+
const r = new URL(e);
|
|
562
|
+
let o = "", s;
|
|
563
|
+
if (this.responseMode === "query" && r.searchParams.size > 0 ? (s = this.#y(r.search, t), r.search = s.paramsString, o = r.toString()) : this.responseMode === "fragment" && r.hash.length > 0 && (s = this.#y(r.hash.substring(1), t), r.hash = s.paramsString, o = r.toString()), s?.oauthParams) {
|
|
564
|
+
if (this.flow === "standard" || this.flow === "hybrid") {
|
|
565
|
+
if ((s.oauthParams.code || s.oauthParams.error) && s.oauthParams.state)
|
|
566
|
+
return s.oauthParams.newUrl = o, s.oauthParams;
|
|
567
|
+
} else if (this.flow === "implicit" && (s.oauthParams.access_token || s.oauthParams.error) && s.oauthParams.state)
|
|
568
|
+
return s.oauthParams.newUrl = o, s.oauthParams;
|
|
453
569
|
}
|
|
454
|
-
return s;
|
|
455
570
|
}
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
571
|
+
/**
|
|
572
|
+
* @typedef {Object} ParsedCallbackParams
|
|
573
|
+
* @property {string} paramsString
|
|
574
|
+
* @property {Record<string, string | undefined>} oauthParams
|
|
575
|
+
*/
|
|
576
|
+
/**
|
|
577
|
+
* @param {string} paramsString
|
|
578
|
+
* @param {string[]} supportedParams
|
|
579
|
+
* @returns {ParsedCallbackParams}
|
|
580
|
+
*/
|
|
581
|
+
#y(e, t) {
|
|
582
|
+
const r = new URLSearchParams(e), o = {};
|
|
583
|
+
for (const [s, n] of Array.from(r.entries()))
|
|
584
|
+
t.includes(s) && (o[s] = n, r.delete(s));
|
|
585
|
+
return {
|
|
586
|
+
paramsString: r.toString(),
|
|
587
|
+
oauthParams: o
|
|
464
588
|
};
|
|
465
|
-
return r.promise = new Promise(function(t, i) {
|
|
466
|
-
r.resolve = t, r.reject = i;
|
|
467
|
-
}), r;
|
|
468
|
-
}
|
|
469
|
-
function re(r, t, i) {
|
|
470
|
-
var s = null, a = new Promise(function(c, n) {
|
|
471
|
-
s = setTimeout(function() {
|
|
472
|
-
n({ error: i });
|
|
473
|
-
}, t);
|
|
474
|
-
});
|
|
475
|
-
return Promise.race([r, a]).finally(function() {
|
|
476
|
-
clearTimeout(s);
|
|
477
|
-
});
|
|
478
589
|
}
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
var a = e.endpoints.authorize();
|
|
486
|
-
a.charAt(0) === "/" ? h.iframeOrigin = Q() : h.iframeOrigin = a.substring(0, a.indexOf("/", 8)), r.setSuccess();
|
|
590
|
+
async #c(e) {
|
|
591
|
+
const { code: t, error: r, prompt: o } = e;
|
|
592
|
+
let s = (/* @__PURE__ */ new Date()).getTime();
|
|
593
|
+
const n = (a, c, l) => {
|
|
594
|
+
if (s = (s + (/* @__PURE__ */ new Date()).getTime()) / 2, this.#h(a, c, l, s), this.#o && this.idTokenParsed && this.idTokenParsed.nonce !== e.storedNonce)
|
|
595
|
+
throw this.#n("[KEYCLOAK] Invalid nonce, clearing token"), this.clearToken(), new Error("Invalid nonce.");
|
|
487
596
|
};
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
a.data == "error" ? o.setError() : o.setSuccess(a.data == "unchanged");
|
|
597
|
+
if (e.kc_action_status && this.onActionUpdate && this.onActionUpdate(e.kc_action_status, e.kc_action), r) {
|
|
598
|
+
if (o !== "none")
|
|
599
|
+
if (e.error_description && e.error_description === "authentication_expired")
|
|
600
|
+
await this.login(e.loginOptions);
|
|
601
|
+
else {
|
|
602
|
+
const a = { error: r, error_description: e.error_description };
|
|
603
|
+
throw this.onAuthError?.(a), a;
|
|
496
604
|
}
|
|
605
|
+
return;
|
|
606
|
+
} else this.flow !== "standard" && (e.access_token || e.id_token) && (n(e.access_token, void 0, e.id_token), this.onAuthSuccess?.());
|
|
607
|
+
if (this.flow !== "implicit" && t)
|
|
608
|
+
try {
|
|
609
|
+
const a = await B(
|
|
610
|
+
this.endpoints.token(),
|
|
611
|
+
t,
|
|
612
|
+
/** @type {string} */
|
|
613
|
+
this.clientId,
|
|
614
|
+
e.redirectUri,
|
|
615
|
+
e.pkceCodeVerifier
|
|
616
|
+
);
|
|
617
|
+
n(a.access_token, a.refresh_token, a.id_token), this.flow === "standard" && this.onAuthSuccess?.(), this.#w();
|
|
618
|
+
} catch (a) {
|
|
619
|
+
throw this.onAuthError?.(), a;
|
|
497
620
|
}
|
|
498
|
-
};
|
|
499
|
-
return window.addEventListener("message", s, !1), r.promise;
|
|
500
621
|
}
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
r
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
}
|
|
539
|
-
function D(r) {
|
|
540
|
-
if (!r || r == "default")
|
|
541
|
-
return {
|
|
542
|
-
login: async function(n) {
|
|
543
|
-
return window.location.assign(await e.createLoginUrl(n)), w().promise;
|
|
544
|
-
},
|
|
545
|
-
logout: async function(n) {
|
|
546
|
-
if (((n == null ? void 0 : n.logoutMethod) ?? e.logoutMethod) === "GET") {
|
|
547
|
-
window.location.replace(e.createLogoutUrl(n));
|
|
548
|
-
return;
|
|
549
|
-
}
|
|
550
|
-
const u = document.createElement("form");
|
|
551
|
-
u.setAttribute("method", "POST"), u.setAttribute("action", e.createLogoutUrl(n)), u.style.display = "none";
|
|
552
|
-
const p = {
|
|
553
|
-
id_token_hint: e.idToken,
|
|
554
|
-
client_id: e.clientId,
|
|
555
|
-
post_logout_redirect_uri: f.redirectUri(n, !1)
|
|
556
|
-
};
|
|
557
|
-
for (const [d, g] of Object.entries(p)) {
|
|
558
|
-
const S = document.createElement("input");
|
|
559
|
-
S.setAttribute("type", "hidden"), S.setAttribute("name", d), S.setAttribute("value", g), u.appendChild(S);
|
|
560
|
-
}
|
|
561
|
-
document.body.appendChild(u), u.submit();
|
|
562
|
-
},
|
|
563
|
-
register: async function(n) {
|
|
564
|
-
return window.location.assign(await e.createRegisterUrl(n)), w().promise;
|
|
565
|
-
},
|
|
566
|
-
accountManagement: function() {
|
|
567
|
-
var n = e.createAccountUrl();
|
|
568
|
-
if (typeof n < "u")
|
|
569
|
-
window.location.href = n;
|
|
570
|
-
else
|
|
571
|
-
throw "Not supported by the OIDC server";
|
|
572
|
-
return w().promise;
|
|
573
|
-
},
|
|
574
|
-
redirectUri: function(n, o) {
|
|
575
|
-
return n && n.redirectUri ? n.redirectUri : e.redirectUri ? e.redirectUri : location.href;
|
|
576
|
-
}
|
|
577
|
-
};
|
|
578
|
-
if (r == "cordova") {
|
|
579
|
-
h.enable = !1;
|
|
580
|
-
var t = function(n, o, u) {
|
|
581
|
-
return window.cordova && window.cordova.InAppBrowser ? window.cordova.InAppBrowser.open(n, o, u) : window.open(n, o, u);
|
|
582
|
-
}, i = function(n) {
|
|
583
|
-
return n && n.cordovaOptions ? Object.keys(n.cordovaOptions).reduce(function(o, u) {
|
|
584
|
-
return o[u] = n.cordovaOptions[u], o;
|
|
585
|
-
}, {}) : {};
|
|
586
|
-
}, s = function(n) {
|
|
587
|
-
return Object.keys(n).reduce(function(o, u) {
|
|
588
|
-
return o.push(u + "=" + n[u]), o;
|
|
589
|
-
}, []).join(",");
|
|
590
|
-
}, a = function(n) {
|
|
591
|
-
var o = i(n);
|
|
592
|
-
return o.location = "no", n && n.prompt == "none" && (o.hidden = "yes"), s(o);
|
|
593
|
-
}, c = function() {
|
|
594
|
-
return e.redirectUri || "http://localhost";
|
|
595
|
-
};
|
|
596
|
-
return {
|
|
597
|
-
login: async function(n) {
|
|
598
|
-
var o = w(), u = a(n), p = await e.createLoginUrl(n), d = t(p, "_blank", u), g = !1, S = !1, I = function() {
|
|
599
|
-
S = !0, d.close();
|
|
600
|
-
};
|
|
601
|
-
return d.addEventListener("loadstart", function(U) {
|
|
602
|
-
if (U.url.indexOf(c()) == 0) {
|
|
603
|
-
var z = E(U.url);
|
|
604
|
-
A(z, o), I(), g = !0;
|
|
605
|
-
}
|
|
606
|
-
}), d.addEventListener("loaderror", function(U) {
|
|
607
|
-
if (!g)
|
|
608
|
-
if (U.url.indexOf(c()) == 0) {
|
|
609
|
-
var z = E(U.url);
|
|
610
|
-
A(z, o), I(), g = !0;
|
|
611
|
-
} else
|
|
612
|
-
o.setError(), I();
|
|
613
|
-
}), d.addEventListener("exit", function(U) {
|
|
614
|
-
S || o.setError({
|
|
615
|
-
reason: "closed_by_user"
|
|
616
|
-
});
|
|
617
|
-
}), o.promise;
|
|
618
|
-
},
|
|
619
|
-
logout: function(n) {
|
|
620
|
-
var o = w(), u = e.createLogoutUrl(n), p = t(u, "_blank", "location=no,hidden=yes,clearcache=yes"), d;
|
|
621
|
-
return p.addEventListener("loadstart", function(g) {
|
|
622
|
-
g.url.indexOf(c()) == 0 && p.close();
|
|
623
|
-
}), p.addEventListener("loaderror", function(g) {
|
|
624
|
-
g.url.indexOf(c()) == 0 || (d = !0), p.close();
|
|
625
|
-
}), p.addEventListener("exit", function(g) {
|
|
626
|
-
d ? o.setError() : (e.clearToken(), o.setSuccess());
|
|
627
|
-
}), o.promise;
|
|
628
|
-
},
|
|
629
|
-
register: async function(n) {
|
|
630
|
-
var o = w(), u = await e.createRegisterUrl(), p = a(n), d = t(u, "_blank", p);
|
|
631
|
-
return d.addEventListener("loadstart", function(g) {
|
|
632
|
-
if (g.url.indexOf(c()) == 0) {
|
|
633
|
-
d.close();
|
|
634
|
-
var S = E(g.url);
|
|
635
|
-
A(S, o);
|
|
636
|
-
}
|
|
637
|
-
}), o.promise;
|
|
638
|
-
},
|
|
639
|
-
accountManagement: function() {
|
|
640
|
-
var n = e.createAccountUrl();
|
|
641
|
-
if (typeof n < "u") {
|
|
642
|
-
var o = t(n, "_blank", "location=no");
|
|
643
|
-
o.addEventListener("loadstart", function(u) {
|
|
644
|
-
u.url.indexOf(c()) == 0 && o.close();
|
|
645
|
-
});
|
|
646
|
-
} else
|
|
647
|
-
throw "Not supported by the OIDC server";
|
|
648
|
-
},
|
|
649
|
-
redirectUri: function(n) {
|
|
650
|
-
return c();
|
|
651
|
-
}
|
|
652
|
-
};
|
|
653
|
-
}
|
|
654
|
-
if (r == "cordova-native")
|
|
655
|
-
return h.enable = !1, {
|
|
656
|
-
login: async function(n) {
|
|
657
|
-
var o = w(), u = await e.createLoginUrl(n);
|
|
658
|
-
return universalLinks.subscribe("keycloak", function(p) {
|
|
659
|
-
universalLinks.unsubscribe("keycloak"), window.cordova.plugins.browsertab.close();
|
|
660
|
-
var d = E(p.url);
|
|
661
|
-
A(d, o);
|
|
662
|
-
}), window.cordova.plugins.browsertab.openUrl(u), o.promise;
|
|
663
|
-
},
|
|
664
|
-
logout: function(n) {
|
|
665
|
-
var o = w(), u = e.createLogoutUrl(n);
|
|
666
|
-
return universalLinks.subscribe("keycloak", function(p) {
|
|
667
|
-
universalLinks.unsubscribe("keycloak"), window.cordova.plugins.browsertab.close(), e.clearToken(), o.setSuccess();
|
|
668
|
-
}), window.cordova.plugins.browsertab.openUrl(u), o.promise;
|
|
669
|
-
},
|
|
670
|
-
register: async function(n) {
|
|
671
|
-
var o = w(), u = await e.createRegisterUrl(n);
|
|
672
|
-
return universalLinks.subscribe("keycloak", function(p) {
|
|
673
|
-
universalLinks.unsubscribe("keycloak"), window.cordova.plugins.browsertab.close();
|
|
674
|
-
var d = E(p.url);
|
|
675
|
-
A(d, o);
|
|
676
|
-
}), window.cordova.plugins.browsertab.openUrl(u), o.promise;
|
|
677
|
-
},
|
|
678
|
-
accountManagement: function() {
|
|
679
|
-
var n = e.createAccountUrl();
|
|
680
|
-
if (typeof n < "u")
|
|
681
|
-
window.cordova.plugins.browsertab.openUrl(n);
|
|
682
|
-
else
|
|
683
|
-
throw "Not supported by the OIDC server";
|
|
684
|
-
},
|
|
685
|
-
redirectUri: function(n) {
|
|
686
|
-
return n && n.redirectUri ? n.redirectUri : e.redirectUri ? e.redirectUri : "http://localhost";
|
|
687
|
-
}
|
|
688
|
-
};
|
|
689
|
-
throw "invalid adapter type: " + r;
|
|
690
|
-
}
|
|
691
|
-
const L = "kc-callback-";
|
|
692
|
-
var j = function() {
|
|
693
|
-
if (!(this instanceof j))
|
|
694
|
-
return new j();
|
|
695
|
-
localStorage.setItem("kc-test", "test"), localStorage.removeItem("kc-test");
|
|
696
|
-
var r = this;
|
|
697
|
-
function t() {
|
|
698
|
-
const c = Date.now();
|
|
699
|
-
for (const [n, o] of s()) {
|
|
700
|
-
const u = a(o);
|
|
701
|
-
(u === null || u < c) && localStorage.removeItem(n);
|
|
702
|
-
}
|
|
703
|
-
}
|
|
704
|
-
function i() {
|
|
705
|
-
for (const [c] of s())
|
|
706
|
-
localStorage.removeItem(c);
|
|
707
|
-
}
|
|
708
|
-
function s() {
|
|
709
|
-
return Object.entries(localStorage).filter(([c]) => c.startsWith(L));
|
|
710
|
-
}
|
|
711
|
-
function a(c) {
|
|
712
|
-
let n;
|
|
622
|
+
async #w() {
|
|
623
|
+
this.#e.enable && this.token && (await X(this.#e.interval * 1e3), await this.#d() && await this.#w());
|
|
624
|
+
}
|
|
625
|
+
/**
|
|
626
|
+
* @param {KeycloakLoginOptions} [options]
|
|
627
|
+
* @returns {Promise<void>}
|
|
628
|
+
*/
|
|
629
|
+
login = (e) => this.#t.login(e);
|
|
630
|
+
/**
|
|
631
|
+
* @param {KeycloakLoginOptions} [options]
|
|
632
|
+
* @returns {Promise<string>}
|
|
633
|
+
*/
|
|
634
|
+
createLoginUrl = async (e) => {
|
|
635
|
+
const t = S(), r = S(), o = this.#t.redirectUri(e), s = {
|
|
636
|
+
state: t,
|
|
637
|
+
nonce: r,
|
|
638
|
+
redirectUri: o,
|
|
639
|
+
loginOptions: e
|
|
640
|
+
};
|
|
641
|
+
e?.prompt && (s.prompt = e.prompt);
|
|
642
|
+
const n = e?.action === "register" ? this.endpoints.register() : this.endpoints.authorize();
|
|
643
|
+
let a = e?.scope || this.scope;
|
|
644
|
+
const c = a ? a.split(" ") : [];
|
|
645
|
+
c.includes("openid") || c.unshift("openid"), a = c.join(" ");
|
|
646
|
+
const l = new URLSearchParams([
|
|
647
|
+
[
|
|
648
|
+
"client_id",
|
|
649
|
+
/** @type {string} */
|
|
650
|
+
this.clientId
|
|
651
|
+
],
|
|
652
|
+
["redirect_uri", o],
|
|
653
|
+
["state", t],
|
|
654
|
+
["response_mode", this.responseMode],
|
|
655
|
+
["response_type", this.responseType],
|
|
656
|
+
["scope", a]
|
|
657
|
+
]);
|
|
658
|
+
if (this.#o && l.append("nonce", r), e?.prompt && l.append("prompt", e.prompt), typeof e?.maxAge == "number" && l.append("max_age", e.maxAge.toString()), e?.loginHint && l.append("login_hint", e.loginHint), e?.idpHint && l.append("kc_idp_hint", e.idpHint), e?.action && e.action !== "register" && l.append("kc_action", e.action), e?.locale && l.append("ui_locales", e.locale), e?.acr && l.append("claims", M(e.acr)), e?.acrValues && l.append("acr_values", e.acrValues), this.pkceMethod)
|
|
713
659
|
try {
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
660
|
+
const d = N(96), h = await D(this.pkceMethod, d);
|
|
661
|
+
s.pkceCodeVerifier = d, l.append("code_challenge", h), l.append("code_challenge_method", this.pkceMethod);
|
|
662
|
+
} catch (d) {
|
|
663
|
+
throw new Error("Failed to generate PKCE challenge.", { cause: d });
|
|
717
664
|
}
|
|
718
|
-
|
|
665
|
+
return this.#l.add(s), `${n}?${l.toString()}`;
|
|
666
|
+
};
|
|
667
|
+
/**
|
|
668
|
+
* @param {KeycloakLogoutOptions} [options]
|
|
669
|
+
* @returns {Promise<void>}
|
|
670
|
+
*/
|
|
671
|
+
logout = (e) => this.#t.logout(e);
|
|
672
|
+
/**
|
|
673
|
+
* @param {KeycloakLogoutOptions} [options]
|
|
674
|
+
* @returns {string}
|
|
675
|
+
*/
|
|
676
|
+
createLogoutUrl = (e) => {
|
|
677
|
+
const t = e?.logoutMethod ?? this.logoutMethod, r = this.endpoints.logout();
|
|
678
|
+
if (t === "POST")
|
|
679
|
+
return r;
|
|
680
|
+
const o = new URLSearchParams([
|
|
681
|
+
[
|
|
682
|
+
"client_id",
|
|
683
|
+
/** @type {string} */
|
|
684
|
+
this.clientId
|
|
685
|
+
],
|
|
686
|
+
["post_logout_redirect_uri", this.#t.redirectUri(e)]
|
|
687
|
+
]);
|
|
688
|
+
return this.idToken && o.append("id_token_hint", this.idToken), `${r}?${o.toString()}`;
|
|
689
|
+
};
|
|
690
|
+
/**
|
|
691
|
+
* @param {KeycloakRegisterOptions} [options]
|
|
692
|
+
* @returns {Promise<void>}
|
|
693
|
+
*/
|
|
694
|
+
register = (e) => this.#t.register(e);
|
|
695
|
+
/**
|
|
696
|
+
* @param {KeycloakRegisterOptions} [options]
|
|
697
|
+
* @returns {Promise<string>}
|
|
698
|
+
*/
|
|
699
|
+
createRegisterUrl = (e) => this.createLoginUrl({ ...e, action: "register" });
|
|
700
|
+
/**
|
|
701
|
+
* @param {KeycloakAccountOptions} [options]
|
|
702
|
+
* @returns {string}
|
|
703
|
+
*/
|
|
704
|
+
createAccountUrl = (e) => {
|
|
705
|
+
const t = this.#s();
|
|
706
|
+
if (!t)
|
|
707
|
+
throw new Error("Unable to create account URL, make sure the adapter is not configured using a generic OIDC provider.");
|
|
708
|
+
const r = new URLSearchParams([
|
|
709
|
+
[
|
|
710
|
+
"referrer",
|
|
711
|
+
/** @type {string} */
|
|
712
|
+
this.clientId
|
|
713
|
+
],
|
|
714
|
+
["referrer_uri", this.#t.redirectUri(e)]
|
|
715
|
+
]);
|
|
716
|
+
return `${t}/account?${r.toString()}`;
|
|
717
|
+
};
|
|
718
|
+
/**
|
|
719
|
+
* @returns {Promise<void>}
|
|
720
|
+
*/
|
|
721
|
+
accountManagement = () => this.#t.accountManagement();
|
|
722
|
+
/**
|
|
723
|
+
* @param {string} role
|
|
724
|
+
* @returns {boolean}
|
|
725
|
+
*/
|
|
726
|
+
hasRealmRole = (e) => {
|
|
727
|
+
const t = this.realmAccess;
|
|
728
|
+
return !!t && t.roles.indexOf(e) >= 0;
|
|
729
|
+
};
|
|
730
|
+
/**
|
|
731
|
+
* @param {string} role
|
|
732
|
+
* @param {string} [resource]
|
|
733
|
+
* @returns {boolean}
|
|
734
|
+
*/
|
|
735
|
+
hasResourceRole = (e, t) => {
|
|
736
|
+
if (!this.resourceAccess)
|
|
737
|
+
return !1;
|
|
738
|
+
const r = this.resourceAccess[t || /** @type {string} */
|
|
739
|
+
this.clientId];
|
|
740
|
+
return !!r && r.roles.indexOf(e) >= 0;
|
|
741
|
+
};
|
|
742
|
+
/**
|
|
743
|
+
* @returns {Promise<KeycloakProfile>}
|
|
744
|
+
*/
|
|
745
|
+
loadUserProfile = async () => {
|
|
746
|
+
const e = this.#s();
|
|
747
|
+
if (!e)
|
|
748
|
+
throw new Error("Unable to load user profile, make sure the adapter is not configured using a generic OIDC provider.");
|
|
749
|
+
const t = `${e}/account`, r = await k(t, {
|
|
750
|
+
headers: [_(this.token)]
|
|
751
|
+
});
|
|
752
|
+
return this.profile = r;
|
|
753
|
+
};
|
|
754
|
+
/**
|
|
755
|
+
* @returns {Promise<{}>}
|
|
756
|
+
*/
|
|
757
|
+
loadUserInfo = async () => {
|
|
758
|
+
const e = this.endpoints.userinfo(), t = await k(e, {
|
|
759
|
+
headers: [_(this.token)]
|
|
760
|
+
});
|
|
761
|
+
return this.userInfo = t;
|
|
762
|
+
};
|
|
763
|
+
/**
|
|
764
|
+
* @param {number} [minValidity]
|
|
765
|
+
* @returns {boolean}
|
|
766
|
+
*/
|
|
767
|
+
isTokenExpired = (e) => {
|
|
768
|
+
if (!this.tokenParsed || !this.refreshToken && this.flow !== "implicit")
|
|
769
|
+
throw new Error("Not authenticated");
|
|
770
|
+
if (this.timeSkew == null)
|
|
771
|
+
return this.#n("[KEYCLOAK] Unable to determine if token is expired as timeskew is not set"), !0;
|
|
772
|
+
if (typeof this.tokenParsed.exp != "number")
|
|
773
|
+
return !1;
|
|
774
|
+
let t = this.tokenParsed.exp - Math.ceil((/* @__PURE__ */ new Date()).getTime() / 1e3) + this.timeSkew;
|
|
775
|
+
if (e) {
|
|
776
|
+
if (isNaN(e))
|
|
777
|
+
throw new Error("Invalid minValidity");
|
|
778
|
+
t -= e;
|
|
719
779
|
}
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
780
|
+
return t < 0;
|
|
781
|
+
};
|
|
782
|
+
/**
|
|
783
|
+
* @param {number} minValidity
|
|
784
|
+
* @returns {Promise<boolean>}
|
|
785
|
+
*/
|
|
786
|
+
updateToken = async (e) => {
|
|
787
|
+
if (!this.refreshToken)
|
|
788
|
+
throw new Error("Unable to update token, no refresh token available.");
|
|
789
|
+
e = e || 5, this.#e.enable && await this.#d();
|
|
790
|
+
let t = !1;
|
|
791
|
+
if (e === -1 ? (t = !0, this.#n("[KEYCLOAK] Refreshing token: forced refresh")) : (!this.tokenParsed || this.isTokenExpired(e)) && (t = !0, this.#n("[KEYCLOAK] Refreshing token: token expired")), !t)
|
|
792
|
+
return !1;
|
|
793
|
+
const { promise: r, resolve: o, reject: s } = Promise.withResolvers();
|
|
794
|
+
if (this.#r.push({ resolve: o, reject: s }), this.#r.length === 1) {
|
|
795
|
+
const n = this.endpoints.token();
|
|
796
|
+
let a = (/* @__PURE__ */ new Date()).getTime();
|
|
732
797
|
try {
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
return JSON.parse(c);
|
|
798
|
+
const c = await G(
|
|
799
|
+
n,
|
|
800
|
+
this.refreshToken,
|
|
801
|
+
/** @type {string} */
|
|
802
|
+
this.clientId
|
|
803
|
+
);
|
|
804
|
+
this.#n("[KEYCLOAK] Token refreshed"), a = (a + (/* @__PURE__ */ new Date()).getTime()) / 2, this.#h(c.access_token, c.refresh_token, c.id_token, a), this.onAuthRefreshSuccess?.();
|
|
805
|
+
for (let l = this.#r.pop(); l != null; l = this.#r.pop())
|
|
806
|
+
l.resolve(!0);
|
|
807
|
+
} catch (c) {
|
|
808
|
+
this.#u("[KEYCLOAK] Failed to refresh token"), c instanceof A && c.response.status === 400 && this.clearToken(), this.onAuthRefreshError?.();
|
|
809
|
+
for (let l = this.#r.pop(); l != null; l = this.#r.pop())
|
|
810
|
+
l.reject(c);
|
|
747
811
|
}
|
|
748
|
-
}
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
812
|
+
}
|
|
813
|
+
return await r;
|
|
814
|
+
};
|
|
815
|
+
clearToken = () => {
|
|
816
|
+
this.token && (this.#h(), this.onAuthLogout?.(), this.loginRequired && this.login());
|
|
817
|
+
};
|
|
818
|
+
/**
|
|
819
|
+
* @param {string} [token]
|
|
820
|
+
* @param {string} [refreshToken]
|
|
821
|
+
* @param {string} [idToken]
|
|
822
|
+
* @param {number} [timeLocal]
|
|
823
|
+
*/
|
|
824
|
+
#h(e, t, r, o) {
|
|
825
|
+
if (this.tokenTimeoutHandle && (clearTimeout(this.tokenTimeoutHandle), this.tokenTimeoutHandle = void 0), t ? (this.refreshToken = t, this.refreshTokenParsed = b(t)) : (delete this.refreshToken, delete this.refreshTokenParsed), r ? (this.idToken = r, this.idTokenParsed = b(r)) : (delete this.idToken, delete this.idTokenParsed), e) {
|
|
826
|
+
if (this.token = e, this.tokenParsed = b(e), this.sessionId = this.tokenParsed.sid, this.authenticated = !0, this.subject = this.tokenParsed.sub, this.realmAccess = this.tokenParsed.realm_access, this.resourceAccess = this.tokenParsed.resource_access, o && (this.timeSkew = Math.floor(o / 1e3) - this.tokenParsed.iat), this.timeSkew !== null && (this.#n("[KEYCLOAK] Estimated time difference between browser and server is " + this.timeSkew + " seconds"), this.onTokenExpired)) {
|
|
827
|
+
const s = (this.tokenParsed.exp - (/* @__PURE__ */ new Date()).getTime() / 1e3 + this.timeSkew) * 1e3;
|
|
828
|
+
this.#n("[KEYCLOAK] Token expires in " + Math.round(s / 1e3) + " s"), s <= 0 ? this.onTokenExpired() : this.tokenTimeoutHandle = window.setTimeout(this.onTokenExpired, s);
|
|
762
829
|
}
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
830
|
+
} else
|
|
831
|
+
delete this.token, delete this.tokenParsed, delete this.subject, delete this.realmAccess, delete this.resourceAccess, this.authenticated = !1;
|
|
832
|
+
}
|
|
833
|
+
/**
|
|
834
|
+
* @returns {string=}
|
|
835
|
+
*/
|
|
836
|
+
#s() {
|
|
837
|
+
if (!(typeof this.authServerUrl > "u"))
|
|
838
|
+
return `${E(this.authServerUrl)}/realms/${encodeURIComponent(
|
|
839
|
+
/** @type {string} */
|
|
840
|
+
this.realm
|
|
841
|
+
)}`;
|
|
842
|
+
}
|
|
843
|
+
/**
|
|
844
|
+
* @param {Function} fn
|
|
845
|
+
* @returns {(message: string) => void}
|
|
846
|
+
*/
|
|
847
|
+
#b(e) {
|
|
848
|
+
return (t) => {
|
|
849
|
+
this.enableLogging && e.call(console, t);
|
|
767
850
|
};
|
|
768
|
-
}
|
|
769
|
-
|
|
851
|
+
}
|
|
852
|
+
}
|
|
853
|
+
function S() {
|
|
854
|
+
if (typeof crypto > "u" || typeof crypto.randomUUID > "u")
|
|
855
|
+
throw new Error("Web Crypto API is not available.");
|
|
856
|
+
return crypto.randomUUID();
|
|
857
|
+
}
|
|
858
|
+
function M(i) {
|
|
859
|
+
return JSON.stringify({
|
|
860
|
+
id_token: {
|
|
861
|
+
acr: i
|
|
862
|
+
}
|
|
863
|
+
});
|
|
864
|
+
}
|
|
865
|
+
function N(i) {
|
|
866
|
+
return K(i, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
|
|
867
|
+
}
|
|
868
|
+
async function D(i, e) {
|
|
869
|
+
if (i !== "S256")
|
|
870
|
+
throw new TypeError(`Invalid value for 'pkceMethod', expected 'S256' but got '${i}'.`);
|
|
871
|
+
const t = new Uint8Array(await W(e));
|
|
872
|
+
return J(t).replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
|
|
873
|
+
}
|
|
874
|
+
function K(i, e) {
|
|
875
|
+
const t = O(i), r = new Array(i);
|
|
876
|
+
for (let o = 0; o < i; o++)
|
|
877
|
+
r[o] = e.charCodeAt(t[o] % e.length);
|
|
878
|
+
return String.fromCharCode.apply(null, r);
|
|
879
|
+
}
|
|
880
|
+
function O(i) {
|
|
881
|
+
if (typeof crypto > "u" || typeof crypto.getRandomValues > "u")
|
|
882
|
+
throw new Error("Web Crypto API is not available.");
|
|
883
|
+
return crypto.getRandomValues(new Uint8Array(i));
|
|
884
|
+
}
|
|
885
|
+
function j(i, e, t) {
|
|
886
|
+
let r;
|
|
887
|
+
const o = new Promise(function(s, n) {
|
|
888
|
+
r = window.setTimeout(function() {
|
|
889
|
+
n(new Error(t));
|
|
890
|
+
}, e);
|
|
891
|
+
});
|
|
892
|
+
return Promise.race([i, o]).finally(function() {
|
|
893
|
+
clearTimeout(r);
|
|
894
|
+
});
|
|
895
|
+
}
|
|
896
|
+
function z() {
|
|
897
|
+
try {
|
|
898
|
+
return new H();
|
|
899
|
+
} catch {
|
|
900
|
+
return new $();
|
|
901
|
+
}
|
|
902
|
+
}
|
|
903
|
+
const g = "kc-callback-";
|
|
904
|
+
class H {
|
|
905
|
+
constructor() {
|
|
906
|
+
globalThis.localStorage.setItem("kc-test", "test"), globalThis.localStorage.removeItem("kc-test");
|
|
907
|
+
}
|
|
908
|
+
/**
|
|
909
|
+
* @param {string} [state]
|
|
910
|
+
* @returns {CallbackState | null}
|
|
911
|
+
*/
|
|
912
|
+
get(e) {
|
|
913
|
+
if (!e)
|
|
914
|
+
return null;
|
|
915
|
+
this.#r();
|
|
916
|
+
const t = g + e, r = globalThis.localStorage.getItem(t);
|
|
917
|
+
return r ? (globalThis.localStorage.removeItem(t), JSON.parse(r)) : null;
|
|
918
|
+
}
|
|
919
|
+
/**
|
|
920
|
+
* @param {CallbackState} state
|
|
921
|
+
*/
|
|
922
|
+
add(e) {
|
|
923
|
+
this.#r();
|
|
924
|
+
const t = g + e.state, r = JSON.stringify({
|
|
925
|
+
...e,
|
|
926
|
+
// Set the expiry time to 1 hour from now.
|
|
927
|
+
expires: Date.now() + 3600 * 1e3
|
|
928
|
+
});
|
|
770
929
|
try {
|
|
771
|
-
|
|
930
|
+
globalThis.localStorage.setItem(t, r);
|
|
772
931
|
} catch {
|
|
932
|
+
this.#t(), globalThis.localStorage.setItem(t, r);
|
|
773
933
|
}
|
|
774
|
-
return new O();
|
|
775
934
|
}
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
935
|
+
/**
|
|
936
|
+
* Clears all values from local storage that are no longer valid.
|
|
937
|
+
*/
|
|
938
|
+
#r() {
|
|
939
|
+
const e = Date.now();
|
|
940
|
+
for (const [t, r] of this.#o()) {
|
|
941
|
+
const o = this.#l(r);
|
|
942
|
+
(o === null || o < e) && globalThis.localStorage.removeItem(t);
|
|
943
|
+
}
|
|
944
|
+
}
|
|
945
|
+
/**
|
|
946
|
+
* Clears all known values from local storage.
|
|
947
|
+
*/
|
|
948
|
+
#t() {
|
|
949
|
+
for (const [e] of this.#o())
|
|
950
|
+
globalThis.localStorage.removeItem(e);
|
|
951
|
+
}
|
|
952
|
+
/**
|
|
953
|
+
* Gets all entries stored in local storage that are known to be managed by this class.
|
|
954
|
+
* @returns {[string, string][]} An array of key-value pairs.
|
|
955
|
+
*/
|
|
956
|
+
#o() {
|
|
957
|
+
return Object.entries(globalThis.localStorage).filter(([e]) => e.startsWith(g));
|
|
958
|
+
}
|
|
959
|
+
/**
|
|
960
|
+
* Parses the expiry time from a value stored in local storage.
|
|
961
|
+
* @param {string} value
|
|
962
|
+
* @returns {number | null} The expiry time in milliseconds, or `null` if the value is malformed.
|
|
963
|
+
*/
|
|
964
|
+
#l(e) {
|
|
965
|
+
let t;
|
|
966
|
+
try {
|
|
967
|
+
t = JSON.parse(e);
|
|
968
|
+
} catch {
|
|
969
|
+
return null;
|
|
970
|
+
}
|
|
971
|
+
return v(t) && "expires" in t && typeof t.expires == "number" ? t.expires : null;
|
|
972
|
+
}
|
|
973
|
+
}
|
|
974
|
+
class $ {
|
|
975
|
+
/**
|
|
976
|
+
* @param {string} [state]
|
|
977
|
+
* @returns {CallbackState | null}
|
|
978
|
+
*/
|
|
979
|
+
get(e) {
|
|
980
|
+
if (!e)
|
|
981
|
+
return null;
|
|
982
|
+
const t = this.#r(g + e);
|
|
983
|
+
return this.#t(g + e, "", this.#o(-100)), t ? JSON.parse(t) : null;
|
|
984
|
+
}
|
|
985
|
+
/**
|
|
986
|
+
* @param {CallbackState} state
|
|
987
|
+
*/
|
|
988
|
+
add(e) {
|
|
989
|
+
this.#t(g + e.state, JSON.stringify(e), this.#o(60));
|
|
990
|
+
}
|
|
991
|
+
/**
|
|
992
|
+
* @param {string} key
|
|
993
|
+
* @returns
|
|
994
|
+
*/
|
|
995
|
+
#r(e) {
|
|
996
|
+
const t = e + "=", r = document.cookie.split(";");
|
|
997
|
+
for (let o = 0; o < r.length; o++) {
|
|
998
|
+
let s = r[o];
|
|
999
|
+
for (; s.charAt(0) === " "; )
|
|
1000
|
+
s = s.substring(1);
|
|
1001
|
+
if (s.indexOf(t) === 0)
|
|
1002
|
+
return s.substring(t.length, s.length);
|
|
1003
|
+
}
|
|
1004
|
+
return "";
|
|
1005
|
+
}
|
|
1006
|
+
/**
|
|
1007
|
+
* @param {string} key
|
|
1008
|
+
* @param {string} value
|
|
1009
|
+
* @param {Date} expirationDate
|
|
1010
|
+
*/
|
|
1011
|
+
#t(e, t, r) {
|
|
1012
|
+
const o = e + "=" + t + "; expires=" + r.toUTCString() + "; ";
|
|
1013
|
+
document.cookie = o;
|
|
1014
|
+
}
|
|
1015
|
+
/**
|
|
1016
|
+
* @param {number} minutes
|
|
1017
|
+
* @returns {Date}
|
|
1018
|
+
*/
|
|
1019
|
+
#o(e) {
|
|
1020
|
+
const t = /* @__PURE__ */ new Date();
|
|
1021
|
+
return t.setTime(t.getTime() + e * 60 * 1e3), t;
|
|
780
1022
|
}
|
|
781
1023
|
}
|
|
782
|
-
function
|
|
783
|
-
const e = String.fromCodePoint(...
|
|
1024
|
+
function J(i) {
|
|
1025
|
+
const e = String.fromCodePoint(...i);
|
|
784
1026
|
return btoa(e);
|
|
785
1027
|
}
|
|
786
|
-
async function
|
|
787
|
-
const
|
|
1028
|
+
async function W(i) {
|
|
1029
|
+
const t = new TextEncoder().encode(i);
|
|
788
1030
|
if (typeof crypto > "u" || typeof crypto.subtle > "u")
|
|
789
1031
|
throw new Error("Web Crypto API is not available.");
|
|
790
|
-
return await crypto.subtle.digest("SHA-256",
|
|
1032
|
+
return await crypto.subtle.digest("SHA-256", t);
|
|
791
1033
|
}
|
|
792
|
-
function
|
|
793
|
-
const [
|
|
794
|
-
if (typeof
|
|
1034
|
+
function b(i) {
|
|
1035
|
+
const [, e] = i.split(".");
|
|
1036
|
+
if (typeof e != "string")
|
|
795
1037
|
throw new Error("Unable to decode token, payload not found.");
|
|
796
|
-
let
|
|
1038
|
+
let t;
|
|
797
1039
|
try {
|
|
798
|
-
|
|
799
|
-
} catch (
|
|
800
|
-
throw new Error("Unable to decode token, payload is not a valid Base64URL value.", { cause:
|
|
1040
|
+
t = F(e);
|
|
1041
|
+
} catch (r) {
|
|
1042
|
+
throw new Error("Unable to decode token, payload is not a valid Base64URL value.", { cause: r });
|
|
801
1043
|
}
|
|
802
1044
|
try {
|
|
803
|
-
return JSON.parse(
|
|
804
|
-
} catch (
|
|
805
|
-
throw new Error("Unable to decode token, payload is not a valid JSON value.", { cause:
|
|
1045
|
+
return JSON.parse(t);
|
|
1046
|
+
} catch (r) {
|
|
1047
|
+
throw new Error("Unable to decode token, payload is not a valid JSON value.", { cause: r });
|
|
806
1048
|
}
|
|
807
1049
|
}
|
|
808
|
-
function
|
|
809
|
-
let e =
|
|
1050
|
+
function F(i) {
|
|
1051
|
+
let e = i.replaceAll("-", "+").replaceAll("_", "/");
|
|
810
1052
|
switch (e.length % 4) {
|
|
811
1053
|
case 0:
|
|
812
1054
|
break;
|
|
@@ -820,21 +1062,85 @@ function ue(l) {
|
|
|
820
1062
|
throw new Error("Input is not of the correct length.");
|
|
821
1063
|
}
|
|
822
1064
|
try {
|
|
823
|
-
return
|
|
1065
|
+
return q(e);
|
|
824
1066
|
} catch {
|
|
825
1067
|
return atob(e);
|
|
826
1068
|
}
|
|
827
1069
|
}
|
|
828
|
-
function
|
|
829
|
-
return decodeURIComponent(atob(
|
|
830
|
-
let
|
|
831
|
-
return
|
|
1070
|
+
function q(i) {
|
|
1071
|
+
return decodeURIComponent(atob(i).replace(/(.)/g, (e, t) => {
|
|
1072
|
+
let r = t.charCodeAt(0).toString(16).toUpperCase();
|
|
1073
|
+
return r.length < 2 && (r = "0" + r), "%" + r;
|
|
832
1074
|
}));
|
|
833
1075
|
}
|
|
834
|
-
function
|
|
835
|
-
return typeof
|
|
1076
|
+
function v(i) {
|
|
1077
|
+
return typeof i == "object" && i !== null;
|
|
836
1078
|
}
|
|
837
|
-
|
|
1079
|
+
async function Y(i) {
|
|
1080
|
+
return await k(i);
|
|
1081
|
+
}
|
|
1082
|
+
async function V(i) {
|
|
1083
|
+
return await k(i);
|
|
1084
|
+
}
|
|
1085
|
+
async function B(i, e, t, r, o) {
|
|
1086
|
+
const s = new URLSearchParams([
|
|
1087
|
+
["code", e],
|
|
1088
|
+
["grant_type", "authorization_code"],
|
|
1089
|
+
["client_id", t],
|
|
1090
|
+
["redirect_uri", r]
|
|
1091
|
+
]);
|
|
1092
|
+
return o && s.append("code_verifier", o), await k(i, {
|
|
1093
|
+
method: "POST",
|
|
1094
|
+
credentials: "include",
|
|
1095
|
+
body: s
|
|
1096
|
+
});
|
|
1097
|
+
}
|
|
1098
|
+
async function G(i, e, t) {
|
|
1099
|
+
const r = new URLSearchParams([
|
|
1100
|
+
["grant_type", "refresh_token"],
|
|
1101
|
+
["refresh_token", e],
|
|
1102
|
+
["client_id", t]
|
|
1103
|
+
]);
|
|
1104
|
+
return await k(i, {
|
|
1105
|
+
method: "POST",
|
|
1106
|
+
credentials: "include",
|
|
1107
|
+
body: r
|
|
1108
|
+
});
|
|
1109
|
+
}
|
|
1110
|
+
async function k(i, e = {}) {
|
|
1111
|
+
const t = new Headers(e.headers);
|
|
1112
|
+
return t.set("Accept", R), await (await Q(i, {
|
|
1113
|
+
...e,
|
|
1114
|
+
headers: t
|
|
1115
|
+
})).json();
|
|
1116
|
+
}
|
|
1117
|
+
async function Q(i, e) {
|
|
1118
|
+
const t = await fetch(i, e);
|
|
1119
|
+
if (!t.ok)
|
|
1120
|
+
throw new A("Server responded with an invalid status.", { response: t });
|
|
1121
|
+
return t;
|
|
1122
|
+
}
|
|
1123
|
+
function _(i) {
|
|
1124
|
+
if (!i)
|
|
1125
|
+
throw new Error("Unable to build authorization header, token is not set, make sure the user is authenticated.");
|
|
1126
|
+
return ["Authorization", `bearer ${i}`];
|
|
1127
|
+
}
|
|
1128
|
+
function E(i) {
|
|
1129
|
+
return i.endsWith("/") ? i.slice(0, -1) : i;
|
|
1130
|
+
}
|
|
1131
|
+
class A extends Error {
|
|
1132
|
+
/** @type {Response} */
|
|
1133
|
+
response;
|
|
1134
|
+
/**
|
|
1135
|
+
* @param {string} message
|
|
1136
|
+
* @param {NetworkErrorOptions} options
|
|
1137
|
+
*/
|
|
1138
|
+
constructor(e, t) {
|
|
1139
|
+
super(e, t), this.response = t.response;
|
|
1140
|
+
}
|
|
1141
|
+
}
|
|
1142
|
+
const X = (i) => new Promise((e) => setTimeout(e, i));
|
|
1143
|
+
class U extends x {
|
|
838
1144
|
constructor(e) {
|
|
839
1145
|
super(e);
|
|
840
1146
|
}
|
|
@@ -849,8 +1155,8 @@ class Y extends $ {
|
|
|
849
1155
|
}
|
|
850
1156
|
}
|
|
851
1157
|
static async init(e) {
|
|
852
|
-
const
|
|
853
|
-
return console.log("KeycloakAdapter", e), await
|
|
1158
|
+
const t = new U(e);
|
|
1159
|
+
return console.log("KeycloakAdapter", e), await t.initialize(), t;
|
|
854
1160
|
}
|
|
855
1161
|
get userInfo() {
|
|
856
1162
|
return this.idTokenParsed;
|
|
@@ -862,116 +1168,107 @@ class Y extends $ {
|
|
|
862
1168
|
return this.authenticated ?? !1;
|
|
863
1169
|
}
|
|
864
1170
|
}
|
|
865
|
-
const
|
|
1171
|
+
const Z = {
|
|
866
1172
|
skipAuthentication: !1
|
|
867
|
-
},
|
|
868
|
-
const e =
|
|
869
|
-
let
|
|
870
|
-
const
|
|
871
|
-
const
|
|
872
|
-
return
|
|
873
|
-
},
|
|
874
|
-
if (!
|
|
875
|
-
return
|
|
876
|
-
e.value || await new Promise((
|
|
877
|
-
const
|
|
878
|
-
|
|
1173
|
+
}, te = (i) => {
|
|
1174
|
+
const e = P(!1);
|
|
1175
|
+
let t;
|
|
1176
|
+
const r = { ...Z, ...i }, o = async () => {
|
|
1177
|
+
const h = await U.init(i.keycloak);
|
|
1178
|
+
return t = h, e.value = !0, h;
|
|
1179
|
+
}, s = () => t?.token, n = async () => {
|
|
1180
|
+
if (!t)
|
|
1181
|
+
return o();
|
|
1182
|
+
e.value || await new Promise((h) => {
|
|
1183
|
+
const f = L(e, (p) => {
|
|
1184
|
+
p && (f(), h());
|
|
879
1185
|
});
|
|
880
1186
|
});
|
|
881
|
-
},
|
|
882
|
-
install(
|
|
883
|
-
|
|
884
|
-
|
|
1187
|
+
}, d = I({
|
|
1188
|
+
install(h) {
|
|
1189
|
+
h.runWithContext(() => {
|
|
1190
|
+
h.config.globalProperties.$auth = r, h.provide(T, d);
|
|
885
1191
|
});
|
|
886
1192
|
},
|
|
887
|
-
updateToken: async () =>
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
user: async () => {
|
|
893
|
-
var v;
|
|
894
|
-
return (v = await y()) == null ? void 0 : v.userInfo;
|
|
895
|
-
},
|
|
896
|
-
logout: async () => {
|
|
897
|
-
var v;
|
|
898
|
-
return (v = await y()) == null ? void 0 : v.logout();
|
|
899
|
-
},
|
|
900
|
-
options: k
|
|
1193
|
+
updateToken: async () => (await n())?.updateToken(),
|
|
1194
|
+
token: s,
|
|
1195
|
+
user: async () => (await n())?.userInfo,
|
|
1196
|
+
logout: async () => (await n())?.logout(),
|
|
1197
|
+
options: r
|
|
901
1198
|
});
|
|
902
|
-
return
|
|
903
|
-
},
|
|
904
|
-
const
|
|
905
|
-
|
|
906
|
-
const e = async (
|
|
907
|
-
const
|
|
1199
|
+
return d;
|
|
1200
|
+
}, re = () => {
|
|
1201
|
+
const i = C(T);
|
|
1202
|
+
i || console.warn("No auth provided, authorized calls may not work");
|
|
1203
|
+
const e = async (t, r, o = { contentType: "application/json" }) => {
|
|
1204
|
+
const s = o?.skipAuth ?? i?.options.skipAuthentication, n = {
|
|
908
1205
|
accept: "application/json",
|
|
909
|
-
...
|
|
1206
|
+
...r.headers ?? {}
|
|
910
1207
|
};
|
|
911
|
-
|
|
912
|
-
const
|
|
913
|
-
if (
|
|
914
|
-
for (const [
|
|
915
|
-
|
|
916
|
-
const
|
|
917
|
-
...
|
|
918
|
-
headers:
|
|
1208
|
+
o.contentType && (n["Content-Type"] = o.contentType), s || (await i?.updateToken(), n.Authorization = `Bearer ${i?.token()}`);
|
|
1209
|
+
const a = new URL(t, window.location.href);
|
|
1210
|
+
if (o?.queryParams)
|
|
1211
|
+
for (const [l, d] of Object.entries(o.queryParams))
|
|
1212
|
+
a.searchParams.set(l, d);
|
|
1213
|
+
const c = await fetch(a.toString(), {
|
|
1214
|
+
...r,
|
|
1215
|
+
headers: n
|
|
919
1216
|
});
|
|
920
|
-
return
|
|
921
|
-
content:
|
|
922
|
-
status:
|
|
1217
|
+
return c.ok ? c.json() : (o?.skipAuth, Promise.reject({
|
|
1218
|
+
content: c.body,
|
|
1219
|
+
status: c.status
|
|
923
1220
|
}));
|
|
924
1221
|
};
|
|
925
1222
|
return {
|
|
926
|
-
get: (
|
|
927
|
-
postFile: (
|
|
928
|
-
const
|
|
929
|
-
for (const
|
|
930
|
-
|
|
931
|
-
return
|
|
932
|
-
|
|
1223
|
+
get: (t, r) => e(t, { method: "GET" }, r),
|
|
1224
|
+
postFile: (t, r, o = {}, s) => {
|
|
1225
|
+
const n = new FormData();
|
|
1226
|
+
for (const a in o)
|
|
1227
|
+
n.append(a, o[a]);
|
|
1228
|
+
return n.append("file", r), e(
|
|
1229
|
+
t,
|
|
933
1230
|
{
|
|
934
1231
|
method: "POST",
|
|
935
|
-
body:
|
|
1232
|
+
body: n
|
|
936
1233
|
},
|
|
937
|
-
{ ...
|
|
1234
|
+
{ ...s, contentType: void 0 }
|
|
938
1235
|
);
|
|
939
1236
|
},
|
|
940
|
-
post: (
|
|
941
|
-
|
|
1237
|
+
post: (t, r, o) => e(
|
|
1238
|
+
t,
|
|
942
1239
|
{
|
|
943
1240
|
method: "POST",
|
|
944
|
-
body: JSON.stringify(
|
|
1241
|
+
body: JSON.stringify(r)
|
|
945
1242
|
},
|
|
946
|
-
|
|
1243
|
+
o
|
|
947
1244
|
),
|
|
948
|
-
patch: (
|
|
949
|
-
|
|
1245
|
+
patch: (t, r, o) => e(
|
|
1246
|
+
t,
|
|
950
1247
|
{
|
|
951
1248
|
method: "PATCH",
|
|
952
|
-
body: JSON.stringify(
|
|
1249
|
+
body: JSON.stringify(r)
|
|
953
1250
|
},
|
|
954
|
-
|
|
1251
|
+
o
|
|
955
1252
|
),
|
|
956
|
-
delete: (
|
|
957
|
-
|
|
1253
|
+
delete: (t, r, o) => e(
|
|
1254
|
+
t,
|
|
958
1255
|
{
|
|
959
1256
|
method: "DELETE",
|
|
960
|
-
body: JSON.stringify(
|
|
1257
|
+
body: JSON.stringify(r)
|
|
961
1258
|
},
|
|
962
|
-
|
|
1259
|
+
o
|
|
963
1260
|
)
|
|
964
1261
|
};
|
|
965
|
-
},
|
|
966
|
-
const
|
|
967
|
-
return
|
|
968
|
-
isAuthenticated: () => !!
|
|
969
|
-
getUser: () =>
|
|
970
|
-
logout: () =>
|
|
1262
|
+
}, oe = () => {
|
|
1263
|
+
const i = C(T);
|
|
1264
|
+
return i || console.warn("No auth provided, authorized calls may not work"), {
|
|
1265
|
+
isAuthenticated: () => !!i?.user(),
|
|
1266
|
+
getUser: () => i?.user(),
|
|
1267
|
+
logout: () => i?.logout()
|
|
971
1268
|
};
|
|
972
1269
|
};
|
|
973
1270
|
export {
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
1271
|
+
te as createAuth,
|
|
1272
|
+
oe as useAuthenticate,
|
|
1273
|
+
re as useHttpRequest
|
|
977
1274
|
};
|