@qlik/api 1.32.0 → 1.34.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.
Files changed (142) hide show
  1. package/api-keys.d.ts +13 -12
  2. package/api-keys.js +64 -50
  3. package/apps.d.ts +56 -56
  4. package/apps.js +392 -304
  5. package/assistants.d.ts +34 -34
  6. package/assistants.js +257 -201
  7. package/audits.d.ts +10 -10
  8. package/audits.js +48 -36
  9. package/{auth-types-DqfMuSRX.d.ts → auth-types-Cj5bM3Yk.d.ts} +29 -9
  10. package/auth.d.ts +17 -4
  11. package/auth.js +4 -2
  12. package/automation-connections.d.ts +12 -12
  13. package/automation-connections.js +75 -59
  14. package/automations.d.ts +29 -29
  15. package/automations.js +159 -123
  16. package/automl-deployments.d.ts +4 -4
  17. package/automl-deployments.js +14 -12
  18. package/automl-predictions.d.ts +13 -13
  19. package/automl-predictions.js +56 -44
  20. package/brands.d.ts +18 -18
  21. package/brands.js +107 -83
  22. package/chunks/{LY7RP2HA.js → 4V6T7Y4L.js} +26 -8
  23. package/chunks/{RCLKKVYB.js → 6C6WMV7V.js} +9 -2
  24. package/chunks/{VVD2DPKQ.js → 6WNP7HZQ.js} +3 -3
  25. package/chunks/7MMXU6EL.js +86 -0
  26. package/chunks/{6ZONDHRN.js → EEE42MLS.js} +11 -4
  27. package/chunks/{FKDGGR2O.js → I2HA7WJB.js} +1362 -1366
  28. package/chunks/{M64RLKVG.js → M7AINAXZ.js} +7 -5
  29. package/chunks/{LTNGXTXG.js → QAOVZB27.js} +3 -3
  30. package/chunks/{YTT2FEVE.js → QZKOA6VR.js} +1 -1
  31. package/chunks/{UZTIZ4H5.js → VUYZKBT5.js} +74 -74
  32. package/chunks/{3RGGGGAR.js → ZCTVPXGO.js} +1 -1
  33. package/collections.d.ts +16 -15
  34. package/collections.js +98 -76
  35. package/conditions.d.ts +13 -13
  36. package/conditions.js +97 -75
  37. package/consumption.d.ts +4 -4
  38. package/consumption.js +11 -9
  39. package/csp-origins.d.ts +9 -9
  40. package/csp-origins.js +53 -41
  41. package/csrf-token.d.ts +3 -3
  42. package/csrf-token.js +10 -8
  43. package/data-alerts.d.ts +22 -22
  44. package/data-alerts.js +139 -107
  45. package/data-assets.d.ts +8 -8
  46. package/data-assets.js +50 -40
  47. package/data-connections.d.ts +16 -16
  48. package/data-connections.js +87 -69
  49. package/data-credentials.d.ts +11 -11
  50. package/data-credentials.js +52 -42
  51. package/data-files.d.ts +18 -18
  52. package/data-files.js +107 -83
  53. package/data-qualities.d.ts +6 -6
  54. package/data-qualities.js +28 -22
  55. package/data-sets.d.ts +10 -10
  56. package/data-sets.js +59 -47
  57. package/data-sources.d.ts +7 -7
  58. package/data-sources.js +28 -22
  59. package/data-stores.d.ts +16 -16
  60. package/data-stores.js +92 -72
  61. package/dcaas.d.ts +6 -6
  62. package/dcaas.js +28 -22
  63. package/di-projects.d.ts +22 -22
  64. package/di-projects.js +148 -116
  65. package/direct-access-agents.d.ts +328 -0
  66. package/direct-access-agents.js +108 -0
  67. package/encryption.d.ts +12 -12
  68. package/encryption.js +82 -62
  69. package/extensions.d.ts +11 -11
  70. package/extensions.js +61 -47
  71. package/glossaries.d.ts +33 -33
  72. package/glossaries.js +221 -173
  73. package/groups.d.ts +12 -12
  74. package/groups.js +72 -56
  75. package/identity-providers.d.ts +11 -11
  76. package/identity-providers.js +67 -51
  77. package/index.d.ts +9 -4
  78. package/index.js +102 -67
  79. package/interceptors.d.ts +9 -2
  80. package/interceptors.js +2 -2
  81. package/invoke-fetch-types-BYCD4pc9.d.ts +98 -0
  82. package/items.d.ts +14 -13
  83. package/items.js +71 -55
  84. package/knowledgebases.d.ts +23 -23
  85. package/knowledgebases.js +153 -119
  86. package/licenses.d.ts +16 -14
  87. package/licenses.js +76 -58
  88. package/lineage-graphs.d.ts +17 -17
  89. package/lineage-graphs.js +76 -60
  90. package/ml.d.ts +238 -60
  91. package/ml.js +391 -286
  92. package/notes.d.ts +4 -4
  93. package/notes.js +19 -15
  94. package/notifications.d.ts +4 -4
  95. package/notifications.js +11 -9
  96. package/oauth-clients.d.ts +14 -14
  97. package/oauth-clients.js +96 -74
  98. package/oauth-tokens.d.ts +5 -5
  99. package/oauth-tokens.js +19 -15
  100. package/package.json +8 -6
  101. package/qix.d.ts +145 -4
  102. package/qix.js +2 -2
  103. package/questions.d.ts +5 -5
  104. package/questions.js +22 -18
  105. package/quotas.d.ts +6 -6
  106. package/quotas.js +20 -16
  107. package/reload-tasks.d.ts +8 -8
  108. package/reload-tasks.js +46 -36
  109. package/reloads.d.ts +7 -7
  110. package/reloads.js +36 -28
  111. package/report-templates.d.ts +10 -10
  112. package/report-templates.js +64 -50
  113. package/reports.d.ts +4 -4
  114. package/reports.js +20 -16
  115. package/roles.d.ts +8 -8
  116. package/roles.js +46 -36
  117. package/sharing-tasks.d.ts +14 -14
  118. package/sharing-tasks.js +89 -69
  119. package/spaces.d.ts +27 -23
  120. package/spaces.js +153 -119
  121. package/tasks.d.ts +17 -17
  122. package/tasks.js +90 -70
  123. package/temp-contents.d.ts +7 -7
  124. package/temp-contents.js +30 -24
  125. package/tenants.d.ts +8 -8
  126. package/tenants.js +57 -45
  127. package/themes.d.ts +11 -11
  128. package/themes.js +61 -47
  129. package/transports.d.ts +8 -8
  130. package/transports.js +49 -37
  131. package/ui-config.d.ts +9 -9
  132. package/ui-config.js +61 -47
  133. package/users.d.ts +15 -15
  134. package/users.js +81 -63
  135. package/web-integrations.d.ts +8 -8
  136. package/web-integrations.js +46 -36
  137. package/web-notifications.d.ts +9 -9
  138. package/web-notifications.js +53 -41
  139. package/webhooks.d.ts +14 -14
  140. package/webhooks.js +88 -68
  141. package/chunks/2ZQ3ZX7F.js +0 -33
  142. package/invoke-fetch-types-Cq7bjkqn.d.ts +0 -243
@@ -1,49 +1,55 @@
1
1
  import {
2
2
  getInterceptors
3
- } from "./3RGGGGAR.js";
3
+ } from "./ZCTVPXGO.js";
4
4
  import {
5
+ cleanFalsyValues,
5
6
  isBrowser,
6
- isNode
7
- } from "./2ZQ3ZX7F.js";
7
+ isNode,
8
+ sortKeys
9
+ } from "./7MMXU6EL.js";
8
10
 
9
- // src/auth/internal/host-config-registry.ts
10
- var registeredHostConfigs = {};
11
- function registerHostConfigInternal(name, hostConfig) {
12
- if (hostConfig?.reference) {
13
- throw new InvalidHostConfigError("Cannot register a host config with a reference");
14
- }
15
- if (registeredHostConfigs[name]) {
16
- console.warn(`registerHostConfig: Host config with name "${name}" is already registered. Overwriting.`);
17
- }
18
- registeredHostConfigs[name] = hostConfig;
19
- }
20
- function unregisterHostConfigInternal(name) {
21
- if (registeredHostConfigs[name]) {
22
- delete registeredHostConfigs[name];
23
- } else {
24
- console.warn(`unregisterHostConfig: Host config with name "${name}" not found.`);
11
+ // src/invoke-fetch/invoke-fetch-errors.ts
12
+ var InvokeFetchError = class extends Error {
13
+ status;
14
+ headers;
15
+ data;
16
+ constructor(errorMessage, status, headers, data) {
17
+ super(errorMessage);
18
+ this.status = status;
19
+ this.headers = headers;
20
+ this.data = data;
21
+ this.stack = cleanStack(this.stack);
25
22
  }
26
- }
27
- function getRegisteredHostConfigInternal(name) {
28
- if (!registeredHostConfigs[name]) {
29
- throw new Error(`Host config with name "${name}" not found.`);
23
+ };
24
+ var EncodingError = class extends Error {
25
+ contentType;
26
+ data;
27
+ constructor(errorMessage, contentType, data) {
28
+ super(errorMessage);
29
+ this.contentType = contentType;
30
+ this.data = data;
31
+ this.stack = cleanStack(this.stack);
30
32
  }
31
- return registeredHostConfigs[name];
32
- }
33
-
34
- // src/auth/internal/default-host-config.ts
35
- var defaultHostConfig = {};
36
- function setDefaultHostConfigInternal(hostConfig) {
37
- defaultHostConfig = hostConfig || {};
38
- }
39
- function withResolvedHostConfig(hostConfig) {
40
- if (hostConfig?.reference) {
41
- return getRegisteredHostConfigInternal(hostConfig.reference);
33
+ };
34
+ var regex = /^.+\/qmfe-api(?:\.js)?:(\d+)(?::\d+)?$/gim;
35
+ var isFromQmfeApi = (line) => {
36
+ const matches = line.match(regex);
37
+ return Boolean(matches && matches.length > 0);
38
+ };
39
+ function cleanStack(stack) {
40
+ if (!stack) {
41
+ return stack;
42
42
  }
43
- if (hostConfig && Object.keys(hostConfig).length > 0) {
44
- return hostConfig;
43
+ const newStack = [];
44
+ const lines = stack.split("\n");
45
+ lines.reverse();
46
+ for (const line of lines) {
47
+ if (isFromQmfeApi(line)) {
48
+ break;
49
+ }
50
+ newStack.unshift(line);
45
51
  }
46
- return defaultHostConfig;
52
+ return newStack.join("\n");
47
53
  }
48
54
 
49
55
  // src/platform/platform-functions.ts
@@ -151,943 +157,920 @@ var result = (data) => ({
151
157
  ...data
152
158
  });
153
159
 
154
- // src/auth/internal/auth-module-registry.ts
155
- var authModules = {};
156
- var ongoingAuthModuleLoading = Promise.resolve();
157
- function registerAuthModule(name, authModule) {
158
- authModules[name.toLowerCase()] = authModule;
159
- }
160
- function getRegisteredAuthModules() {
161
- return Object.keys(authModules);
162
- }
163
- function getRegisteredAuthModule(authType) {
164
- return authModules[authType.toLowerCase()];
160
+ // src/auth/auth-types.ts
161
+ var hostConfigCommonProperties = [
162
+ "authType",
163
+ "autoRedirect",
164
+ "authRedirectUserConfirmation",
165
+ "embedRuntimeUrl",
166
+ "host",
167
+ "onAuthFailed"
168
+ ];
169
+ var authTypesThatCanBeOmitted = [
170
+ "apikey",
171
+ "oauth2",
172
+ "cookie",
173
+ "windowscookie",
174
+ "reference",
175
+ "anonymous"
176
+ ];
177
+
178
+ // src/utils/random.ts
179
+ import { customAlphabet, nanoid } from "nanoid";
180
+ function generateRandomString(targetLength) {
181
+ return nanoid(targetLength);
165
182
  }
166
- async function getAuthModule(hostConfig) {
167
- const hostConfigToUse = withResolvedHostConfig(hostConfig);
168
- const authType = await determineAuthType(hostConfigToUse);
169
- if (ongoingAuthModuleLoading) {
170
- await ongoingAuthModuleLoading;
171
- }
172
- let authModule = getRegisteredAuthModule(authType);
173
- if (!authModule) {
174
- ongoingAuthModuleLoading = (async () => {
175
- authModule = await resolveGloballyDefinedAuthModule(authType);
176
- if (authModule) {
177
- registerAuthModule(authType, authModule);
178
- }
179
- })();
180
- await ongoingAuthModuleLoading;
181
- }
182
- if (!authModule) {
183
- throw new InvalidAuthTypeError(authType);
184
- }
185
- if (authModule.validateHostConfig) {
186
- authModule.validateHostConfig({ authType, ...hostConfigToUse });
187
- }
188
- return authModule;
183
+ function generateRandomHexString(targetLength) {
184
+ return customAlphabet("1234567890abcdef", targetLength)();
189
185
  }
190
- async function resolveGloballyDefinedAuthModule(authType) {
191
- const globalWindow = globalThis;
192
- const globalVariable = globalWindow[authType];
193
- if (globalVariable) {
194
- let potentialAuthModule;
195
- if (typeof globalVariable === "function") {
196
- potentialAuthModule = await globalVariable();
197
- } else {
198
- potentialAuthModule = globalVariable;
199
- }
200
- if (potentialAuthModule && potentialAuthModule.getRestCallAuthParams && potentialAuthModule.getWebSocketAuthParams && potentialAuthModule.handleAuthenticationError) {
201
- return potentialAuthModule;
186
+
187
+ // src/utils/expose-internal-test-apis.ts
188
+ var internalApisName = "__QLIK_INTERNAL__DO_NOT_USE_OR_YOU_WILL_BE_FIRED";
189
+ function exposeInternalApiOnWindow(name, fn) {
190
+ if (globalThis.location?.origin.startsWith("https://localhost:") || globalThis.location?.origin?.endsWith("qlik-stage.com")) {
191
+ if (globalThis[internalApisName] === void 0) {
192
+ globalThis[internalApisName] = {};
202
193
  }
203
- console.error("Not a valid auth module", potentialAuthModule);
204
- throw new InvalidAuthTypeError(authType);
194
+ globalThis[internalApisName][name] = fn;
205
195
  }
206
- return Promise.resolve(void 0);
207
196
  }
208
197
 
209
- // src/auth/auth-errors.ts
210
- var InvalidHostConfigError = class extends Error {
211
- constructor(message) {
212
- super(`Invalid host config: ${message}`);
213
- this.name = "InvalidHostConfigError";
214
- }
215
- };
216
- var UnexpectedAuthTypeError = class extends Error {
217
- constructor(...expectedAuthTypes) {
218
- const ors = expectedAuthTypes.map((item, index) => index === 0 ? `"${item}"` : `or "${item}"`).join(" ");
219
- super(`HostConfig is not properly configured. authType is expected to be ${ors}`);
220
- this.name = "UnexpectedAuthTypeError";
221
- }
222
- };
223
- var InvalidAuthTypeError = class extends Error {
224
- constructor(authType) {
225
- const validAuthModules = getRegisteredAuthModules();
226
- super(
227
- `Not a valid auth type: ${authType}, valid auth types are; '${validAuthModules.filter((name) => name.toLowerCase() !== "qmfeembedframerauthmodule").join("', '")}'`
228
- );
229
- this.name = "InvalidAuthTypeError";
198
+ // src/auth/internal/default-auth-modules/oauth/storage-helpers.ts
199
+ var storagePrefix = "qlik-qmfe-api";
200
+ function getTopicFromOauthHostConfig(hostConfig) {
201
+ let topic = hostConfig.clientId + (hostConfig.scope ? `_${hostConfig.scope}` : "_user_default");
202
+ if (hostConfig.subject) {
203
+ topic += `_${hostConfig.subject}`;
230
204
  }
231
- };
232
- function errorToString({ title, detail, code, status }) {
233
- if (detail) {
234
- return `${title} - ${detail} (Status: ${status}, Code: ${code})`;
205
+ if (hostConfig.userId) {
206
+ topic += `_${hostConfig.userId}`;
235
207
  }
236
- return `${title} (Status: ${status}, Code: ${code})`;
208
+ return topic;
237
209
  }
238
- var AuthorizationError = class extends Error {
239
- errors;
240
- constructor(errors) {
241
- if (typeof errors !== "object") {
242
- super("Unknown error");
243
- return;
244
- }
245
- const errorArray = Array.isArray(errors) ? errors : [errors];
246
- super(errorArray.map(errorToString).join(", "));
247
- this.errors = errorArray;
248
- }
249
- };
250
-
251
- // src/auth/auth-functions.ts
252
- var lastErrorMessage = "";
253
- function logToConsole({ message }) {
254
- if (message !== lastErrorMessage) {
255
- lastErrorMessage = message;
256
- console.error(message);
257
- }
210
+ function getTopicFromAnonHostConfig(hostConfig) {
211
+ return `${hostConfig.accessCode}_${hostConfig.clientId}`;
258
212
  }
259
- function isHostCrossOrigin(hostConfig) {
260
- if (!globalThis.location?.origin) {
261
- return true;
262
- }
263
- const hostConfigToUse = withResolvedHostConfig(hostConfig);
264
- if (Object.keys(hostConfigToUse).length === 0) {
265
- return false;
266
- }
267
- try {
268
- const locationUrl = new URL(toValidLocationUrl(hostConfigToUse));
269
- return locationUrl.origin !== globalThis.location.origin;
270
- } catch {
213
+ var cachedTokens = {};
214
+ function clearAllCachedTokens() {
215
+ for (const key in cachedTokens) {
216
+ delete cachedTokens[key];
271
217
  }
272
- return false;
273
218
  }
274
- async function isWindows(hostConfig) {
275
- const hostConfigToUse = withResolvedHostConfig(hostConfig);
276
- if (typeof hostConfigToUse.forceIsWindows === "boolean") {
277
- return hostConfigToUse.forceIsWindows;
219
+ exposeInternalApiOnWindow("clearAllAccessTokens", () => {
220
+ console.log("Clearing tokens", cachedTokens);
221
+ Object.keys(cachedTokens).forEach((key) => {
222
+ console.log("Clearing access tokens for", key);
223
+ deleteFromLocalStorage(key, ["access-token", "refresh-token"]);
224
+ deleteFromSessionStorage(key, ["access-token", "refresh-token"]);
225
+ });
226
+ clearAllCachedTokens();
227
+ });
228
+ function saveInLocalStorage(topic, name, value) {
229
+ localStorage.setItem(`${storagePrefix}-${topic}-${name}`, value);
230
+ }
231
+ function saveInSessionStorage(topic, name, value) {
232
+ sessionStorage.setItem(`${storagePrefix}-${topic}-${name}`, value);
233
+ }
234
+ function loadFromLocalStorage(topic, name) {
235
+ return localStorage.getItem(`${storagePrefix}-${topic}-${name}`) || void 0;
236
+ }
237
+ function loadFromSessionStorage(topic, name) {
238
+ return sessionStorage.getItem(`${storagePrefix}-${topic}-${name}`) || void 0;
239
+ }
240
+ function deleteFromLocalStorage(topic, names) {
241
+ names.forEach((name) => localStorage.removeItem(`${storagePrefix}-${topic}-${name}`));
242
+ }
243
+ function deleteFromSessionStorage(topic, names) {
244
+ names.forEach((name) => sessionStorage.removeItem(`${storagePrefix}-${topic}-${name}`));
245
+ }
246
+ function loadAndDeleteFromSessionStorage(topic, name) {
247
+ const id = `${storagePrefix}-${topic}-${name}`;
248
+ const result2 = sessionStorage.getItem(id) || void 0;
249
+ sessionStorage.removeItem(id);
250
+ return result2;
251
+ }
252
+ function loadOauthTokensFromStorage(topic, accessTokenStorage) {
253
+ let accessToken;
254
+ let refreshToken;
255
+ if (accessTokenStorage === "local") {
256
+ accessToken = loadFromLocalStorage(topic, "access-token");
257
+ refreshToken = loadFromLocalStorage(topic, "refresh-token");
258
+ } else if (accessTokenStorage === "session") {
259
+ accessToken = loadFromSessionStorage(topic, "access-token");
260
+ refreshToken = loadFromSessionStorage(topic, "refresh-token");
278
261
  }
279
- if (hostConfigToUse.authType === "cookie") {
280
- return false;
262
+ if (accessToken) {
263
+ return {
264
+ accessToken,
265
+ refreshToken
266
+ };
281
267
  }
282
- if (hostConfigToUse.authType === "windowscookie") {
283
- return true;
268
+ return void 0;
269
+ }
270
+ async function loadCachedOauthTokens(hostConfig) {
271
+ return cachedTokens[getTopicFromOauthHostConfig(hostConfig)];
272
+ }
273
+ async function loadOrAcquireAccessTokenOauth(hostConfig, acquireTokens) {
274
+ if (!hostConfig.clientId) {
275
+ throw new InvalidHostConfigError('A host config with authType set to "oauth2" has to also provide a clientId');
284
276
  }
285
- return (await getPlatform({ hostConfig })).isWindows;
277
+ const topic = getTopicFromOauthHostConfig(hostConfig);
278
+ return loadOrAcquireAccessToken(topic, acquireTokens, hostConfig.noCache, hostConfig.accessTokenStorage);
286
279
  }
287
- function toValidLocationUrl(hostConfig) {
288
- const url = withResolvedHostConfig(hostConfig)?.host;
289
- let locationUrl;
290
- if (!url) {
291
- locationUrl = "";
292
- } else if (url.toLowerCase().startsWith("https://") || url.toLowerCase().startsWith("http://")) {
293
- locationUrl = url;
294
- } else {
295
- locationUrl = `https://${url}`;
296
- }
297
- while (locationUrl[locationUrl.length - 1] === "/") {
298
- locationUrl = locationUrl.substring(0, locationUrl.length - 1);
280
+ async function loadOrAcquireAccessTokenAnon(hostConfig, acquireTokens) {
281
+ if (!hostConfig.accessCode) {
282
+ throw new InvalidHostConfigError(
283
+ 'A host config with authType set to "anonymous" has to also provide an accessCode'
284
+ );
299
285
  }
300
- return locationUrl;
286
+ const topic = getTopicFromAnonHostConfig(hostConfig);
287
+ return loadOrAcquireAccessToken(topic, acquireTokens, false, void 0);
301
288
  }
302
- function toValidWebsocketLocationUrl(hostConfig) {
303
- const url = withResolvedHostConfig(hostConfig)?.host;
304
- let locationUrl;
305
- if (!url) {
306
- locationUrl = globalThis.location.origin;
307
- } else if (url.toLowerCase().startsWith("https://") || url.toLowerCase().startsWith("http://")) {
308
- locationUrl = url;
309
- } else {
310
- locationUrl = `https://${url}`;
311
- }
312
- while (locationUrl[locationUrl.length - 1] === "/") {
313
- locationUrl = locationUrl.substring(0, locationUrl.length - 1);
289
+ async function loadOrAcquireAccessToken(topic, acquireTokens, noCache, accessTokenStorage) {
290
+ if (noCache) {
291
+ return acquireTokens();
314
292
  }
315
- return locationUrl.replace(leadingHttp, "ws");
316
- }
317
- async function getWebSocketAuthParams(props) {
318
- const hostConfigToUse = withResolvedHostConfig(props.hostConfig);
319
- try {
320
- const authModule = await getAuthModule(hostConfigToUse);
321
- return await authModule.getWebSocketAuthParams({
322
- ...props,
323
- hostConfig: hostConfigToUse
324
- });
325
- } catch (err) {
326
- (hostConfigToUse.onAuthFailed || logToConsole)(normalizeAuthModuleError(err));
327
- throw err;
293
+ const mayUseStorage = isBrowser();
294
+ const storedOauthTokens = cachedTokens[topic] || (mayUseStorage ? loadOauthTokensFromStorage(topic, accessTokenStorage) : void 0);
295
+ if (storedOauthTokens) {
296
+ cachedTokens[topic] = storedOauthTokens;
297
+ return Promise.resolve(storedOauthTokens);
328
298
  }
329
- }
330
- async function getWebResourceAuthParams(props) {
331
- const hostConfigToUse = withResolvedHostConfig(props.hostConfig);
332
- try {
333
- const authModule = await getAuthModule(hostConfigToUse);
334
- return await authModule.getWebResourceAuthParams?.({
335
- ...props,
336
- hostConfig: hostConfigToUse
337
- }) || { queryParams: {} };
338
- } catch (err) {
339
- (hostConfigToUse.onAuthFailed || logToConsole)(normalizeAuthModuleError(err));
340
- throw err;
299
+ const tokensPromise = acquireTokens();
300
+ cachedTokens[topic] = tokensPromise;
301
+ if (mayUseStorage) {
302
+ const tokens = await tokensPromise;
303
+ if (accessTokenStorage === "local" && tokens) {
304
+ if (tokens.accessToken) {
305
+ saveInLocalStorage(topic, "access-token", tokens.accessToken);
306
+ }
307
+ if (tokens.refreshToken) {
308
+ saveInLocalStorage(topic, "refresh-token", tokens.refreshToken);
309
+ }
310
+ } else if (accessTokenStorage === "session" && tokens) {
311
+ if (tokens.accessToken) {
312
+ saveInSessionStorage(topic, "access-token", tokens.accessToken);
313
+ }
314
+ if (tokens.refreshToken) {
315
+ saveInSessionStorage(topic, "refresh-token", tokens.refreshToken);
316
+ }
317
+ }
341
318
  }
319
+ return tokensPromise;
342
320
  }
343
- async function handleAuthenticationError(props) {
344
- const hostConfigToUse = withResolvedHostConfig(props.hostConfig);
345
- const authModule = await getAuthModule(hostConfigToUse);
346
- const result2 = await authModule.handleAuthenticationError({
347
- ...props,
348
- hostConfig: hostConfigToUse
349
- });
350
- const willRetry = props.canRetry && result2.retry;
351
- const willHangUntilANewPageIsLoaded = result2.preventDefault;
352
- if (!willRetry && !willHangUntilANewPageIsLoaded) {
353
- const { status, errorBody } = props;
354
- (hostConfigToUse.onAuthFailed || logToConsole)(normalizeInbandAuthError({ status, errorBody }));
321
+ function clearStoredOauthTokens(hostConfig) {
322
+ const topic = getTopicFromOauthHostConfig(hostConfig);
323
+ delete cachedTokens[topic];
324
+ if (isBrowser()) {
325
+ deleteFromLocalStorage(topic, ["access-token", "refresh-token"]);
326
+ deleteFromSessionStorage(topic, ["access-token", "refresh-token"]);
355
327
  }
356
- return result2;
357
328
  }
358
- async function getRestCallAuthParams(props) {
359
- const hostConfigToUse = withResolvedHostConfig(props.hostConfig);
360
- try {
361
- const authModule = await getAuthModule(hostConfigToUse);
362
- return await authModule.getRestCallAuthParams({
363
- ...props,
364
- hostConfig: hostConfigToUse
365
- });
366
- } catch (err) {
367
- (hostConfigToUse.onAuthFailed || logToConsole)(normalizeAuthModuleError(err));
368
- throw err;
329
+ function clearStoredAnonymousTokens(hostConfig) {
330
+ const topic = getTopicFromAnonHostConfig(hostConfig);
331
+ delete cachedTokens[topic];
332
+ if (isBrowser()) {
333
+ deleteFromLocalStorage(topic, ["access-token", "refresh-token"]);
334
+ deleteFromSessionStorage(topic, ["access-token", "refresh-token"]);
369
335
  }
370
336
  }
371
- async function getAccessToken(props) {
372
- const res = await getRestCallAuthParams({ method: "GET", ...props });
373
- const authorizationHeader = res.headers?.Authorization;
374
- if (authorizationHeader.indexOf("Bearer ") === 0) {
375
- return authorizationHeader.substring(7);
337
+
338
+ // src/auth/internal/default-auth-modules/oauth/oauth-utils.ts
339
+ function toPerformInteractiveLoginFunction(performInteractiveLogin) {
340
+ if (typeof performInteractiveLogin === "string") {
341
+ const fn = lookupInteractiveLoginFn(performInteractiveLogin);
342
+ if (!fn) {
343
+ throw new Error(`No such function: ${performInteractiveLogin}`);
344
+ }
345
+ return fn;
376
346
  }
377
- throw new Error("Unknown format of authorization header returned by remote auth module");
378
- }
379
- function registerAuthModule2(name, authModule) {
380
- registerAuthModule(name, authModule);
381
- }
382
- function setDefaultHostConfig(hostConfig) {
383
- setDefaultHostConfigInternal(hostConfig);
384
- }
385
- function registerHostConfig(name, hostConfig) {
386
- registerHostConfigInternal(name, hostConfig);
347
+ return performInteractiveLogin;
387
348
  }
388
- function unregisterHostConfig(name) {
389
- unregisterHostConfigInternal(name);
349
+ function lookupGetAccessFn(getAccessToken) {
350
+ return globalThis[getAccessToken];
390
351
  }
391
- function serializeHostConfig(hostConfig) {
392
- const hostConfigToUse = withResolvedHostConfig(hostConfig);
393
- return JSON.stringify(hostConfigToUse, hostConfigPropertyIgnorer);
352
+ function lookupInteractiveLoginFn(name) {
353
+ return globalThis[name];
394
354
  }
395
- async function determineAuthType(hostConfig) {
396
- if (hostConfig.authType) {
397
- return hostConfig.authType;
398
- }
399
- if (hostConfig.apiKey) {
400
- return "apikey";
401
- }
402
- if (hostConfig.accessCode) {
403
- return "anonymous";
404
- }
405
- if (hostConfig.clientId) {
406
- return "oauth2";
407
- }
408
- if (hostConfig.webIntegrationId) {
409
- return "cookie";
410
- }
411
- if (hostConfig.reference) {
412
- return "reference";
413
- }
414
- if (await isWindows(hostConfig)) {
415
- return "windowscookie";
355
+ function handlePossibleErrors(data) {
356
+ if (data.errors) {
357
+ throw new AuthorizationError(data.errors);
416
358
  }
417
- return "cookie";
418
359
  }
419
- function checkForCrossDomainRequest(hostConfig) {
420
- const hostConfigToUse = withResolvedHostConfig(hostConfig);
421
- if (isHostCrossOrigin(hostConfigToUse)) {
422
- if (Object.keys(hostConfigToUse).length === 0) {
423
- throw new InvalidHostConfigError("a host config must be provided when making a cross domain request");
424
- }
425
- if (!hostConfigToUse.host) {
426
- throw new InvalidHostConfigError("A 'host' must be set in host config when making a cross domain request");
427
- }
428
- }
360
+ function toQueryString(queryParams) {
361
+ const queryParamsKeys = Object.keys(queryParams);
362
+ queryParamsKeys.sort();
363
+ const query = queryParamsKeys.map((k) => `${k}=${queryParams[k]}`).join("&");
364
+ return query;
429
365
  }
430
- var logout = () => {
431
- globalThis.loggingOut = true;
432
- globalThis.location.href = "/logout";
433
- };
434
- var leadingHttp = /^http/;
435
- function normalizeInbandAuthError({ errorBody, status }) {
436
- const authError = errorBody;
437
- if (typeof authError?.errors === "object") {
438
- const err = new AuthorizationError(authError?.errors);
439
- return { message: err.message };
366
+ function byteArrayToBase64(hashArray) {
367
+ let result2 = "";
368
+ if (isBrowser()) {
369
+ const byteArrayToString = String.fromCharCode.apply(null, hashArray);
370
+ result2 = btoa(byteArrayToString);
371
+ } else if (isNode()) {
372
+ result2 = Buffer.from(hashArray).toString("base64");
373
+ } else {
374
+ throw new Error("Environment not supported for oauth2 authentication");
440
375
  }
441
- return { message: `HTTP ${status}` };
376
+ return result2;
442
377
  }
443
- function normalizeAuthModuleError(err) {
444
- return { message: err.message || "Unknown error" };
378
+ async function sha256(message) {
379
+ const msgBuffer = new TextEncoder().encode(message);
380
+ const hashBuffer = await globalThis.crypto.subtle.digest("SHA-256", msgBuffer);
381
+ const hashArray = Array.from(new Uint8Array(hashBuffer));
382
+ const hashBase64 = byteArrayToBase64(hashArray);
383
+ return hashBase64.replaceAll(/\+/g, "-").replaceAll(/\//g, "_").replace(/=+$/, "");
445
384
  }
446
- function hostConfigPropertyIgnorer(key, value) {
447
- if (key === "") {
448
- return value;
449
- }
450
- if (key === "authType") {
451
- return void 0;
452
- }
453
- const vtype = typeof value;
454
- if (vtype === "object" || vtype === "function") {
455
- return void 0;
456
- }
457
- return value;
385
+ async function createInteractiveLoginUrl(hostConfig, redirectUri, state, verifier) {
386
+ const clientId = hostConfig.clientId || "";
387
+ const locationUrl = toValidLocationUrl(hostConfig);
388
+ const codeChallenge = await sha256(verifier);
389
+ const queryParams = {
390
+ response_type: "code",
391
+ client_id: clientId,
392
+ redirect_uri: redirectUri,
393
+ scope: hostConfig.scope || "user_default",
394
+ state,
395
+ code_challenge: codeChallenge,
396
+ code_challenge_method: "S256"
397
+ };
398
+ return `${locationUrl}/oauth/authorize?${toQueryString(queryParams)}`;
458
399
  }
459
-
460
- // src/random/random.ts
461
- import { customAlphabet, nanoid } from "nanoid";
462
- function generateRandomString(targetLength) {
463
- return nanoid(targetLength);
400
+ async function startFullPageLoginFlow(hostConfig) {
401
+ const clientId = hostConfig.clientId || "";
402
+ const locationUrl = toValidLocationUrl(hostConfig);
403
+ const verifier = generateRandomString(128);
404
+ const state = generateRandomString(43);
405
+ const codeChallenge = await sha256(verifier);
406
+ const redirectUri = hostConfig.redirectUri || globalThis.location.href;
407
+ const topic = getTopicFromOauthHostConfig(hostConfig);
408
+ clearStoredOauthTokens(hostConfig);
409
+ saveInSessionStorage(topic, "state", state);
410
+ saveInSessionStorage(topic, "verifier", verifier);
411
+ saveInSessionStorage(topic, "href", globalThis.location.href);
412
+ saveInSessionStorage("", "client-in-progress", topic);
413
+ const queryParams = {
414
+ response_type: "code",
415
+ client_id: clientId,
416
+ redirect_uri: redirectUri,
417
+ scope: hostConfig.scope || "user_default",
418
+ state,
419
+ code_challenge: codeChallenge,
420
+ code_challenge_method: "S256"
421
+ };
422
+ const url = `${locationUrl}/oauth/authorize?${toQueryString(queryParams)}`;
423
+ globalThis.location.replace(url);
464
424
  }
465
- function generateRandomHexString(targetLength) {
466
- return customAlphabet("1234567890abcdef", targetLength)();
467
- }
468
-
469
- // src/auth/internal/auth-functions.ts
470
- function getCredentialsForCookieAuth(hostConfig) {
471
- if (hostConfig.crossSiteCookies === false) {
472
- return "same-origin";
473
- }
474
- if (isHostCrossOrigin(hostConfig)) {
475
- return "include";
425
+ async function exchangeCodeAndVerifierForAccessTokenData(hostConfig, code, verifier, redirectUri) {
426
+ try {
427
+ const result2 = await fetch(`${toValidLocationUrl(hostConfig)}/oauth/token`, {
428
+ method: "POST",
429
+ credentials: "include",
430
+ mode: "cors",
431
+ headers: { "content-type": "application/json" },
432
+ redirect: "follow",
433
+ body: JSON.stringify({
434
+ grant_type: "authorization_code",
435
+ scope: hostConfig.scope || "user_default",
436
+ ...code ? { code } : {},
437
+ ...{ redirect_uri: redirectUri || globalThis.location.href },
438
+ ...verifier ? { code_verifier: verifier } : {},
439
+ client_id: hostConfig.clientId
440
+ })
441
+ });
442
+ const data = await result2.json();
443
+ handlePossibleErrors(data);
444
+ return {
445
+ accessToken: data.access_token,
446
+ refreshToken: data.refresh_token,
447
+ errors: data.errors
448
+ };
449
+ } catch (err) {
450
+ console.error(err);
451
+ return new Promise(() => {
452
+ });
476
453
  }
477
- return "same-origin";
478
454
  }
479
- function internalValidateHostConfig(hostConfig, options) {
480
- const missingRequiredProps = [];
481
- for (const requiredProp of options.requiredProps) {
482
- if (!hostConfig[requiredProp]) {
483
- missingRequiredProps.push(requiredProp);
484
- }
485
- }
486
- if (missingRequiredProps.length > 0) {
487
- throw new InvalidHostConfigError(
488
- `missing required properties in host config; '${missingRequiredProps.join("', '")}'`
489
- );
455
+ function createBodyWithCredentialsEtc(clientId, clientSecret, scope, subject, userId) {
456
+ const commonProps = {
457
+ client_id: clientId,
458
+ client_secret: clientSecret,
459
+ scope
460
+ };
461
+ if (subject) {
462
+ return {
463
+ ...commonProps,
464
+ grant_type: "urn:qlik:oauth:user-impersonation",
465
+ user_lookup: {
466
+ field: "subject",
467
+ value: subject
468
+ }
469
+ };
490
470
  }
491
- const validProps = [
492
- "authType",
493
- "autoRedirect",
494
- "authRedirectUserConfirmation",
495
- "embedRuntimeUrl",
496
- "host",
497
- "onAuthFailed",
498
- ...options.requiredProps,
499
- ...options.optionalProps
500
- ];
501
- const invalidKeys = [];
502
- Object.keys(hostConfig).forEach((key) => {
503
- if (!validProps.some((k) => k === key)) {
504
- invalidKeys.push(key);
505
- }
506
- });
507
- if (invalidKeys.length > 0) {
508
- throw new InvalidHostConfigError(`unknown properties in host config; '${invalidKeys.join("', '")}'`);
471
+ if (userId) {
472
+ return {
473
+ ...commonProps,
474
+ grant_type: "urn:qlik:oauth:user-impersonation",
475
+ user_lookup: {
476
+ field: "userId",
477
+ value: userId
478
+ }
479
+ };
509
480
  }
510
- return true;
481
+ return {
482
+ ...commonProps,
483
+ grant_type: "client_credentials"
484
+ };
511
485
  }
512
-
513
- // src/utils/expose-internal-test-apis.ts
514
- var internalApisName = "__QLIK_INTERNAL__DO_NOT_USE_OR_YOU_WILL_BE_FIRED";
515
- function exposeInternalApiOnWindow(name, fn) {
516
- if (globalThis.location?.origin.startsWith("https://localhost:") || globalThis.location?.origin?.endsWith("qlik-stage.com")) {
517
- if (globalThis[internalApisName] === void 0) {
518
- globalThis[internalApisName] = {};
519
- }
520
- globalThis[internalApisName][name] = fn;
521
- }
486
+ async function getOauthTokensWithCredentials(baseUrl, clientId, clientSecret, scope = "user_default", subject, userId) {
487
+ const result2 = await fetch(`${baseUrl}/oauth/token`, {
488
+ method: "POST",
489
+ mode: "cors",
490
+ headers: { "content-type": "application/json" },
491
+ body: JSON.stringify(createBodyWithCredentialsEtc(clientId, clientSecret, scope, subject, userId))
492
+ });
493
+ const data = await result2.json();
494
+ return {
495
+ accessToken: data.access_token,
496
+ refreshToken: data.refresh_token,
497
+ errors: data.errors
498
+ };
522
499
  }
523
-
524
- // src/auth/internal/default-auth-modules/oauth/storage-helpers.ts
525
- var storagePrefix = "qlik-qmfe-api";
526
- function getTopicFromOauthHostConfig(hostConfig) {
527
- let topic = hostConfig.clientId + (hostConfig.scope ? `_${hostConfig.scope}` : "_user_default");
528
- if (hostConfig.subject) {
529
- topic += `_${hostConfig.subject}`;
530
- }
531
- if (hostConfig.userId) {
532
- topic += `_${hostConfig.userId}`;
533
- }
534
- return topic;
500
+ async function getOauthTokensWithRefreshToken(baseUrl, refreshToken, clientSecret) {
501
+ const result2 = await fetch(`${baseUrl}/oauth/token`, {
502
+ method: "POST",
503
+ mode: "cors",
504
+ headers: { "content-type": "application/json" },
505
+ body: JSON.stringify({
506
+ grant_type: "refresh_token",
507
+ refresh_token: refreshToken,
508
+ client_secret: clientSecret
509
+ })
510
+ });
511
+ const data = await result2.json();
512
+ return {
513
+ accessToken: data.access_token,
514
+ refreshToken: data.refresh_token,
515
+ errors: data.errors
516
+ };
535
517
  }
536
- function getTopicFromAnonHostConfig(hostConfig) {
537
- return `${hostConfig.accessCode}_${hostConfig.clientId}`;
518
+ async function getAnonymousOauthAccessToken(baseUrl, accessCode, clientId, trackingCode) {
519
+ const result2 = await fetch(`${baseUrl}/oauth/token/anonymous-embed`, {
520
+ method: "POST",
521
+ mode: "cors",
522
+ headers: { "content-type": "application/json" },
523
+ body: JSON.stringify({
524
+ eac: accessCode,
525
+ client_id: clientId,
526
+ grant_type: "urn:qlik:oauth:anonymous-embed",
527
+ tracking_code: trackingCode
528
+ })
529
+ });
530
+ const data = await result2.json();
531
+ return {
532
+ accessToken: data.access_token,
533
+ refreshToken: data.refresh_token,
534
+ errors: data.errors
535
+ };
538
536
  }
539
- var cachedTokens = {};
540
- function clearAllCachedTokens() {
541
- for (const key in cachedTokens) {
542
- delete cachedTokens[key];
537
+ async function getOAuthTokensForNode(hostConfig) {
538
+ const { clientId, clientSecret } = hostConfig;
539
+ if (!clientId || !clientSecret) {
540
+ throw new InvalidHostConfigError(
541
+ 'A host config with authType set to "oauth2" has to provide a clientId and a clientSecret'
542
+ );
543
543
  }
544
- }
545
- exposeInternalApiOnWindow("clearAllAccessTokens", () => {
546
- console.log("Clearing tokens", cachedTokens);
547
- Object.keys(cachedTokens).forEach((key) => {
548
- console.log("Clearing access tokens for", key);
549
- deleteFromLocalStorage(key, ["access-token", "refresh-token"]);
550
- deleteFromSessionStorage(key, ["access-token", "refresh-token"]);
544
+ const oauthTokens = await loadOrAcquireAccessTokenOauth(hostConfig, async () => {
545
+ if (!hostConfig.clientId || !hostConfig.clientSecret) {
546
+ throw new InvalidHostConfigError(
547
+ 'A host config with authType set to "oauth2" has to provide a clientId and a clientSecret'
548
+ );
549
+ }
550
+ return getOauthTokensWithCredentials(
551
+ toValidLocationUrl(hostConfig),
552
+ hostConfig.clientId,
553
+ hostConfig.clientSecret,
554
+ hostConfig.scope,
555
+ hostConfig.subject,
556
+ hostConfig.userId
557
+ );
551
558
  });
552
- clearAllCachedTokens();
553
- });
554
- function saveInLocalStorage(topic, name, value) {
555
- localStorage.setItem(`${storagePrefix}-${topic}-${name}`, value);
556
- }
557
- function saveInSessionStorage(topic, name, value) {
558
- sessionStorage.setItem(`${storagePrefix}-${topic}-${name}`, value);
559
- }
560
- function loadFromLocalStorage(topic, name) {
561
- return localStorage.getItem(`${storagePrefix}-${topic}-${name}`) || void 0;
562
- }
563
- function loadFromSessionStorage(topic, name) {
564
- return sessionStorage.getItem(`${storagePrefix}-${topic}-${name}`) || void 0;
565
- }
566
- function deleteFromLocalStorage(topic, names) {
567
- names.forEach((name) => localStorage.removeItem(`${storagePrefix}-${topic}-${name}`));
568
- }
569
- function deleteFromSessionStorage(topic, names) {
570
- names.forEach((name) => sessionStorage.removeItem(`${storagePrefix}-${topic}-${name}`));
571
- }
572
- function loadAndDeleteFromSessionStorage(topic, name) {
573
- const id = `${storagePrefix}-${topic}-${name}`;
574
- const result2 = sessionStorage.getItem(id) || void 0;
575
- sessionStorage.removeItem(id);
576
- return result2;
559
+ return oauthTokens;
577
560
  }
578
- function loadOauthTokensFromStorage(topic, accessTokenStorage) {
579
- let accessToken;
580
- let refreshToken;
581
- if (accessTokenStorage === "local") {
582
- accessToken = loadFromLocalStorage(topic, "access-token");
583
- refreshToken = loadFromLocalStorage(topic, "refresh-token");
584
- } else if (accessTokenStorage === "session") {
585
- accessToken = loadFromSessionStorage(topic, "access-token");
586
- refreshToken = loadFromSessionStorage(topic, "refresh-token");
561
+ async function getOAuthTokensForBrowser(hostConfig) {
562
+ const { clientId } = hostConfig;
563
+ if (!clientId) {
564
+ throw new InvalidHostConfigError('A host config with authType set to "oauth2" has to also provide a clientId');
587
565
  }
588
- if (accessToken) {
589
- return {
590
- accessToken,
591
- refreshToken
592
- };
566
+ const oauthTokens = await loadOrAcquireAccessTokenOauth(hostConfig, async () => {
567
+ if (hostConfig.getAccessToken) {
568
+ try {
569
+ const tokenFetchedFromRemote = typeof hostConfig.getAccessToken === "string" ? await lookupGetAccessFn(hostConfig.getAccessToken)() : await hostConfig.getAccessToken();
570
+ return {
571
+ accessToken: tokenFetchedFromRemote,
572
+ refreshToken: void 0,
573
+ errors: void 0
574
+ };
575
+ } catch {
576
+ return errorMessageToAuthData("Could not fetch access token using custom function");
577
+ }
578
+ }
579
+ if (hostConfig.performInteractiveLogin) {
580
+ let usedRedirectUri;
581
+ try {
582
+ const verifier2 = generateRandomString(128);
583
+ const originalState = generateRandomString(43);
584
+ const { code: code2, state } = extractCodeAndState(
585
+ await toPerformInteractiveLoginFunction(hostConfig.performInteractiveLogin)({
586
+ getLoginUrl: async ({ redirectUri }) => {
587
+ usedRedirectUri = redirectUri;
588
+ return createInteractiveLoginUrl(hostConfig, redirectUri, originalState, verifier2);
589
+ }
590
+ })
591
+ );
592
+ if (!usedRedirectUri) {
593
+ return errorMessageToAuthData("No redirect uri provided");
594
+ }
595
+ if (originalState !== state) {
596
+ return errorMessageToAuthData("State returned by custom interactive login function does not match original");
597
+ }
598
+ if (!code2) {
599
+ return errorMessageToAuthData("No code found in response from custom interactive login function");
600
+ }
601
+ const tokenResponse = await exchangeCodeAndVerifierForAccessTokenData(
602
+ hostConfig,
603
+ code2,
604
+ verifier2,
605
+ usedRedirectUri
606
+ );
607
+ return tokenResponse;
608
+ } catch (error) {
609
+ return {
610
+ accessToken: void 0,
611
+ refreshToken: void 0,
612
+ errors: [
613
+ {
614
+ code: "",
615
+ status: 401,
616
+ title: "Could not perform custom interactive login",
617
+ detail: `${error}`
618
+ }
619
+ ]
620
+ };
621
+ }
622
+ }
623
+ const topic = getTopicFromOauthHostConfig(hostConfig);
624
+ const code = loadAndDeleteFromSessionStorage(topic, "code");
625
+ const verifier = loadAndDeleteFromSessionStorage(topic, "verifier");
626
+ if (code && verifier) {
627
+ const tokenResponse = await exchangeCodeAndVerifierForAccessTokenData(
628
+ hostConfig,
629
+ code,
630
+ verifier,
631
+ hostConfig.redirectUri
632
+ );
633
+ if (tokenResponse) {
634
+ return tokenResponse;
635
+ }
636
+ }
637
+ return void 0;
638
+ });
639
+ if (oauthTokens) {
640
+ return oauthTokens;
593
641
  }
594
- return void 0;
595
- }
596
- async function loadCachedOauthTokens(hostConfig) {
597
- return cachedTokens[getTopicFromOauthHostConfig(hostConfig)];
598
- }
599
- async function loadOrAcquireAccessTokenOauth(hostConfig, acquireTokens) {
600
- if (!hostConfig.clientId) {
601
- throw new InvalidHostConfigError('A host config with authType set to "oauth2" has to also provide a clientId');
642
+ if (hostConfig.performInteractiveLogin) {
643
+ return new Promise(() => {
644
+ });
602
645
  }
603
- const topic = getTopicFromOauthHostConfig(hostConfig);
604
- return loadOrAcquireAccessToken(topic, acquireTokens, hostConfig.noCache, hostConfig.accessTokenStorage);
605
- }
606
- async function loadOrAcquireAccessTokenAnon(hostConfig, acquireTokens) {
607
- if (!hostConfig.accessCode) {
608
- throw new InvalidHostConfigError(
609
- 'A host config with authType set to "anonymous" has to also provide an accessCode'
610
- );
646
+ if (hostConfig.authRedirectUserConfirmation) {
647
+ await hostConfig.authRedirectUserConfirmation();
611
648
  }
612
- const topic = getTopicFromAnonHostConfig(hostConfig);
613
- return loadOrAcquireAccessToken(topic, acquireTokens, false, void 0);
649
+ startFullPageLoginFlow(hostConfig);
650
+ return new Promise(() => {
651
+ });
614
652
  }
615
- async function loadOrAcquireAccessToken(topic, acquireTokens, noCache, accessTokenStorage) {
616
- if (noCache) {
617
- return acquireTokens();
618
- }
619
- const mayUseStorage = isBrowser();
620
- const storedOauthTokens = cachedTokens[topic] || (mayUseStorage ? loadOauthTokensFromStorage(topic, accessTokenStorage) : void 0);
621
- if (storedOauthTokens) {
622
- cachedTokens[topic] = storedOauthTokens;
623
- return Promise.resolve(storedOauthTokens);
653
+ var lastOauthTokensCall = Promise.resolve("");
654
+ async function getOAuthAccessToken(hostConfig) {
655
+ if (isNode()) {
656
+ const tokens = await getOAuthTokensForNode(hostConfig);
657
+ if (tokens) {
658
+ handlePossibleErrors(tokens);
659
+ return tokens.accessToken || "";
660
+ }
661
+ return "";
624
662
  }
625
- const tokensPromise = acquireTokens();
626
- cachedTokens[topic] = tokensPromise;
627
- if (mayUseStorage) {
628
- const tokens = await tokensPromise;
629
- if (accessTokenStorage === "local" && tokens) {
630
- if (tokens.accessToken) {
631
- saveInLocalStorage(topic, "access-token", tokens.accessToken);
632
- }
633
- if (tokens.refreshToken) {
634
- saveInLocalStorage(topic, "refresh-token", tokens.refreshToken);
635
- }
636
- } else if (accessTokenStorage === "session" && tokens) {
637
- if (tokens.accessToken) {
638
- saveInSessionStorage(topic, "access-token", tokens.accessToken);
663
+ if (isBrowser()) {
664
+ lastOauthTokensCall = lastOauthTokensCall.then(async () => {
665
+ const tokens = await getOAuthTokensForBrowser(hostConfig);
666
+ if (tokens) {
667
+ handlePossibleErrors(tokens);
668
+ return tokens.accessToken || "";
639
669
  }
640
- if (tokens.refreshToken) {
641
- saveInSessionStorage(topic, "refresh-token", tokens.refreshToken);
670
+ return "";
671
+ });
672
+ }
673
+ return lastOauthTokensCall;
674
+ }
675
+ async function refreshAccessToken(hostConfig) {
676
+ const tokens = await loadCachedOauthTokens(hostConfig);
677
+ clearStoredOauthTokens(hostConfig);
678
+ if (tokens && tokens.refreshToken && hostConfig.clientSecret) {
679
+ const refreshedTokens = await loadOrAcquireAccessTokenOauth(hostConfig, async () => {
680
+ if (!tokens || !tokens.refreshToken || !hostConfig.clientSecret) {
681
+ throw new Error("Trying to refresh tokens without refreshToken or clientSecret");
642
682
  }
683
+ return getOauthTokensWithRefreshToken(
684
+ toValidLocationUrl(hostConfig),
685
+ tokens.refreshToken,
686
+ hostConfig.clientSecret
687
+ );
688
+ });
689
+ if (refreshedTokens) {
690
+ handlePossibleErrors(refreshedTokens);
643
691
  }
644
692
  }
645
- return tokensPromise;
646
693
  }
647
- function clearStoredOauthTokens(hostConfig) {
648
- const topic = getTopicFromOauthHostConfig(hostConfig);
649
- delete cachedTokens[topic];
650
- if (isBrowser()) {
651
- deleteFromLocalStorage(topic, ["access-token", "refresh-token"]);
652
- deleteFromSessionStorage(topic, ["access-token", "refresh-token"]);
694
+ function extractCodeAndState(input) {
695
+ if (typeof input === "string") {
696
+ const queryParams = new URLSearchParams(new URL(input).search);
697
+ return {
698
+ code: queryParams.get("code") || "",
699
+ state: queryParams.get("state") || ""
700
+ };
653
701
  }
702
+ return input;
654
703
  }
655
- function clearStoredAnonymousTokens(hostConfig) {
656
- const topic = getTopicFromAnonHostConfig(hostConfig);
657
- delete cachedTokens[topic];
658
- if (isBrowser()) {
659
- deleteFromLocalStorage(topic, ["access-token", "refresh-token"]);
660
- deleteFromSessionStorage(topic, ["access-token", "refresh-token"]);
661
- }
704
+ function errorMessageToAuthData(message) {
705
+ return {
706
+ accessToken: void 0,
707
+ refreshToken: void 0,
708
+ errors: [
709
+ {
710
+ code: "",
711
+ status: 401,
712
+ title: message,
713
+ detail: ""
714
+ }
715
+ ]
716
+ };
662
717
  }
663
718
 
664
- // src/auth/internal/default-auth-modules/oauth/oauth-utils.ts
665
- function toPerformInteractiveLoginFunction(performInteractiveLogin) {
666
- if (typeof performInteractiveLogin === "string") {
667
- const fn = lookupInteractiveLoginFn(performInteractiveLogin);
668
- if (!fn) {
669
- throw new Error(`No such function: ${performInteractiveLogin}`);
670
- }
671
- return fn;
719
+ // src/auth/internal/default-auth-modules/oauth/temporary-token.ts
720
+ async function exchangeAccessTokenForTemporaryToken(hostConfig, accessToken, purpose) {
721
+ const response = await fetch(`${toValidLocationUrl(hostConfig)}/oauth/token`, {
722
+ method: "POST",
723
+ credentials: "include",
724
+ mode: "cors",
725
+ headers: { "content-type": "application/json" },
726
+ redirect: "follow",
727
+ body: JSON.stringify({
728
+ subject_token: accessToken,
729
+ subject_token_type: "urn:ietf:params:oauth:token-type:access_token",
730
+ grant_type: "urn:ietf:params:oauth:grant-type:token-exchange",
731
+ purpose,
732
+ redirect_uri: globalThis.location?.href,
733
+ client_id: hostConfig.clientId
734
+ })
735
+ });
736
+ if (response.status !== 200) {
737
+ throw await toError(response);
672
738
  }
673
- return performInteractiveLogin;
674
- }
675
- function lookupGetAccessFn(getAccessToken2) {
676
- return globalThis[getAccessToken2];
677
- }
678
- function lookupInteractiveLoginFn(name) {
679
- return globalThis[name];
739
+ const data = await response.json();
740
+ return data.access_token;
680
741
  }
681
- function handlePossibleErrors(data) {
682
- if (data.errors) {
683
- throw new AuthorizationError(data.errors);
742
+ async function toError(response) {
743
+ const body = await response.text();
744
+ try {
745
+ const data = JSON.parse(body);
746
+ return new AuthorizationError(data.errors);
747
+ } catch {
748
+ return new AuthorizationError([
749
+ {
750
+ code: "unknown",
751
+ status: response.status,
752
+ detail: body,
753
+ title: "Unknown authentication error"
754
+ }
755
+ ]);
684
756
  }
685
757
  }
686
- function toQueryString(queryParams) {
687
- const queryParamsKeys = Object.keys(queryParams);
688
- queryParamsKeys.sort();
689
- const query = queryParamsKeys.map((k) => `${k}=${queryParams[k]}`).join("&");
690
- return query;
758
+
759
+ // src/auth/internal/default-auth-modules/anonymous.ts
760
+ async function handlePotentialAuthenticationErrorAndRetry(hostConfig, fn) {
761
+ try {
762
+ return await fn();
763
+ } catch (err) {
764
+ const { retry } = await handleAuthenticationError({
765
+ hostConfig,
766
+ canRetry: true
767
+ });
768
+ if (retry) {
769
+ return fn();
770
+ }
771
+ throw err;
772
+ }
691
773
  }
692
- function byteArrayToBase64(hashArray) {
693
- let result2 = "";
774
+ async function getOrCreateTrackingCode(hostConfig) {
775
+ let trackingCode;
694
776
  if (isBrowser()) {
695
- const byteArrayToString = String.fromCharCode.apply(null, hashArray);
696
- result2 = btoa(byteArrayToString);
697
- } else if (isNode()) {
698
- result2 = Buffer.from(hashArray).toString("base64");
777
+ const topic = getTopicFromAnonHostConfig(hostConfig);
778
+ trackingCode = loadFromLocalStorage(topic, "tracking-code");
779
+ if (!trackingCode) {
780
+ trackingCode = createTrackingCode();
781
+ }
782
+ saveInLocalStorage(topic, "tracking-code", trackingCode);
699
783
  } else {
700
- throw new Error("Environment not supported for oauth2 authentication");
784
+ trackingCode = createTrackingCode();
701
785
  }
702
- return result2;
703
- }
704
- async function sha256(message) {
705
- const msgBuffer = new TextEncoder().encode(message);
706
- const hashBuffer = await globalThis.crypto.subtle.digest("SHA-256", msgBuffer);
707
- const hashArray = Array.from(new Uint8Array(hashBuffer));
708
- const hashBase64 = byteArrayToBase64(hashArray);
709
- return hashBase64.replaceAll(/\+/g, "-").replaceAll(/\//g, "_").replace(/=+$/, "");
710
- }
711
- async function createInteractiveLoginUrl(hostConfig, redirectUri, state, verifier) {
712
- const clientId = hostConfig.clientId || "";
713
- const locationUrl = toValidLocationUrl(hostConfig);
714
- const codeChallenge = await sha256(verifier);
715
- const queryParams = {
716
- response_type: "code",
717
- client_id: clientId,
718
- redirect_uri: redirectUri,
719
- scope: hostConfig.scope || "user_default",
720
- state,
721
- code_challenge: codeChallenge,
722
- code_challenge_method: "S256"
723
- };
724
- return `${locationUrl}/oauth/authorize?${toQueryString(queryParams)}`;
786
+ return trackingCode;
725
787
  }
726
- async function startFullPageLoginFlow(hostConfig) {
727
- const clientId = hostConfig.clientId || "";
728
- const locationUrl = toValidLocationUrl(hostConfig);
729
- const verifier = generateRandomString(128);
730
- const state = generateRandomString(43);
731
- const codeChallenge = await sha256(verifier);
732
- const redirectUri = hostConfig.redirectUri || globalThis.location.href;
733
- const topic = getTopicFromOauthHostConfig(hostConfig);
734
- clearStoredOauthTokens(hostConfig);
735
- saveInSessionStorage(topic, "state", state);
736
- saveInSessionStorage(topic, "verifier", verifier);
737
- saveInSessionStorage(topic, "href", globalThis.location.href);
738
- saveInSessionStorage("", "client-in-progress", topic);
739
- const queryParams = {
740
- response_type: "code",
741
- client_id: clientId,
742
- redirect_uri: redirectUri,
743
- scope: hostConfig.scope || "user_default",
744
- state,
745
- code_challenge: codeChallenge,
746
- code_challenge_method: "S256"
747
- };
748
- const url = `${locationUrl}/oauth/authorize?${toQueryString(queryParams)}`;
749
- globalThis.location.replace(url);
788
+ function createTrackingCode() {
789
+ const timeStamp = Math.floor(Date.now() / 1e3).toString(16);
790
+ const randomString = generateRandomHexString(40 - timeStamp.length);
791
+ return `${timeStamp}${randomString}`;
750
792
  }
751
- async function exchangeCodeAndVerifierForAccessTokenData(hostConfig, code, verifier, redirectUri) {
752
- try {
753
- const result2 = await fetch(`${toValidLocationUrl(hostConfig)}/oauth/token`, {
754
- method: "POST",
755
- credentials: "include",
756
- mode: "cors",
757
- headers: { "content-type": "application/json" },
758
- redirect: "follow",
759
- body: JSON.stringify({
760
- grant_type: "authorization_code",
761
- scope: hostConfig.scope || "user_default",
762
- ...code ? { code } : {},
763
- ...{ redirect_uri: redirectUri || globalThis.location.href },
764
- ...verifier ? { code_verifier: verifier } : {},
765
- client_id: hostConfig.clientId
766
- })
767
- });
768
- const data = await result2.json();
769
- handlePossibleErrors(data);
770
- return {
771
- accessToken: data.access_token,
772
- refreshToken: data.refresh_token,
773
- errors: data.errors
774
- };
775
- } catch (err) {
776
- console.error(err);
777
- return new Promise(() => {
778
- });
793
+ async function getAnonymousAccessToken(hostConfig) {
794
+ const { accessCode, clientId } = hostConfig;
795
+ if (!accessCode || !clientId) {
796
+ throw new InvalidHostConfigError(
797
+ 'A host config with authType set to "anonymous" has to provide both an accessCode and clientId'
798
+ );
779
799
  }
780
- }
781
- function createBodyWithCredentialsEtc(clientId, clientSecret, scope, subject, userId) {
782
- const commonProps = {
783
- client_id: clientId,
784
- client_secret: clientSecret,
785
- scope
786
- };
787
- if (subject) {
788
- return {
789
- ...commonProps,
790
- grant_type: "urn:qlik:oauth:user-impersonation",
791
- user_lookup: {
792
- field: "subject",
793
- value: subject
794
- }
795
- };
800
+ const tokens = await loadOrAcquireAccessTokenAnon(hostConfig, async () => {
801
+ const baseUrl = toValidLocationUrl(hostConfig);
802
+ const trackingCode = await getOrCreateTrackingCode(hostConfig);
803
+ return getAnonymousOauthAccessToken(baseUrl, accessCode, clientId, trackingCode);
804
+ });
805
+ if (!tokens) {
806
+ return "";
807
+ }
808
+ if (tokens.errors) {
809
+ throw new AuthorizationError(tokens.errors);
796
810
  }
797
- if (userId) {
798
- return {
799
- ...commonProps,
800
- grant_type: "urn:qlik:oauth:user-impersonation",
801
- user_lookup: {
802
- field: "userId",
803
- value: userId
804
- }
805
- };
811
+ if (tokens.accessToken) {
812
+ return tokens.accessToken;
806
813
  }
814
+ return "";
815
+ }
816
+ async function getRestCallAuthParams({
817
+ hostConfig
818
+ }) {
807
819
  return {
808
- ...commonProps,
809
- grant_type: "client_credentials"
820
+ headers: {
821
+ Authorization: `Bearer ${await getAnonymousAccessToken(hostConfig)}`
822
+ },
823
+ queryParams: {},
824
+ credentials: "omit"
810
825
  };
811
826
  }
812
- async function getOauthTokensWithCredentials(baseUrl, clientId, clientSecret, scope = "user_default", subject, userId) {
813
- const result2 = await fetch(`${baseUrl}/oauth/token`, {
814
- method: "POST",
815
- mode: "cors",
816
- headers: { "content-type": "application/json" },
817
- body: JSON.stringify(createBodyWithCredentialsEtc(clientId, clientSecret, scope, subject, userId))
827
+ async function getWebSocketAuthParams({
828
+ hostConfig
829
+ }) {
830
+ const websocketAccessToken = await handlePotentialAuthenticationErrorAndRetry(hostConfig, async () => {
831
+ const accessToken = await getAnonymousAccessToken(hostConfig);
832
+ return exchangeAccessTokenForTemporaryToken(hostConfig, accessToken, "websocket");
818
833
  });
819
- const data = await result2.json();
820
834
  return {
821
- accessToken: data.access_token,
822
- refreshToken: data.refresh_token,
823
- errors: data.errors
835
+ queryParams: {
836
+ accessToken: websocketAccessToken
837
+ }
824
838
  };
825
839
  }
826
- async function getOauthTokensWithRefreshToken(baseUrl, refreshToken, clientSecret) {
827
- const result2 = await fetch(`${baseUrl}/oauth/token`, {
828
- method: "POST",
829
- mode: "cors",
830
- headers: { "content-type": "application/json" },
831
- body: JSON.stringify({
832
- grant_type: "refresh_token",
833
- refresh_token: refreshToken,
834
- client_secret: clientSecret
835
- })
840
+ async function getWebResourceAuthParams({
841
+ hostConfig
842
+ }) {
843
+ const websocketResourceAccessToken = await handlePotentialAuthenticationErrorAndRetry(hostConfig, async () => {
844
+ const accessToken = await getAnonymousAccessToken(hostConfig);
845
+ return exchangeAccessTokenForTemporaryToken(hostConfig, accessToken, "websocket");
836
846
  });
837
- const data = await result2.json();
838
847
  return {
839
- accessToken: data.access_token,
840
- refreshToken: data.refresh_token,
841
- errors: data.errors
848
+ queryParams: {
849
+ accessToken: websocketResourceAccessToken
850
+ }
842
851
  };
843
852
  }
844
- async function getAnonymousOauthAccessToken(baseUrl, accessCode, clientId, trackingCode) {
845
- const result2 = await fetch(`${baseUrl}/oauth/token/anonymous-embed`, {
846
- method: "POST",
847
- mode: "cors",
848
- headers: { "content-type": "application/json" },
849
- body: JSON.stringify({
850
- eac: accessCode,
851
- client_id: clientId,
852
- grant_type: "urn:qlik:oauth:anonymous-embed",
853
- tracking_code: trackingCode
854
- })
855
- });
856
- const data = await result2.json();
853
+ async function handleAuthenticationError({
854
+ hostConfig
855
+ }) {
856
+ clearStoredAnonymousTokens(hostConfig);
857
857
  return {
858
- accessToken: data.access_token,
859
- refreshToken: data.refresh_token,
860
- errors: data.errors
858
+ preventDefault: false,
859
+ retry: true
861
860
  };
862
861
  }
863
- async function getOAuthTokensForNode(hostConfig) {
864
- const { clientId, clientSecret } = hostConfig;
865
- if (!clientId || !clientSecret) {
866
- throw new InvalidHostConfigError(
867
- 'A host config with authType set to "oauth2" has to provide a clientId and a clientSecret'
868
- );
869
- }
870
- const oauthTokens = await loadOrAcquireAccessTokenOauth(hostConfig, async () => {
871
- if (!hostConfig.clientId || !hostConfig.clientSecret) {
872
- throw new InvalidHostConfigError(
873
- 'A host config with authType set to "oauth2" has to provide a clientId and a clientSecret'
874
- );
875
- }
876
- return getOauthTokensWithCredentials(
877
- toValidLocationUrl(hostConfig),
878
- hostConfig.clientId,
879
- hostConfig.clientSecret,
880
- hostConfig.scope,
881
- hostConfig.subject,
882
- hostConfig.userId
883
- );
862
+ var anonymous_default = {
863
+ requiredProps: ["clientId", "accessCode"],
864
+ optionalProps: [],
865
+ getRestCallAuthParams,
866
+ getWebSocketAuthParams,
867
+ getWebResourceAuthParams,
868
+ handleAuthenticationError
869
+ };
870
+
871
+ // src/auth/internal/default-auth-modules/apikey.ts
872
+ function getRestCallAuthParams2({ hostConfig }) {
873
+ return Promise.resolve({
874
+ headers: {
875
+ Authorization: `Bearer ${hostConfig?.apiKey}`
876
+ },
877
+ queryParams: {},
878
+ credentials: "omit"
884
879
  });
885
- return oauthTokens;
886
880
  }
887
- async function getOAuthTokensForBrowser(hostConfig) {
888
- const { clientId } = hostConfig;
889
- if (!clientId) {
890
- throw new InvalidHostConfigError('A host config with authType set to "oauth2" has to also provide a clientId');
891
- }
892
- const oauthTokens = await loadOrAcquireAccessTokenOauth(hostConfig, async () => {
893
- if (hostConfig.getAccessToken) {
894
- try {
895
- const tokenFetchedFromRemote = typeof hostConfig.getAccessToken === "string" ? await lookupGetAccessFn(hostConfig.getAccessToken)() : await hostConfig.getAccessToken();
896
- return {
897
- accessToken: tokenFetchedFromRemote,
898
- refreshToken: void 0,
899
- errors: void 0
900
- };
901
- } catch {
902
- return errorMessageToAuthData("Could not fetch access token using custom function");
903
- }
881
+ async function getWebSocketAuthParams2() {
882
+ return {
883
+ queryParams: {
884
+ // accessToken: hostConfig.apiKey,
904
885
  }
905
- if (hostConfig.performInteractiveLogin) {
906
- let usedRedirectUri;
907
- try {
908
- const verifier2 = generateRandomString(128);
909
- const originalState = generateRandomString(43);
910
- const { code: code2, state } = extractCodeAndState(
911
- await toPerformInteractiveLoginFunction(hostConfig.performInteractiveLogin)({
912
- getLoginUrl: async ({ redirectUri }) => {
913
- usedRedirectUri = redirectUri;
914
- return createInteractiveLoginUrl(hostConfig, redirectUri, originalState, verifier2);
915
- }
916
- })
917
- );
918
- if (!usedRedirectUri) {
919
- return errorMessageToAuthData("No redirect uri provided");
920
- }
921
- if (originalState !== state) {
922
- return errorMessageToAuthData("State returned by custom interactive login function does not match original");
923
- }
924
- if (!code2) {
925
- return errorMessageToAuthData("No code found in response from custom interactive login function");
926
- }
927
- const tokenResponse = await exchangeCodeAndVerifierForAccessTokenData(
886
+ };
887
+ }
888
+ function handleAuthenticationError2() {
889
+ return Promise.resolve({});
890
+ }
891
+ var apikey_default = {
892
+ requiredProps: ["apiKey"],
893
+ optionalProps: [],
894
+ getRestCallAuthParams: getRestCallAuthParams2,
895
+ getWebSocketAuthParams: getWebSocketAuthParams2,
896
+ handleAuthenticationError: handleAuthenticationError2
897
+ };
898
+
899
+ // src/http/http-constants.ts
900
+ var QLIK_CSRF_TOKEN = "qlik-csrf-token";
901
+
902
+ // src/http/http-functions.ts
903
+ function clearCsrfToken(hostConfig) {
904
+ const locationUrl = toValidLocationUrl(hostConfig);
905
+ delete csrfTokens[locationUrl];
906
+ }
907
+ async function getCsrfToken(hostConfig, noCache) {
908
+ const locationUrl = toValidLocationUrl(hostConfig);
909
+ let pathTemplate;
910
+ if (await isWindows(hostConfig)) {
911
+ pathTemplate = "/qps/csrftoken";
912
+ } else {
913
+ pathTemplate = "/api/v1/csrf-token";
914
+ }
915
+ const fetchCsrfToken = async () => {
916
+ try {
917
+ const res = await invokeFetch("csrf-token", {
918
+ method: "get",
919
+ pathTemplate,
920
+ options: {
928
921
  hostConfig,
929
- code2,
930
- verifier2,
931
- usedRedirectUri
932
- );
933
- return tokenResponse;
934
- } catch (error) {
935
- return {
936
- accessToken: void 0,
937
- refreshToken: void 0,
938
- errors: [
939
- {
940
- code: "",
941
- status: 401,
942
- title: "Could not perform custom interactive login",
943
- detail: `${error}`
944
- }
945
- ]
946
- };
922
+ noCache: true
923
+ }
924
+ });
925
+ const csrfToken = res.headers.get(QLIK_CSRF_TOKEN);
926
+ if (!csrfToken) {
927
+ return "";
947
928
  }
948
- }
949
- const topic = getTopicFromOauthHostConfig(hostConfig);
950
- const code = loadAndDeleteFromSessionStorage(topic, "code");
951
- const verifier = loadAndDeleteFromSessionStorage(topic, "verifier");
952
- if (code && verifier) {
953
- const tokenResponse = await exchangeCodeAndVerifierForAccessTokenData(
954
- hostConfig,
955
- code,
956
- verifier,
957
- hostConfig.redirectUri
958
- );
959
- if (tokenResponse) {
960
- return tokenResponse;
929
+ return csrfToken;
930
+ } catch (e) {
931
+ const error = e;
932
+ if (error.status === 404) {
933
+ return "";
961
934
  }
935
+ throw e;
962
936
  }
963
- return void 0;
964
- });
965
- if (oauthTokens) {
966
- return oauthTokens;
937
+ };
938
+ if (noCache) {
939
+ csrfTokens[locationUrl] = fetchCsrfToken();
940
+ return csrfTokens[locationUrl];
967
941
  }
968
- if (hostConfig.performInteractiveLogin) {
969
- return new Promise(() => {
970
- });
942
+ csrfTokens[locationUrl] = csrfTokens[locationUrl] || fetchCsrfToken();
943
+ return csrfTokens[locationUrl];
944
+ }
945
+ var csrfTokens = {};
946
+
947
+ // src/auth/internal/internal-auth-functions.ts
948
+ function internalGetCredentialsForCookieAuth(hostConfig) {
949
+ if (hostConfig.crossSiteCookies === false) {
950
+ return "same-origin";
971
951
  }
972
- if (hostConfig.authRedirectUserConfirmation) {
973
- await hostConfig.authRedirectUserConfirmation();
952
+ if (isHostCrossOrigin(hostConfig)) {
953
+ return "include";
974
954
  }
975
- startFullPageLoginFlow(hostConfig);
976
- return new Promise(() => {
977
- });
955
+ return "same-origin";
978
956
  }
979
- var lastOauthTokensCall = Promise.resolve("");
980
- async function getOAuthAccessToken(hostConfig) {
981
- if (isNode()) {
982
- const tokens = await getOAuthTokensForNode(hostConfig);
983
- if (tokens) {
984
- handlePossibleErrors(tokens);
985
- return tokens.accessToken || "";
986
- }
987
- return "";
957
+
958
+ // src/auth/internal/default-auth-modules/cookie.ts
959
+ function isModifyingVerb(verb) {
960
+ return !(verb === "get" || verb === "GET");
961
+ }
962
+ async function getRestCallAuthParams3({
963
+ hostConfig,
964
+ method
965
+ }) {
966
+ const headers = {};
967
+ if (isModifyingVerb(method)) {
968
+ headers["qlik-csrf-token"] = await getCsrfToken(hostConfig);
988
969
  }
989
- if (isBrowser()) {
990
- lastOauthTokensCall = lastOauthTokensCall.then(async () => {
991
- const tokens = await getOAuthTokensForBrowser(hostConfig);
992
- if (tokens) {
993
- handlePossibleErrors(tokens);
994
- return tokens.accessToken || "";
995
- }
996
- return "";
997
- });
970
+ if (hostConfig.webIntegrationId) {
971
+ headers["qlik-web-integration-id"] = hostConfig.webIntegrationId;
998
972
  }
999
- return lastOauthTokensCall;
973
+ return { headers, queryParams: {}, credentials: internalGetCredentialsForCookieAuth(hostConfig) };
1000
974
  }
1001
- async function refreshAccessToken(hostConfig) {
1002
- const tokens = await loadCachedOauthTokens(hostConfig);
1003
- clearStoredOauthTokens(hostConfig);
1004
- if (tokens && tokens.refreshToken && hostConfig.clientSecret) {
1005
- const refreshedTokens = await loadOrAcquireAccessTokenOauth(hostConfig, async () => {
1006
- if (!tokens || !tokens.refreshToken || !hostConfig.clientSecret) {
1007
- throw new Error("Trying to refresh tokens without refreshToken or clientSecret");
1008
- }
1009
- return getOauthTokensWithRefreshToken(
1010
- toValidLocationUrl(hostConfig),
1011
- tokens.refreshToken,
1012
- hostConfig.clientSecret
1013
- );
1014
- });
1015
- if (refreshedTokens) {
1016
- handlePossibleErrors(refreshedTokens);
1017
- }
975
+ async function getWebSocketAuthParams3({
976
+ hostConfig
977
+ }) {
978
+ const params = {
979
+ // Bypass the cache to get one rest call out the door that can catch a 401 since the websocket only returns a general error
980
+ "qlik-csrf-token": await getCsrfToken(hostConfig, true)
981
+ };
982
+ if (hostConfig.webIntegrationId) {
983
+ params["qlik-web-integration-id"] = hostConfig.webIntegrationId;
1018
984
  }
985
+ return { queryParams: params };
1019
986
  }
1020
- function extractCodeAndState(input) {
1021
- if (typeof input === "string") {
1022
- const queryParams = new URLSearchParams(new URL(input).search);
987
+ async function handleAuthenticationError3({
988
+ hostConfig,
989
+ status
990
+ }) {
991
+ clearCsrfToken(hostConfig);
992
+ if (status === 403) {
1023
993
  return {
1024
- code: queryParams.get("code") || "",
1025
- state: queryParams.get("state") || ""
994
+ preventDefault: false,
995
+ retry: true
1026
996
  };
1027
997
  }
1028
- return input;
1029
- }
1030
- function errorMessageToAuthData(message) {
998
+ const webIntegrationParam = hostConfig.webIntegrationId ? `qlik-web-integration-id=${hostConfig?.webIntegrationId}&` : "";
999
+ const locationUrl = toValidLocationUrl(hostConfig);
1000
+ if (hostConfig.authRedirectUserConfirmation) {
1001
+ await hostConfig.authRedirectUserConfirmation();
1002
+ }
1003
+ globalThis.location.replace(
1004
+ `${locationUrl}/login?${webIntegrationParam}returnto=${encodeURIComponent(globalThis.location.href)}`
1005
+ );
1031
1006
  return {
1032
- accessToken: void 0,
1033
- refreshToken: void 0,
1034
- errors: [
1035
- {
1036
- code: "",
1037
- status: 401,
1038
- title: message,
1039
- detail: ""
1040
- }
1041
- ]
1007
+ preventDefault: true
1042
1008
  };
1043
1009
  }
1010
+ var cookie_default = {
1011
+ requiredProps: [],
1012
+ optionalProps: ["webIntegrationId", "crossSiteCookies", "anonymousMode"],
1013
+ getRestCallAuthParams: getRestCallAuthParams3,
1014
+ getWebSocketAuthParams: getWebSocketAuthParams3,
1015
+ handleAuthenticationError: handleAuthenticationError3
1016
+ };
1044
1017
 
1045
- // src/auth/internal/default-auth-modules/oauth/temporary-token.ts
1046
- async function exchangeAccessTokenForTemporaryToken(hostConfig, accessToken, purpose) {
1047
- const response = await fetch(`${toValidLocationUrl(hostConfig)}/oauth/token`, {
1048
- method: "POST",
1049
- credentials: "include",
1050
- mode: "cors",
1051
- headers: { "content-type": "application/json" },
1052
- redirect: "follow",
1053
- body: JSON.stringify({
1054
- subject_token: accessToken,
1055
- subject_token_type: "urn:ietf:params:oauth:token-type:access_token",
1056
- grant_type: "urn:ietf:params:oauth:grant-type:token-exchange",
1057
- purpose,
1058
- redirect_uri: globalThis.location?.href,
1059
- client_id: hostConfig.clientId
1060
- })
1061
- });
1062
- if (response.status !== 200) {
1063
- throw await toError(response);
1064
- }
1065
- const data = await response.json();
1066
- return data.access_token;
1018
+ // src/auth/internal/default-auth-modules/none.ts
1019
+ function getRestCallAuthParams4() {
1020
+ return Promise.resolve({ headers: {}, queryParams: {}, credentials: "same-origin" });
1067
1021
  }
1068
- async function toError(response) {
1069
- const body = await response.text();
1070
- try {
1071
- const data = JSON.parse(body);
1072
- return new AuthorizationError(data.errors);
1073
- } catch {
1074
- return new AuthorizationError([
1075
- {
1076
- code: "unknown",
1077
- status: response.status,
1078
- detail: body,
1079
- title: "Unknown authentication error"
1022
+ function getWebSocketAuthParams4() {
1023
+ return Promise.resolve({ queryParams: {} });
1024
+ }
1025
+ function handleAuthenticationError4() {
1026
+ return Promise.resolve({});
1027
+ }
1028
+ var none_default = {
1029
+ requiredProps: [],
1030
+ optionalProps: [],
1031
+ getRestCallAuthParams: getRestCallAuthParams4,
1032
+ getWebSocketAuthParams: getWebSocketAuthParams4,
1033
+ handleAuthenticationError: handleAuthenticationError4
1034
+ };
1035
+
1036
+ // src/auth/internal/default-auth-modules/oauth/callback.ts
1037
+ function handleOAuthCallback() {
1038
+ const urlParams = new URLSearchParams(globalThis.location.search);
1039
+ const callbackCode = urlParams.get("code") || void 0;
1040
+ const callbackState = urlParams.get("state") || void 0;
1041
+ if (urlParams.get("error")) {
1042
+ const element = document.createElement("pre");
1043
+ element.innerText = `<code>${JSON.stringify({
1044
+ error: urlParams.get("error"),
1045
+ error_code: urlParams.get("error_code"),
1046
+ error_description: urlParams.get("error_description"),
1047
+ error_detail: urlParams.get("error_detail"),
1048
+ error_uri: urlParams.get("error_uri")
1049
+ })}</code>`;
1050
+ document.body.prepend(element);
1051
+ }
1052
+ const topic = loadAndDeleteFromSessionStorage("", "client-in-progress");
1053
+ if (topic && callbackCode && callbackState) {
1054
+ const stateFromLocalStorage = loadAndDeleteFromSessionStorage(topic, "state");
1055
+ const finalRedirectUri = loadAndDeleteFromSessionStorage(topic, "href");
1056
+ if (stateFromLocalStorage && stateFromLocalStorage === callbackState && finalRedirectUri) {
1057
+ saveInSessionStorage(topic, "code", callbackCode);
1058
+ if (finalRedirectUri !== globalThis.location.href) {
1059
+ globalThis.location.replace(finalRedirectUri);
1080
1060
  }
1081
- ]);
1061
+ }
1082
1062
  }
1083
1063
  }
1084
1064
 
1085
- // src/auth/internal/default-auth-modules/anonymous.ts
1086
- async function handlePotentialAuthenticationErrorAndRetry(hostConfig, fn) {
1065
+ // src/auth/internal/default-auth-modules/oauth.ts
1066
+ if (isBrowser()) {
1067
+ handleOAuthCallback();
1068
+ }
1069
+ async function handlePotentialAuthenticationErrorAndRetry2(hostConfig, fn) {
1087
1070
  try {
1088
1071
  return await fn();
1089
1072
  } catch (err) {
1090
- const { retry } = await handleAuthenticationError2({
1073
+ const { retry } = await handleAuthenticationError5({
1091
1074
  hostConfig,
1092
1075
  canRetry: true
1093
1076
  });
@@ -1097,518 +1080,586 @@ async function handlePotentialAuthenticationErrorAndRetry(hostConfig, fn) {
1097
1080
  throw err;
1098
1081
  }
1099
1082
  }
1100
- async function getOrCreateTrackingCode(hostConfig) {
1101
- let trackingCode;
1083
+ async function getRestCallAuthParams5({
1084
+ hostConfig
1085
+ }) {
1086
+ return {
1087
+ headers: {
1088
+ Authorization: `Bearer ${await getOAuthAccessToken(hostConfig)}`
1089
+ },
1090
+ queryParams: {},
1091
+ credentials: "omit"
1092
+ };
1093
+ }
1094
+ async function getWebSocketAuthParams5({
1095
+ hostConfig
1096
+ }) {
1097
+ const websocketAccessToken = await handlePotentialAuthenticationErrorAndRetry2(hostConfig, async () => {
1098
+ const accessToken = await getOAuthAccessToken(hostConfig);
1099
+ return exchangeAccessTokenForTemporaryToken(hostConfig, accessToken, "websocket");
1100
+ });
1101
+ return {
1102
+ queryParams: {
1103
+ accessToken: websocketAccessToken
1104
+ }
1105
+ };
1106
+ }
1107
+ async function getWebResourceAuthParams2({
1108
+ hostConfig
1109
+ }) {
1110
+ const webResourceAccessToken = await handlePotentialAuthenticationErrorAndRetry2(hostConfig, async () => {
1111
+ const accessToken = await getOAuthAccessToken(hostConfig);
1112
+ return exchangeAccessTokenForTemporaryToken(hostConfig, accessToken, "webresource");
1113
+ });
1114
+ return {
1115
+ queryParams: {
1116
+ accessToken: webResourceAccessToken
1117
+ }
1118
+ };
1119
+ }
1120
+ async function handleAuthenticationError5({
1121
+ hostConfig
1122
+ }) {
1123
+ if (hostConfig.getAccessToken) {
1124
+ clearStoredOauthTokens(hostConfig);
1125
+ return {
1126
+ preventDefault: false,
1127
+ retry: true
1128
+ };
1129
+ }
1102
1130
  if (isBrowser()) {
1103
- const topic = getTopicFromAnonHostConfig(hostConfig);
1104
- trackingCode = loadFromLocalStorage(topic, "tracking-code");
1105
- if (!trackingCode) {
1106
- trackingCode = createTrackingCode();
1131
+ if (hostConfig.performInteractiveLogin) {
1132
+ clearStoredOauthTokens(hostConfig);
1133
+ return {
1134
+ retry: true
1135
+ };
1107
1136
  }
1108
- saveInLocalStorage(topic, "tracking-code", trackingCode);
1109
- } else {
1110
- trackingCode = createTrackingCode();
1137
+ if (hostConfig.authRedirectUserConfirmation) {
1138
+ await hostConfig.authRedirectUserConfirmation();
1139
+ }
1140
+ startFullPageLoginFlow(hostConfig);
1141
+ return {
1142
+ preventDefault: true
1143
+ };
1111
1144
  }
1112
- return trackingCode;
1145
+ await refreshAccessToken(hostConfig);
1146
+ return {
1147
+ preventDefault: false,
1148
+ retry: true
1149
+ };
1150
+ }
1151
+ var oauth_default = {
1152
+ requiredProps: ["clientId"],
1153
+ optionalProps: [
1154
+ "clientSecret",
1155
+ "redirectUri",
1156
+ "accessTokenStorage",
1157
+ "scope",
1158
+ "subject",
1159
+ "userId",
1160
+ "noCache",
1161
+ "getAccessToken",
1162
+ "performInteractiveLogin"
1163
+ ],
1164
+ getRestCallAuthParams: getRestCallAuthParams5,
1165
+ getWebSocketAuthParams: getWebSocketAuthParams5,
1166
+ getWebResourceAuthParams: getWebResourceAuthParams2,
1167
+ handleAuthenticationError: handleAuthenticationError5
1168
+ };
1169
+
1170
+ // src/auth/internal/default-auth-modules/reference.ts
1171
+ function getRestCallAuthParams6() {
1172
+ throw new Error("getRestCallAuthParams should never be called for reference auth module");
1113
1173
  }
1114
- function createTrackingCode() {
1115
- const timeStamp = Math.floor(Date.now() / 1e3).toString(16);
1116
- const randomString = generateRandomHexString(40 - timeStamp.length);
1117
- return `${timeStamp}${randomString}`;
1174
+ function getWebSocketAuthParams6() {
1175
+ throw new Error("getWebSocketAuthParams should never be called for reference auth module");
1118
1176
  }
1119
- async function getAnonymousAccessToken(hostConfig) {
1120
- const { accessCode, clientId } = hostConfig;
1121
- if (!accessCode || !clientId) {
1122
- throw new InvalidHostConfigError(
1123
- 'A host config with authType set to "anonymous" has to provide both an accessCode and clientId'
1124
- );
1125
- }
1126
- const tokens = await loadOrAcquireAccessTokenAnon(hostConfig, async () => {
1127
- const baseUrl = toValidLocationUrl(hostConfig);
1128
- const trackingCode = await getOrCreateTrackingCode(hostConfig);
1129
- return getAnonymousOauthAccessToken(baseUrl, accessCode, clientId, trackingCode);
1130
- });
1131
- if (!tokens) {
1132
- return "";
1133
- }
1134
- if (tokens.errors) {
1135
- throw new AuthorizationError(tokens.errors);
1136
- }
1137
- if (tokens.accessToken) {
1138
- return tokens.accessToken;
1177
+ function handleAuthenticationError6() {
1178
+ throw new Error("handleAuthenticationError should never be called for reference auth module");
1179
+ }
1180
+ var reference_default = {
1181
+ requiredProps: ["reference"],
1182
+ optionalProps: [],
1183
+ getRestCallAuthParams: getRestCallAuthParams6,
1184
+ getWebSocketAuthParams: getWebSocketAuthParams6,
1185
+ handleAuthenticationError: handleAuthenticationError6
1186
+ };
1187
+
1188
+ // src/auth/internal/default-auth-modules/windows-cookie/xrf-keys.ts
1189
+ var xrfKeys = {};
1190
+ function createXrfKey() {
1191
+ let result2 = "";
1192
+ for (let i = 0; i < 16; i += 1) {
1193
+ const j = Math.floor(Math.random() * 62);
1194
+ if (j < 10) {
1195
+ result2 += j;
1196
+ } else if (j > 9 && j < 36) {
1197
+ result2 += String.fromCharCode(j + 55);
1198
+ } else {
1199
+ result2 += String.fromCharCode(j + 61);
1200
+ }
1139
1201
  }
1140
- return "";
1202
+ return result2;
1203
+ }
1204
+ function getXrfKey(hostConfig) {
1205
+ const locationUrl = toValidLocationUrl(hostConfig);
1206
+ xrfKeys[locationUrl] = xrfKeys[locationUrl] || createXrfKey();
1207
+ return xrfKeys[locationUrl];
1141
1208
  }
1142
- async function getRestCallAuthParams2({
1209
+
1210
+ // src/auth/internal/default-auth-modules/windows-cookie.ts
1211
+ async function getRestCallAuthParams7({
1143
1212
  hostConfig
1144
1213
  }) {
1145
1214
  return {
1146
1215
  headers: {
1147
- Authorization: `Bearer ${await getAnonymousAccessToken(hostConfig)}`
1216
+ "X-Qlik-XrfKey": getXrfKey(hostConfig)
1148
1217
  },
1149
- queryParams: {},
1150
- credentials: "omit"
1151
- };
1152
- }
1153
- async function getWebSocketAuthParams2({
1154
- hostConfig
1155
- }) {
1156
- const websocketAccessToken = await handlePotentialAuthenticationErrorAndRetry(hostConfig, async () => {
1157
- const accessToken = await getAnonymousAccessToken(hostConfig);
1158
- return exchangeAccessTokenForTemporaryToken(hostConfig, accessToken, "websocket");
1159
- });
1160
- return {
1161
1218
  queryParams: {
1162
- accessToken: websocketAccessToken
1163
- }
1219
+ xrfkey: getXrfKey(hostConfig)
1220
+ },
1221
+ credentials: internalGetCredentialsForCookieAuth(hostConfig)
1164
1222
  };
1165
1223
  }
1166
- async function getWebResourceAuthParams2({
1224
+ async function getWebSocketAuthParams7({
1167
1225
  hostConfig
1168
1226
  }) {
1169
- const websocketResourceAccessToken = await handlePotentialAuthenticationErrorAndRetry(hostConfig, async () => {
1170
- const accessToken = await getAnonymousAccessToken(hostConfig);
1171
- return exchangeAccessTokenForTemporaryToken(hostConfig, accessToken, "websocket");
1172
- });
1173
1227
  return {
1174
1228
  queryParams: {
1175
- accessToken: websocketResourceAccessToken
1229
+ xrfkey: getXrfKey(hostConfig),
1230
+ "qlik-csrf-token": await getCsrfToken(hostConfig, true)
1176
1231
  }
1177
1232
  };
1178
1233
  }
1179
- async function handleAuthenticationError2({
1234
+ async function handleAuthenticationError7({
1180
1235
  hostConfig
1181
1236
  }) {
1182
- clearStoredAnonymousTokens(hostConfig);
1237
+ if (hostConfig.loginUri) {
1238
+ if (hostConfig.authRedirectUserConfirmation) {
1239
+ await hostConfig.authRedirectUserConfirmation();
1240
+ }
1241
+ globalThis.location.replace(
1242
+ hostConfig.loginUri.replace("{location}", encodeURIComponent(globalThis.location.href))
1243
+ );
1244
+ return {
1245
+ preventDefault: true
1246
+ };
1247
+ }
1183
1248
  return {
1184
- preventDefault: false,
1185
- retry: true
1249
+ // Do nothing, just let the error be thrown to calling code
1186
1250
  };
1187
1251
  }
1188
- var anonymous_default = {
1189
- getRestCallAuthParams: getRestCallAuthParams2,
1190
- getWebSocketAuthParams: getWebSocketAuthParams2,
1191
- getWebResourceAuthParams: getWebResourceAuthParams2,
1192
- handleAuthenticationError: handleAuthenticationError2,
1193
- validateHostConfig: (hostConfig) => internalValidateHostConfig(hostConfig, {
1194
- requiredProps: ["clientId", "accessCode"],
1195
- optionalProps: []
1196
- })
1252
+ var windows_cookie_default = {
1253
+ requiredProps: [],
1254
+ optionalProps: ["loginUri", "crossSiteCookies"],
1255
+ getRestCallAuthParams: getRestCallAuthParams7,
1256
+ getWebSocketAuthParams: getWebSocketAuthParams7,
1257
+ handleAuthenticationError: handleAuthenticationError7
1197
1258
  };
1198
1259
 
1199
- // src/auth/internal/default-auth-modules/apikey.ts
1200
- function getRestCallAuthParams3({ hostConfig }) {
1201
- return Promise.resolve({
1202
- headers: {
1203
- Authorization: `Bearer ${hostConfig?.apiKey}`
1204
- },
1205
- queryParams: {},
1206
- credentials: "omit"
1260
+ // src/auth/internal/auth-module-registry.ts
1261
+ var authModules = {};
1262
+ var ongoingAuthModuleLoading = Promise.resolve();
1263
+ var authModulesRegistered = false;
1264
+ (function registerDefaultAuthModules() {
1265
+ if (!authModulesRegistered) {
1266
+ registerAuthModule("apikey", apikey_default);
1267
+ registerAuthModule("cookie", cookie_default);
1268
+ registerAuthModule("none", none_default);
1269
+ registerAuthModule("oauth2", oauth_default);
1270
+ registerAuthModule("anonymous", anonymous_default);
1271
+ registerAuthModule("windowscookie", windows_cookie_default);
1272
+ registerAuthModule("reference", reference_default);
1273
+ authModulesRegistered = true;
1274
+ }
1275
+ })();
1276
+ function registerAuthModule(name, authModule) {
1277
+ authModules[name.toLowerCase()] = authModule;
1278
+ }
1279
+ function getRegisteredAuthModules() {
1280
+ return Object.keys(authModules);
1281
+ }
1282
+ function getRegisteredAuthModule(authType) {
1283
+ return authModules[authType.toLowerCase()];
1284
+ }
1285
+ async function getAuthModule(hostConfig) {
1286
+ const hostConfigToUse = withResolvedHostConfig(hostConfig);
1287
+ const authType = await determineAuthType(hostConfigToUse);
1288
+ if (ongoingAuthModuleLoading) {
1289
+ await ongoingAuthModuleLoading;
1290
+ }
1291
+ let authModule = getRegisteredAuthModule(authType);
1292
+ if (!authModule) {
1293
+ ongoingAuthModuleLoading = (async () => {
1294
+ authModule = await resolveGloballyDefinedAuthModule(authType);
1295
+ if (authModule) {
1296
+ registerAuthModule(authType, authModule);
1297
+ }
1298
+ })();
1299
+ await ongoingAuthModuleLoading;
1300
+ }
1301
+ if (!authModule) {
1302
+ throw new InvalidAuthTypeError(authType);
1303
+ }
1304
+ if (authModule.validateHostConfig) {
1305
+ authModule.validateHostConfig({ authType, ...hostConfigToUse });
1306
+ } else {
1307
+ internalValidateHostConfig(
1308
+ { authType, ...hostConfigToUse },
1309
+ { requiredProps: authModule.requiredProps || [], optionalProps: authModule.optionalProps || [] }
1310
+ );
1311
+ }
1312
+ return authModule;
1313
+ }
1314
+ async function resolveGloballyDefinedAuthModule(authType) {
1315
+ const globalWindow = globalThis;
1316
+ const globalVariable = globalWindow[authType];
1317
+ if (globalVariable) {
1318
+ let potentialAuthModule;
1319
+ if (typeof globalVariable === "function") {
1320
+ potentialAuthModule = await globalVariable();
1321
+ } else {
1322
+ potentialAuthModule = globalVariable;
1323
+ }
1324
+ if (potentialAuthModule && potentialAuthModule.getRestCallAuthParams && potentialAuthModule.getWebSocketAuthParams && potentialAuthModule.handleAuthenticationError) {
1325
+ return potentialAuthModule;
1326
+ }
1327
+ console.error("Not a valid auth module", potentialAuthModule);
1328
+ throw new InvalidAuthTypeError(authType);
1329
+ }
1330
+ return Promise.resolve(void 0);
1331
+ }
1332
+ function internalValidateHostConfig(hostConfig, { requiredProps, optionalProps }) {
1333
+ const missingRequiredProps = [];
1334
+ for (const requiredProp of requiredProps) {
1335
+ if (!hostConfig[requiredProp]) {
1336
+ missingRequiredProps.push(requiredProp);
1337
+ }
1338
+ }
1339
+ if (missingRequiredProps.length > 0) {
1340
+ throw new InvalidHostConfigError(
1341
+ `missing required properties in host config; '${missingRequiredProps.join("', '")}'`
1342
+ );
1343
+ }
1344
+ const validProps = [...hostConfigCommonProperties, ...requiredProps, ...optionalProps];
1345
+ const invalidKeys = [];
1346
+ Object.keys(hostConfig).forEach((key) => {
1347
+ if (!validProps.includes(key)) {
1348
+ invalidKeys.push(key);
1349
+ }
1207
1350
  });
1351
+ if (invalidKeys.length > 0) {
1352
+ console.warn(`WARNING: unknown properties in host config; '${invalidKeys.join("', '")}'`);
1353
+ }
1354
+ return true;
1208
1355
  }
1209
- async function getWebSocketAuthParams3() {
1210
- return {
1211
- queryParams: {
1212
- // accessToken: hostConfig.apiKey,
1356
+ async function determineAuthType(hostConfig) {
1357
+ if (hostConfig.authType) {
1358
+ return hostConfig.authType;
1359
+ }
1360
+ if (hostConfig.apiKey) {
1361
+ return "apikey";
1362
+ }
1363
+ if (hostConfig.accessCode) {
1364
+ return "anonymous";
1365
+ }
1366
+ if (hostConfig.clientId) {
1367
+ return "oauth2";
1368
+ }
1369
+ if (hostConfig.webIntegrationId) {
1370
+ return "cookie";
1371
+ }
1372
+ if (hostConfig.reference) {
1373
+ return "reference";
1374
+ }
1375
+ if (await isWindows(hostConfig)) {
1376
+ return "windowscookie";
1377
+ }
1378
+ return "cookie";
1379
+ }
1380
+
1381
+ // src/auth/auth-errors.ts
1382
+ var InvalidHostConfigError = class extends Error {
1383
+ constructor(message) {
1384
+ super(`Invalid host config: ${message}`);
1385
+ this.name = "InvalidHostConfigError";
1386
+ }
1387
+ };
1388
+ var UnexpectedAuthTypeError = class extends Error {
1389
+ constructor(...expectedAuthTypes) {
1390
+ const ors = expectedAuthTypes.map((item, index) => index === 0 ? `"${item}"` : `or "${item}"`).join(" ");
1391
+ super(`HostConfig is not properly configured. authType is expected to be ${ors}`);
1392
+ this.name = "UnexpectedAuthTypeError";
1393
+ }
1394
+ };
1395
+ var InvalidAuthTypeError = class extends Error {
1396
+ constructor(authType) {
1397
+ const validAuthModules = getRegisteredAuthModules();
1398
+ super(
1399
+ `Not a valid auth type: ${authType}, valid auth types are; '${validAuthModules.filter((name) => name.toLowerCase() !== "qmfeembedframerauthmodule").join("', '")}'`
1400
+ );
1401
+ this.name = "InvalidAuthTypeError";
1402
+ }
1403
+ };
1404
+ function errorToString({ title, detail, code, status }) {
1405
+ if (detail) {
1406
+ return `${title} - ${detail} (Status: ${status}, Code: ${code})`;
1407
+ }
1408
+ return `${title} (Status: ${status}, Code: ${code})`;
1409
+ }
1410
+ var AuthorizationError = class extends Error {
1411
+ errors;
1412
+ constructor(errors) {
1413
+ if (typeof errors !== "object") {
1414
+ super("Unknown error");
1415
+ return;
1213
1416
  }
1214
- };
1215
- }
1216
- function handleAuthenticationError3() {
1217
- return Promise.resolve({});
1218
- }
1219
- var apikey_default = {
1220
- getRestCallAuthParams: getRestCallAuthParams3,
1221
- getWebSocketAuthParams: getWebSocketAuthParams3,
1222
- handleAuthenticationError: handleAuthenticationError3,
1223
- validateHostConfig: (hostConfig) => internalValidateHostConfig(hostConfig, { requiredProps: ["apiKey"], optionalProps: [] })
1417
+ const errorArray = Array.isArray(errors) ? errors : [errors];
1418
+ super(errorArray.map(errorToString).join(", "));
1419
+ this.errors = errorArray;
1420
+ }
1224
1421
  };
1225
1422
 
1226
- // src/http/http-functions.ts
1227
- var QLIK_CSRF_TOKEN = "qlik-csrf-token";
1228
- function clearCsrfToken(hostConfig) {
1229
- const locationUrl = toValidLocationUrl(hostConfig);
1230
- delete csrfTokens[locationUrl];
1231
- }
1232
- async function getCsrfToken(hostConfig, noCache) {
1233
- const locationUrl = toValidLocationUrl(hostConfig);
1234
- let pathTemplate;
1235
- if (await isWindows(hostConfig)) {
1236
- pathTemplate = "/qps/csrftoken";
1237
- } else {
1238
- pathTemplate = "/api/v1/csrf-token";
1423
+ // src/auth/internal/host-config-functions.ts
1424
+ function removeDefaults(hostConfig) {
1425
+ const cleanedHostConfig = cleanFalsyValues(hostConfig) || {};
1426
+ if (cleanedHostConfig.host) {
1427
+ cleanedHostConfig.host = toValidLocationUrl(cleanedHostConfig);
1239
1428
  }
1240
- const fetchCsrfToken = async () => {
1241
- try {
1242
- const res = await invokeFetch("csrf-token", {
1243
- method: "get",
1244
- pathTemplate,
1245
- options: {
1246
- hostConfig,
1247
- noCache: true
1248
- }
1249
- });
1250
- const csrfToken = res.headers.get(QLIK_CSRF_TOKEN);
1251
- if (!csrfToken) {
1252
- return "";
1253
- }
1254
- return csrfToken;
1255
- } catch (e) {
1256
- const error = e;
1257
- if (error.status === 404) {
1258
- return "";
1259
- }
1260
- throw e;
1429
+ if (isBrowser()) {
1430
+ if (toValidLocationUrl(cleanedHostConfig) === window.location.origin) {
1431
+ delete cleanedHostConfig.host;
1261
1432
  }
1262
- };
1263
- if (noCache) {
1264
- csrfTokens[locationUrl] = fetchCsrfToken();
1265
- return csrfTokens[locationUrl];
1266
1433
  }
1267
- csrfTokens[locationUrl] = csrfTokens[locationUrl] || fetchCsrfToken();
1268
- return csrfTokens[locationUrl];
1434
+ if (cleanedHostConfig.authType && authTypesThatCanBeOmitted.includes(cleanedHostConfig.authType)) {
1435
+ delete cleanedHostConfig.authType;
1436
+ }
1437
+ return cleanedHostConfig;
1269
1438
  }
1270
- var csrfTokens = {};
1271
-
1272
- // src/auth/internal/default-auth-modules/cookie.ts
1273
- function isModifyingVerb(verb) {
1274
- return !(verb === "get" || verb === "GET");
1439
+ function globalReplacer(key, value) {
1440
+ if (typeof value === "function") {
1441
+ return void 0;
1442
+ }
1443
+ return value;
1275
1444
  }
1276
- async function getRestCallAuthParams4({
1277
- hostConfig,
1278
- method
1279
- }) {
1280
- const headers = {};
1281
- if (isModifyingVerb(method)) {
1282
- headers["qlik-csrf-token"] = await getCsrfToken(hostConfig);
1445
+ function serializeHostConfig(hostConfig) {
1446
+ const hostConfigToUse = removeDefaults(withResolvedHostConfig(hostConfig));
1447
+ const sorted = sortKeys(hostConfigToUse);
1448
+ return JSON.stringify(sorted, globalReplacer);
1449
+ }
1450
+ var registeredHostConfigs = /* @__PURE__ */ new Map();
1451
+ function registerHostConfig(name, hostConfig) {
1452
+ if (hostConfig?.reference) {
1453
+ throw new InvalidHostConfigError("Cannot register a host config with a reference");
1283
1454
  }
1284
- if (hostConfig.webIntegrationId) {
1285
- headers["qlik-web-integration-id"] = hostConfig.webIntegrationId;
1455
+ if (registeredHostConfigs.has(name)) {
1456
+ console.warn(`registerHostConfig: Host config with name "${name}" is already registered. Overwriting.`);
1286
1457
  }
1287
- return { headers, queryParams: {}, credentials: getCredentialsForCookieAuth(hostConfig) };
1458
+ registeredHostConfigs.set(name, hostConfig);
1288
1459
  }
1289
- async function getWebSocketAuthParams4({
1290
- hostConfig
1291
- }) {
1292
- const params = {
1293
- // Bypass the cache to get one rest call out the door that can catch a 401 since the websocket only returns a general error
1294
- "qlik-csrf-token": await getCsrfToken(hostConfig, true)
1295
- };
1296
- if (hostConfig.webIntegrationId) {
1297
- params["qlik-web-integration-id"] = hostConfig.webIntegrationId;
1460
+ function unregisterHostConfig(name) {
1461
+ if (registeredHostConfigs.has(name)) {
1462
+ registeredHostConfigs.delete(name);
1463
+ } else {
1464
+ console.warn(`unregisterHostConfig: Host config with name "${name}" not found.`);
1298
1465
  }
1299
- return { queryParams: params };
1300
1466
  }
1301
- async function handleAuthenticationError4({
1302
- hostConfig,
1303
- status
1304
- }) {
1305
- clearCsrfToken(hostConfig);
1306
- if (status === 403) {
1307
- return {
1308
- preventDefault: false,
1309
- retry: true
1310
- };
1311
- }
1312
- const webIntegrationParam = hostConfig.webIntegrationId ? `qlik-web-integration-id=${hostConfig?.webIntegrationId}&` : "";
1313
- const locationUrl = toValidLocationUrl(hostConfig);
1314
- if (hostConfig.authRedirectUserConfirmation) {
1315
- await hostConfig.authRedirectUserConfirmation();
1316
- }
1317
- globalThis.location.replace(
1318
- `${locationUrl}/login?${webIntegrationParam}returnto=${encodeURIComponent(globalThis.location.href)}`
1319
- );
1320
- return {
1321
- preventDefault: true
1322
- };
1467
+ function getRegisteredHostConfig(name) {
1468
+ return registeredHostConfigs.get(name);
1469
+ }
1470
+ function setDefaultHostConfig(hostConfig) {
1471
+ registerHostConfig("default", hostConfig || {});
1472
+ }
1473
+ function getDefaultHostConfig() {
1474
+ return getRegisteredHostConfig("default") || {};
1323
1475
  }
1324
- var cookie_default = {
1325
- getRestCallAuthParams: getRestCallAuthParams4,
1326
- getWebSocketAuthParams: getWebSocketAuthParams4,
1327
- handleAuthenticationError: handleAuthenticationError4,
1328
- validateHostConfig: (hostConfig) => internalValidateHostConfig(hostConfig, {
1329
- requiredProps: [],
1330
- optionalProps: ["webIntegrationId", "crossSiteCookies", "anonymousMode"]
1331
- })
1332
- };
1333
1476
 
1334
- // src/auth/internal/default-auth-modules/none.ts
1335
- function getRestCallAuthParams5() {
1336
- return Promise.resolve({ headers: {}, queryParams: {}, credentials: "same-origin" });
1477
+ // src/auth/auth-functions.ts
1478
+ globalThis.loggingOut = false;
1479
+ var lastErrorMessage = "";
1480
+ function logToConsole({ message }) {
1481
+ if (message !== lastErrorMessage) {
1482
+ lastErrorMessage = message;
1483
+ console.error(message);
1484
+ }
1337
1485
  }
1338
- function getWebSocketAuthParams5() {
1339
- return Promise.resolve({ queryParams: {} });
1486
+ function determineAuthType2(hostConfig) {
1487
+ return determineAuthType(hostConfig);
1340
1488
  }
1341
- function handleAuthenticationError5() {
1342
- return Promise.resolve({});
1489
+ function isHostCrossOrigin(hostConfig) {
1490
+ if (!globalThis.location?.origin) {
1491
+ return true;
1492
+ }
1493
+ const hostConfigToUse = withResolvedHostConfig(hostConfig);
1494
+ if (Object.keys(hostConfigToUse).length === 0) {
1495
+ return false;
1496
+ }
1497
+ try {
1498
+ const locationUrl = new URL(toValidLocationUrl(hostConfigToUse));
1499
+ return locationUrl.origin !== globalThis.location.origin;
1500
+ } catch {
1501
+ }
1502
+ return false;
1343
1503
  }
1344
- var none_default = {
1345
- getRestCallAuthParams: getRestCallAuthParams5,
1346
- getWebSocketAuthParams: getWebSocketAuthParams5,
1347
- handleAuthenticationError: handleAuthenticationError5,
1348
- validateHostConfig: (hostConfig) => internalValidateHostConfig(hostConfig, { requiredProps: [], optionalProps: [] })
1349
- };
1350
-
1351
- // src/auth/internal/default-auth-modules/oauth/callback.ts
1352
- function handleOAuthCallback() {
1353
- const urlParams = new URLSearchParams(globalThis.location.search);
1354
- const callbackCode = urlParams.get("code") || void 0;
1355
- const callbackState = urlParams.get("state") || void 0;
1356
- if (urlParams.get("error")) {
1357
- const element = document.createElement("pre");
1358
- element.innerText = `<code>${JSON.stringify({
1359
- error: urlParams.get("error"),
1360
- error_code: urlParams.get("error_code"),
1361
- error_description: urlParams.get("error_description"),
1362
- error_detail: urlParams.get("error_detail"),
1363
- error_uri: urlParams.get("error_uri")
1364
- })}</code>`;
1365
- document.body.prepend(element);
1504
+ async function isWindows(hostConfig) {
1505
+ const hostConfigToUse = withResolvedHostConfig(hostConfig);
1506
+ if (typeof hostConfigToUse.forceIsWindows === "boolean") {
1507
+ return hostConfigToUse.forceIsWindows;
1366
1508
  }
1367
- const topic = loadAndDeleteFromSessionStorage("", "client-in-progress");
1368
- if (topic && callbackCode && callbackState) {
1369
- const stateFromLocalStorage = loadAndDeleteFromSessionStorage(topic, "state");
1370
- const finalRedirectUri = loadAndDeleteFromSessionStorage(topic, "href");
1371
- if (stateFromLocalStorage && stateFromLocalStorage === callbackState && finalRedirectUri) {
1372
- saveInSessionStorage(topic, "code", callbackCode);
1373
- if (finalRedirectUri !== globalThis.location.href) {
1374
- globalThis.location.replace(finalRedirectUri);
1375
- }
1376
- }
1509
+ if (hostConfigToUse.authType === "cookie") {
1510
+ return false;
1511
+ }
1512
+ if (hostConfigToUse.authType === "windowscookie") {
1513
+ return true;
1377
1514
  }
1515
+ return (await getPlatform({ hostConfig })).isWindows;
1378
1516
  }
1379
-
1380
- // src/auth/internal/default-auth-modules/oauth.ts
1381
- if (isBrowser()) {
1382
- handleOAuthCallback();
1517
+ function toValidLocationUrl(hostConfig) {
1518
+ const url = withResolvedHostConfig(hostConfig)?.host?.trim();
1519
+ let locationUrl;
1520
+ if (!url) {
1521
+ locationUrl = "";
1522
+ } else if (url.toLowerCase().startsWith("https://") || url.toLowerCase().startsWith("http://")) {
1523
+ locationUrl = url;
1524
+ } else {
1525
+ locationUrl = `https://${url}`;
1526
+ }
1527
+ while (locationUrl[locationUrl.length - 1] === "/") {
1528
+ locationUrl = locationUrl.substring(0, locationUrl.length - 1);
1529
+ }
1530
+ return locationUrl;
1383
1531
  }
1384
- async function handlePotentialAuthenticationErrorAndRetry2(hostConfig, fn) {
1532
+ function toValidWebsocketLocationUrl(hostConfig) {
1533
+ const url = withResolvedHostConfig(hostConfig)?.host;
1534
+ let locationUrl;
1535
+ if (!url) {
1536
+ locationUrl = globalThis.location.origin;
1537
+ } else if (url.toLowerCase().startsWith("https://") || url.toLowerCase().startsWith("http://")) {
1538
+ locationUrl = url;
1539
+ } else {
1540
+ locationUrl = `https://${url}`;
1541
+ }
1542
+ while (locationUrl[locationUrl.length - 1] === "/") {
1543
+ locationUrl = locationUrl.substring(0, locationUrl.length - 1);
1544
+ }
1545
+ return locationUrl.replace(leadingHttp, "ws");
1546
+ }
1547
+ async function getWebSocketAuthParams8(props) {
1548
+ const hostConfigToUse = withResolvedHostConfig(props.hostConfig);
1385
1549
  try {
1386
- return await fn();
1550
+ const authModule = await getAuthModule(hostConfigToUse);
1551
+ return await authModule.getWebSocketAuthParams({
1552
+ ...props,
1553
+ hostConfig: hostConfigToUse
1554
+ });
1387
1555
  } catch (err) {
1388
- const { retry } = await handleAuthenticationError6({
1389
- hostConfig,
1390
- canRetry: true
1556
+ (hostConfigToUse.onAuthFailed || logToConsole)(normalizeAuthModuleError(err));
1557
+ throw err;
1558
+ }
1559
+ }
1560
+ async function getWebResourceAuthParams3(props) {
1561
+ const hostConfigToUse = withResolvedHostConfig(props.hostConfig);
1562
+ try {
1563
+ const authModule = await getAuthModule(hostConfigToUse);
1564
+ return await authModule.getWebResourceAuthParams?.({
1565
+ ...props,
1566
+ hostConfig: hostConfigToUse
1567
+ }) || { queryParams: {} };
1568
+ } catch (err) {
1569
+ (hostConfigToUse.onAuthFailed || logToConsole)(normalizeAuthModuleError(err));
1570
+ throw err;
1571
+ }
1572
+ }
1573
+ async function handleAuthenticationError8(props) {
1574
+ const hostConfigToUse = withResolvedHostConfig(props.hostConfig);
1575
+ const authModule = await getAuthModule(hostConfigToUse);
1576
+ const result2 = await authModule.handleAuthenticationError({
1577
+ ...props,
1578
+ hostConfig: hostConfigToUse
1579
+ });
1580
+ const willRetry = props.canRetry && result2.retry;
1581
+ const willHangUntilANewPageIsLoaded = result2.preventDefault;
1582
+ if (!willRetry && !willHangUntilANewPageIsLoaded) {
1583
+ const { status, errorBody } = props;
1584
+ (hostConfigToUse.onAuthFailed || logToConsole)(normalizeInbandAuthError({ status, errorBody }));
1585
+ }
1586
+ return result2;
1587
+ }
1588
+ async function getRestCallAuthParams8(props) {
1589
+ const hostConfigToUse = withResolvedHostConfig(props.hostConfig);
1590
+ try {
1591
+ const authModule = await getAuthModule(hostConfigToUse);
1592
+ return await authModule.getRestCallAuthParams({
1593
+ ...props,
1594
+ hostConfig: hostConfigToUse
1391
1595
  });
1392
- if (retry) {
1393
- return fn();
1394
- }
1596
+ } catch (err) {
1597
+ (hostConfigToUse.onAuthFailed || logToConsole)(normalizeAuthModuleError(err));
1395
1598
  throw err;
1396
1599
  }
1397
1600
  }
1398
- async function getRestCallAuthParams6({
1399
- hostConfig
1400
- }) {
1401
- return {
1402
- headers: {
1403
- Authorization: `Bearer ${await getOAuthAccessToken(hostConfig)}`
1404
- },
1405
- queryParams: {},
1406
- credentials: "omit"
1407
- };
1601
+ function registerAuthModule2(name, authModule) {
1602
+ registerAuthModule(name, authModule);
1408
1603
  }
1409
- async function getWebSocketAuthParams6({
1410
- hostConfig
1411
- }) {
1412
- const websocketAccessToken = await handlePotentialAuthenticationErrorAndRetry2(hostConfig, async () => {
1413
- const accessToken = await getOAuthAccessToken(hostConfig);
1414
- return exchangeAccessTokenForTemporaryToken(hostConfig, accessToken, "websocket");
1415
- });
1416
- return {
1417
- queryParams: {
1418
- accessToken: websocketAccessToken
1419
- }
1420
- };
1604
+ function setDefaultHostConfig2(hostConfig) {
1605
+ setDefaultHostConfig(hostConfig);
1421
1606
  }
1422
- async function getWebResourceAuthParams3({
1423
- hostConfig
1424
- }) {
1425
- const webResourceAccessToken = await handlePotentialAuthenticationErrorAndRetry2(hostConfig, async () => {
1426
- const accessToken = await getOAuthAccessToken(hostConfig);
1427
- return exchangeAccessTokenForTemporaryToken(hostConfig, accessToken, "webresource");
1428
- });
1429
- return {
1430
- queryParams: {
1431
- accessToken: webResourceAccessToken
1432
- }
1433
- };
1607
+ function registerHostConfig2(name, hostConfig) {
1608
+ registerHostConfig(name, hostConfig);
1434
1609
  }
1435
- async function handleAuthenticationError6({
1436
- hostConfig
1437
- }) {
1438
- if (hostConfig.getAccessToken) {
1439
- clearStoredOauthTokens(hostConfig);
1440
- return {
1441
- preventDefault: false,
1442
- retry: true
1443
- };
1444
- }
1445
- if (isBrowser()) {
1446
- if (hostConfig.performInteractiveLogin) {
1447
- clearStoredOauthTokens(hostConfig);
1448
- return {
1449
- retry: true
1450
- };
1610
+ function unregisterHostConfig2(name) {
1611
+ unregisterHostConfig(name);
1612
+ }
1613
+ function serializeHostConfig2(hostConfig) {
1614
+ return serializeHostConfig(hostConfig);
1615
+ }
1616
+ function checkForCrossDomainRequest(hostConfig) {
1617
+ const hostConfigToUse = withResolvedHostConfig(hostConfig);
1618
+ if (isHostCrossOrigin(hostConfigToUse)) {
1619
+ if (Object.keys(hostConfigToUse).length === 0) {
1620
+ throw new InvalidHostConfigError("a host config must be provided when making a cross domain request");
1451
1621
  }
1452
- if (hostConfig.authRedirectUserConfirmation) {
1453
- await hostConfig.authRedirectUserConfirmation();
1622
+ if (!hostConfigToUse.host) {
1623
+ throw new InvalidHostConfigError(
1624
+ "A 'host' property must be set in host config when making a cross domain request"
1625
+ );
1454
1626
  }
1455
- startFullPageLoginFlow(hostConfig);
1456
- return {
1457
- preventDefault: true
1458
- };
1459
1627
  }
1460
- await refreshAccessToken(hostConfig);
1461
- return {
1462
- preventDefault: false,
1463
- retry: true
1464
- };
1465
- }
1466
- var oauth_default = {
1467
- getRestCallAuthParams: getRestCallAuthParams6,
1468
- getWebSocketAuthParams: getWebSocketAuthParams6,
1469
- getWebResourceAuthParams: getWebResourceAuthParams3,
1470
- handleAuthenticationError: handleAuthenticationError6,
1471
- validateHostConfig: (hostConfig) => internalValidateHostConfig(hostConfig, {
1472
- requiredProps: ["clientId"],
1473
- optionalProps: [
1474
- "clientSecret",
1475
- "redirectUri",
1476
- "accessTokenStorage",
1477
- "scope",
1478
- "subject",
1479
- "userId",
1480
- "noCache",
1481
- "getAccessToken",
1482
- "performInteractiveLogin"
1483
- ]
1484
- })
1485
- };
1486
-
1487
- // src/auth/internal/default-auth-modules/reference.ts
1488
- function getRestCallAuthParams7() {
1489
- throw new Error("getRestCallAuthParams should never be called for reference auth module");
1490
- }
1491
- function getWebSocketAuthParams7() {
1492
- throw new Error("getWebSocketAuthParams should never be called for reference auth module");
1493
- }
1494
- function handleAuthenticationError7() {
1495
- throw new Error("handleAuthenticationError should never be called for reference auth module");
1496
1628
  }
1497
- var reference_default = {
1498
- getRestCallAuthParams: getRestCallAuthParams7,
1499
- getWebSocketAuthParams: getWebSocketAuthParams7,
1500
- handleAuthenticationError: handleAuthenticationError7,
1501
- validateHostConfig: (hostConfig) => internalValidateHostConfig(hostConfig, { requiredProps: ["reference"], optionalProps: [] })
1629
+ var logout = () => {
1630
+ globalThis.loggingOut = true;
1631
+ globalThis.location.href = "/logout";
1502
1632
  };
1503
-
1504
- // src/auth/internal/default-auth-modules/windows-cookie/xrf-keys.ts
1505
- var xrfKeys = {};
1506
- function createXrfKey() {
1507
- let result2 = "";
1508
- for (let i = 0; i < 16; i += 1) {
1509
- const j = Math.floor(Math.random() * 62);
1510
- if (j < 10) {
1511
- result2 += j;
1512
- } else if (j > 9 && j < 36) {
1513
- result2 += String.fromCharCode(j + 55);
1514
- } else {
1515
- result2 += String.fromCharCode(j + 61);
1516
- }
1633
+ var leadingHttp = /^http/;
1634
+ function normalizeInbandAuthError({ errorBody, status }) {
1635
+ const authError = errorBody;
1636
+ if (typeof authError?.errors === "object") {
1637
+ const err = new AuthorizationError(authError?.errors);
1638
+ return { message: err.message };
1517
1639
  }
1518
- return result2;
1519
- }
1520
- function getXrfKey(hostConfig) {
1521
- const locationUrl = toValidLocationUrl(hostConfig);
1522
- xrfKeys[locationUrl] = xrfKeys[locationUrl] || createXrfKey();
1523
- return xrfKeys[locationUrl];
1524
- }
1525
-
1526
- // src/auth/internal/default-auth-modules/windows-cookie.ts
1527
- async function getRestCallAuthParams8({
1528
- hostConfig
1529
- }) {
1530
- return {
1531
- headers: {
1532
- "X-Qlik-XrfKey": getXrfKey(hostConfig)
1533
- },
1534
- queryParams: {
1535
- xrfkey: getXrfKey(hostConfig)
1536
- },
1537
- credentials: getCredentialsForCookieAuth(hostConfig)
1538
- };
1640
+ return { message: `HTTP ${status}` };
1539
1641
  }
1540
- async function getWebSocketAuthParams8({
1541
- hostConfig
1542
- }) {
1543
- return {
1544
- queryParams: {
1545
- xrfkey: getXrfKey(hostConfig),
1546
- "qlik-csrf-token": await getCsrfToken(hostConfig, true)
1547
- }
1548
- };
1642
+ function normalizeAuthModuleError(err) {
1643
+ return { message: err.message || "Unknown error" };
1549
1644
  }
1550
- async function handleAuthenticationError8({
1551
- hostConfig
1552
- }) {
1553
- if (hostConfig.loginUri) {
1554
- if (hostConfig.authRedirectUserConfirmation) {
1555
- await hostConfig.authRedirectUserConfirmation();
1645
+ function withResolvedHostConfig(hostConfig) {
1646
+ if (hostConfig?.reference) {
1647
+ const refConfig = getRegisteredHostConfig(hostConfig.reference);
1648
+ if (!refConfig) {
1649
+ throw new InvalidHostConfigError(
1650
+ `Host config with name "${hostConfig.reference}" not found.`
1651
+ );
1556
1652
  }
1557
- globalThis.location.replace(
1558
- hostConfig.loginUri.replace("{location}", encodeURIComponent(globalThis.location.href))
1559
- );
1560
- return {
1561
- preventDefault: true
1562
- };
1653
+ return refConfig;
1563
1654
  }
1564
- return {
1565
- // Do nothing, just let the error be thrown to calling code
1566
- };
1567
- }
1568
- var windows_cookie_default = {
1569
- getRestCallAuthParams: getRestCallAuthParams8,
1570
- getWebSocketAuthParams: getWebSocketAuthParams8,
1571
- handleAuthenticationError: handleAuthenticationError8,
1572
- validateHostConfig: (hostConfig) => internalValidateHostConfig(hostConfig, {
1573
- requiredProps: [],
1574
- optionalProps: ["loginUri", "crossSiteCookies"]
1575
- })
1576
- };
1577
-
1578
- // src/auth/auth.ts
1579
- globalThis.loggingOut = false;
1580
- var authModulesRegistered = false;
1581
- function registerDefaultAuthModules() {
1582
- if (!authModulesRegistered) {
1583
- registerAuthModule("apikey", apikey_default);
1584
- registerAuthModule("cookie", cookie_default);
1585
- registerAuthModule("none", none_default);
1586
- registerAuthModule("oauth2", oauth_default);
1587
- registerAuthModule("anonymous", anonymous_default);
1588
- registerAuthModule("windowscookie", windows_cookie_default);
1589
- registerAuthModule("reference", reference_default);
1590
- authModulesRegistered = true;
1655
+ if (hostConfig && Object.keys(hostConfig).length > 0) {
1656
+ return hostConfig;
1591
1657
  }
1658
+ return getDefaultHostConfig();
1659
+ }
1660
+ function getDefaultHostConfig2() {
1661
+ return getDefaultHostConfig();
1592
1662
  }
1593
- registerDefaultAuthModules();
1594
- var auth = {
1595
- logout,
1596
- registerAuthModule,
1597
- setDefaultHostConfig,
1598
- registerHostConfig,
1599
- unregisterHostConfig,
1600
- getRestCallAuthParams,
1601
- getWebSocketAuthParams,
1602
- getWebResourceAuthParams,
1603
- handleAuthenticationError,
1604
- toValidLocationUrl,
1605
- toValidWebsocketLocationUrl,
1606
- isWindows,
1607
- isHostCrossOrigin,
1608
- determineAuthType,
1609
- serializeHostConfig
1610
- };
1611
- var auth_default = auth;
1612
1663
 
1613
1664
  // src/invoke-fetch/internal/invoke-fetch-helpers.ts
1614
1665
  function encodeQueryParams(query) {
@@ -1981,14 +2032,14 @@ async function getInvokeFetchUrlParams({
1981
2032
  headers: authHeaders,
1982
2033
  queryParams: authQueryParams,
1983
2034
  credentials
1984
- } = await getRestCallAuthParams({
2035
+ } = await getRestCallAuthParams8({
1985
2036
  hostConfig: options?.hostConfig,
1986
2037
  method
1987
2038
  });
1988
2039
  const url = locationUrl + applyPathVariables(pathTemplate, pathVariables);
1989
2040
  const queryString = encodeQueryParams({ ...query, ...authQueryParams });
1990
2041
  const completeUrl = toCompleteUrl(url, queryString);
1991
- const cacheKey = toCacheKey(url, queryString, serializeHostConfig(options?.hostConfig), options?.headers);
2042
+ const cacheKey = toCacheKey(url, queryString, serializeHostConfig2(options?.hostConfig), options?.headers);
1992
2043
  return { completeUrl, cacheKey, authHeaders, credentials };
1993
2044
  }
1994
2045
  function invokeFetchWithUrl(api, props) {
@@ -2067,7 +2118,7 @@ function invokeFetchWithUrlAndRetry(api, {
2067
2118
  return cloneResultPromise(resultPromiseAfterCacheClearing);
2068
2119
  }
2069
2120
  function addPagingFunctions(api, value, method, body, options, authHeaders, credentials) {
2070
- const serializedHostConfig = serializeHostConfig(options?.hostConfig);
2121
+ const serializedHostConfig = serializeHostConfig2(options?.hostConfig);
2071
2122
  return value.then((resp) => {
2072
2123
  const dataWithPotentialLinks = resp.data;
2073
2124
  if (!dataWithPotentialLinks) {
@@ -2114,7 +2165,7 @@ async function interceptAuthenticationErrors(hostConfig, resultPromise, performR
2114
2165
  if (globalThis.loggingOut) {
2115
2166
  return neverResolvingPromise();
2116
2167
  }
2117
- const { retry, preventDefault } = await handleAuthenticationError({
2168
+ const { retry, preventDefault } = await handleAuthenticationError8({
2118
2169
  hostConfig,
2119
2170
  status: err.status,
2120
2171
  headers: err.headers,
@@ -2166,50 +2217,6 @@ async function download(blob, filename) {
2166
2217
  }
2167
2218
  }
2168
2219
 
2169
- // src/invoke-fetch/invoke-fetch-error.ts
2170
- var InvokeFetchError = class extends Error {
2171
- status;
2172
- headers;
2173
- data;
2174
- constructor(errorMessage, status, headers, data) {
2175
- super(errorMessage);
2176
- this.status = status;
2177
- this.headers = headers;
2178
- this.data = data;
2179
- this.stack = cleanStack(this.stack);
2180
- }
2181
- };
2182
- var EncodingError = class extends Error {
2183
- contentType;
2184
- data;
2185
- constructor(errorMessage, contentType, data) {
2186
- super(errorMessage);
2187
- this.contentType = contentType;
2188
- this.data = data;
2189
- this.stack = cleanStack(this.stack);
2190
- }
2191
- };
2192
- var regex = /^.+\/qmfe-api(?:\.js)?:(\d+)(?::\d+)?$/gim;
2193
- var isFromQmfeApi = (line) => {
2194
- const matches = line.match(regex);
2195
- return Boolean(matches && matches.length > 0);
2196
- };
2197
- function cleanStack(stack) {
2198
- if (!stack) {
2199
- return stack;
2200
- }
2201
- const newStack = [];
2202
- const lines = stack.split("\n");
2203
- lines.reverse();
2204
- for (const line of lines) {
2205
- if (isFromQmfeApi(line)) {
2206
- break;
2207
- }
2208
- newStack.unshift(line);
2209
- }
2210
- return newStack.join("\n");
2211
- }
2212
-
2213
2220
  // src/invoke-fetch/invoke-fetch-functions.ts
2214
2221
  var defaultUserAgent = "qmfe-api/latest";
2215
2222
  async function invokeFetch(api, props, interceptors) {
@@ -2301,44 +2308,33 @@ async function parseFetchResponse(fetchResponse, url) {
2301
2308
  return invokeFetchResponse;
2302
2309
  }
2303
2310
 
2304
- // src/invoke-fetch/invoke-fetch.ts
2305
- var invokeFetchExp = {
2306
- invokeFetch,
2307
- clearApiCache,
2308
- parseFetchResponse
2309
- };
2310
- var invoke_fetch_default = invokeFetchExp;
2311
-
2312
2311
  export {
2313
2312
  getPlatform,
2313
+ generateRandomString,
2314
+ exposeInternalApiOnWindow,
2315
+ InvokeFetchError,
2316
+ EncodingError,
2317
+ invokeFetch,
2318
+ clearApiCache,
2319
+ parseFetchResponse,
2314
2320
  InvalidHostConfigError,
2315
2321
  UnexpectedAuthTypeError,
2316
2322
  InvalidAuthTypeError,
2317
2323
  AuthorizationError,
2324
+ determineAuthType2 as determineAuthType,
2318
2325
  isHostCrossOrigin,
2319
2326
  isWindows,
2320
2327
  toValidLocationUrl,
2321
2328
  toValidWebsocketLocationUrl,
2322
- getWebSocketAuthParams,
2323
- getWebResourceAuthParams,
2324
- handleAuthenticationError,
2325
- getRestCallAuthParams,
2326
- getAccessToken,
2329
+ getWebSocketAuthParams8 as getWebSocketAuthParams,
2330
+ getWebResourceAuthParams3 as getWebResourceAuthParams,
2331
+ handleAuthenticationError8 as handleAuthenticationError,
2332
+ getRestCallAuthParams8 as getRestCallAuthParams,
2327
2333
  registerAuthModule2 as registerAuthModule,
2328
- setDefaultHostConfig,
2329
- registerHostConfig,
2330
- unregisterHostConfig,
2331
- serializeHostConfig,
2332
- determineAuthType,
2333
- checkForCrossDomainRequest,
2334
+ setDefaultHostConfig2 as setDefaultHostConfig,
2335
+ registerHostConfig2 as registerHostConfig,
2336
+ unregisterHostConfig2 as unregisterHostConfig,
2337
+ serializeHostConfig2 as serializeHostConfig,
2334
2338
  logout,
2335
- generateRandomString,
2336
- exposeInternalApiOnWindow,
2337
- InvokeFetchError,
2338
- EncodingError,
2339
- invokeFetch,
2340
- clearApiCache,
2341
- parseFetchResponse,
2342
- invoke_fetch_default,
2343
- auth_default
2339
+ getDefaultHostConfig2 as getDefaultHostConfig
2344
2340
  };