oidc-spa 4.13.0 → 4.13.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/OidcInitializationError.js +51 -32
  2. package/OidcInitializationError.js.map +1 -1
  3. package/backend.d.ts +0 -4
  4. package/backend.js +193 -109
  5. package/backend.js.map +1 -1
  6. package/mock/oidc.js +103 -57
  7. package/mock/oidc.js.map +1 -1
  8. package/mock/react.js +2 -2
  9. package/mock/react.js.map +1 -1
  10. package/oidc.js +944 -721
  11. package/oidc.js.map +1 -1
  12. package/package.json +1 -1
  13. package/react/react.js +135 -70
  14. package/react/react.js.map +1 -1
  15. package/src/backend.ts +0 -5
  16. package/tools/Deferred.js +35 -13
  17. package/tools/Deferred.js.map +1 -1
  18. package/tools/StatefulObservable.js +11 -11
  19. package/tools/StatefulObservable.js.map +1 -1
  20. package/tools/createIsUserActive.js +15 -15
  21. package/tools/createIsUserActive.js.map +1 -1
  22. package/tools/createObjectThatThrowsIfAccessed.js +61 -13
  23. package/tools/createObjectThatThrowsIfAccessed.js.map +1 -1
  24. package/tools/decodeJwt.js +1 -1
  25. package/tools/decodeJwt.js.map +1 -1
  26. package/tools/fnv1aHashToHex.js +2 -2
  27. package/tools/getDownlinkAndRtt.js +30 -8
  28. package/tools/getDownlinkAndRtt.js.map +1 -1
  29. package/tools/getPrUserInteraction.js +4 -4
  30. package/tools/getPrUserInteraction.js.map +1 -1
  31. package/tools/powerhooks/useGuaranteedMemo.js +29 -4
  32. package/tools/powerhooks/useGuaranteedMemo.js.map +1 -1
  33. package/tools/readExpirationTimeInJwt.js +3 -3
  34. package/tools/readExpirationTimeInJwt.js.map +1 -1
  35. package/tools/startCountdown.js +65 -17
  36. package/tools/startCountdown.js.map +1 -1
  37. package/tools/subscribeToUserInteraction.js +67 -18
  38. package/tools/subscribeToUserInteraction.js.map +1 -1
  39. package/tools/urlQueryParams.js +48 -29
  40. package/tools/urlQueryParams.js.map +1 -1
package/oidc.js CHANGED
@@ -1,744 +1,967 @@
1
1
  "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createOidc = createOidc;
4
- const oidc_client_ts_and_jwt_decode_1 = require("./vendor/frontend/oidc-client-ts-and-jwt-decode");
5
- const tsafe_1 = require("./vendor/frontend/tsafe");
6
- const readExpirationTimeInJwt_1 = require("./tools/readExpirationTimeInJwt");
7
- const tsafe_2 = require("./vendor/frontend/tsafe");
8
- const urlQueryParams_1 = require("./tools/urlQueryParams");
9
- const fnv1aHashToHex_1 = require("./tools/fnv1aHashToHex");
10
- const Deferred_1 = require("./tools/Deferred");
11
- const decodeJwt_1 = require("./tools/decodeJwt");
12
- const getDownlinkAndRtt_1 = require("./tools/getDownlinkAndRtt");
13
- const createIsUserActive_1 = require("./tools/createIsUserActive");
14
- const startCountdown_1 = require("./tools/startCountdown");
15
- const worker_timers_1 = require("./vendor/frontend/worker-timers");
16
- const OidcInitializationError_1 = require("./OidcInitializationError");
17
- const PARAMS_TO_RETRIEVE_FROM_SUCCESSFUL_LOGIN = ["code", "state", "session_state", "iss"];
18
- let $isUserActive = undefined;
19
- const prOidcByConfigHash = new Map();
20
- const URL_real = window.URL;
21
- /** @see: https://github.com/garronej/oidc-spa#option-1-usage-without-involving-the-ui-framework */
22
- async function createOidc(params) {
23
- const { issuerUri, clientId, clientSecret, scopes = ["profile"], transformUrlBeforeRedirect = url => url, extraQueryParams: extraQueryParamsOrGetter, publicUrl: publicUrl_params, decodedIdTokenSchema, __unsafe_ssoSessionIdleSeconds, autoLogoutParams = { "redirectTo": "current page" }, isAuthGloballyRequired = false, postLoginRedirectUrl } = params;
24
- const getExtraQueryParams = (() => {
25
- if (typeof extraQueryParamsOrGetter === "function") {
26
- return extraQueryParamsOrGetter;
27
- }
28
- if (extraQueryParamsOrGetter !== undefined) {
29
- return () => extraQueryParamsOrGetter;
30
- }
31
- return undefined;
32
- })();
33
- const publicUrl = (() => {
34
- if (publicUrl_params === undefined) {
35
- return undefined;
36
- }
37
- return (publicUrl_params.startsWith("http")
38
- ? publicUrl_params
39
- : `${window.location.origin}${publicUrl_params}`).replace(/\/$/, "");
40
- })();
41
- const configHash = (0, fnv1aHashToHex_1.fnv1aHashToHex)(`${issuerUri} ${clientId} ${clientSecret !== null && clientSecret !== void 0 ? clientSecret : ""} ${scopes.join(" ")}`);
42
- use_previous_instance: {
43
- const prOidc = prOidcByConfigHash.get(configHash);
44
- if (prOidc === undefined) {
45
- break use_previous_instance;
2
+ var __assign = (this && this.__assign) || function () {
3
+ __assign = Object.assign || function(t) {
4
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
5
+ s = arguments[i];
6
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7
+ t[p] = s[p];
46
8
  }
47
- console.warn([
48
- `oidc-spa has been instantiated more than once with the same configuration.`,
49
- `If you are in development mode with hot module replacement this is expected you can ignore this warning.`,
50
- `In production however this is something that should be addressed.`
51
- ].join(" "));
52
- return prOidc;
53
- }
54
- const dOidc = new Deferred_1.Deferred();
55
- prOidcByConfigHash.set(configHash, dOidc.pr);
56
- const silentSso = publicUrl === undefined
57
- ? {
58
- "hasDedicatedHtmlFile": false,
59
- "redirectUri": window.location.href
60
- }
61
- : {
62
- "hasDedicatedHtmlFile": true,
63
- "redirectUri": `${publicUrl}/silent-sso.html`
64
- };
65
- const SILENT_SSO_KEY = "oidcSpaSilentSso";
66
- const CONFIG_HASH_KEY = "configHash";
67
- silent_sso_polyfill: {
68
- if (!(0, urlQueryParams_1.retrieveQueryParamFromUrl)({
69
- "url": window.location.href,
70
- "name": SILENT_SSO_KEY
71
- }).wasPresent) {
72
- break silent_sso_polyfill;
73
- }
74
- {
75
- const result = (0, urlQueryParams_1.retrieveQueryParamFromUrl)({
76
- "url": window.location.href,
77
- "name": CONFIG_HASH_KEY
78
- });
79
- if (!result.wasPresent || result.value !== configHash) {
80
- break silent_sso_polyfill;
9
+ return t;
10
+ };
11
+ return __assign.apply(this, arguments);
12
+ };
13
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
14
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
15
+ return new (P || (P = Promise))(function (resolve, reject) {
16
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
17
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
18
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
19
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
20
+ });
21
+ };
22
+ var __generator = (this && this.__generator) || function (thisArg, body) {
23
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
24
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
25
+ function verb(n) { return function (v) { return step([n, v]); }; }
26
+ function step(op) {
27
+ if (f) throw new TypeError("Generator is already executing.");
28
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
29
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
30
+ if (y = 0, t) op = [op[0] & 2, t.value];
31
+ switch (op[0]) {
32
+ case 0: case 1: t = op; break;
33
+ case 4: _.label++; return { value: op[1], done: false };
34
+ case 5: _.label++; y = op[1]; op = [0]; continue;
35
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
36
+ default:
37
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
38
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
39
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
40
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
41
+ if (t[2]) _.ops.pop();
42
+ _.trys.pop(); continue;
81
43
  }
44
+ op = body.call(thisArg, _);
45
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
46
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
47
+ }
48
+ };
49
+ var __rest = (this && this.__rest) || function (s, e) {
50
+ var t = {};
51
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
52
+ t[p] = s[p];
53
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
54
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
55
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
56
+ t[p[i]] = s[p[i]];
82
57
  }
83
- if (silentSso.hasDedicatedHtmlFile) {
84
- // Here the user forget to create the silent-sso.html file or or the web server is not serving it correctly
85
- // we shouldn't fall back to the SPA page.
86
- // In this case we want to let the timeout of the parent expire to provide the correct error message.
87
- await new Promise(() => { });
88
- }
89
- parent.postMessage(location.href, location.origin);
90
- await new Promise(() => { });
58
+ return t;
59
+ };
60
+ var __read = (this && this.__read) || function (o, n) {
61
+ var m = typeof Symbol === "function" && o[Symbol.iterator];
62
+ if (!m) return o;
63
+ var i = m.call(o), r, ar = [], e;
64
+ try {
65
+ while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
91
66
  }
92
- const oidcClientTsUserManager = new oidc_client_ts_and_jwt_decode_1.UserManager({
93
- "authority": issuerUri,
94
- "client_id": clientId,
95
- "client_secret": clientSecret,
96
- "redirect_uri": "" /* provided when calling login */,
97
- "response_type": "code",
98
- "scope": Array.from(new Set(["openid", ...scopes])).join(" "),
99
- "automaticSilentRenew": false,
100
- "silent_redirect_uri": (() => {
101
- let { redirectUri } = silentSso;
102
- redirectUri = (0, urlQueryParams_1.addQueryParamToUrl)({
103
- "url": redirectUri,
104
- "name": CONFIG_HASH_KEY,
105
- "value": configHash
106
- }).newUrl;
107
- redirectUri = (0, urlQueryParams_1.addQueryParamToUrl)({
108
- "url": redirectUri,
109
- "name": SILENT_SSO_KEY,
110
- "value": "true"
111
- }).newUrl;
112
- return redirectUri;
113
- })()
114
- });
115
- let lastPublicRoute = undefined;
116
- // NOTE: To call only if not logged in.
117
- const startTrackingLastPublicRoute = () => {
118
- const realPushState = history.pushState.bind(history);
119
- history.pushState = function pushState(...args) {
120
- lastPublicRoute = window.location.href;
121
- return realPushState(...args);
122
- };
123
- };
124
- let hasLoginBeenCalled = false;
125
- const loginOrGoToAuthServer = async (params) => {
126
- const { extraQueryParams: extraQueryParams_fromLoginFn, redirectUrl, transformUrlBeforeRedirect: transformUrlBeforeRedirect_fromLoginFn = url => url, ...rest } = params;
127
- login_only: {
128
- if (rest.action !== "login") {
129
- break login_only;
130
- }
131
- if (hasLoginBeenCalled) {
132
- return new Promise(() => { });
133
- }
134
- hasLoginBeenCalled = true;
67
+ catch (error) { e = { error: error }; }
68
+ finally {
69
+ try {
70
+ if (r && !r.done && (m = i["return"])) m.call(i);
135
71
  }
136
- const { newUrl: redirect_uri } = (0, urlQueryParams_1.addQueryParamToUrl)({
137
- "url": (() => {
138
- if (redirectUrl === undefined) {
139
- return window.location.href;
140
- }
141
- return redirectUrl.startsWith("/")
142
- ? `${window.location.origin}${redirectUrl}`
143
- : redirectUrl;
144
- })(),
145
- "name": CONFIG_HASH_KEY,
146
- "value": configHash
147
- });
148
- // NOTE: This is for handling cases when user press the back button on the login pages.
149
- // When the app is hosted on https (so not in dev mode) the browser will restore the state of the app
150
- // instead of reloading the page.
151
- login_only: {
152
- if (rest.action !== "login") {
153
- break login_only;
154
- }
155
- const callback = () => {
156
- if (document.visibilityState === "visible") {
157
- document.removeEventListener("visibilitychange", callback);
158
- if (rest.doesCurrentHrefRequiresAuth) {
159
- if (lastPublicRoute !== undefined) {
160
- window.location.href = lastPublicRoute;
161
- }
162
- else {
163
- window.history.back();
164
- }
165
- }
166
- else {
167
- hasLoginBeenCalled = false;
168
- }
169
- }
170
- };
171
- document.addEventListener("visibilitychange", callback);
72
+ finally { if (e) throw e.error; }
73
+ }
74
+ return ar;
75
+ };
76
+ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
77
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
78
+ if (ar || !(i in from)) {
79
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
80
+ ar[i] = from[i];
172
81
  }
173
- //NOTE: We know there is a extraQueryParameter option but it doesn't allow
174
- // to control the encoding so we have to highjack global URL Class that is
175
- // used internally by oidc-client-ts. It's save to do so since this is the
176
- // last thing that will be done before the redirect.
177
- {
178
- const URL = (...args) => {
179
- const urlInstance = new URL_real(...args);
180
- return new Proxy(urlInstance, {
181
- "get": (target, prop) => {
182
- if (prop === "href") {
183
- let url = urlInstance.href;
184
- [
185
- [getExtraQueryParams === null || getExtraQueryParams === void 0 ? void 0 : getExtraQueryParams(), transformUrlBeforeRedirect],
186
- [
187
- extraQueryParams_fromLoginFn,
188
- transformUrlBeforeRedirect_fromLoginFn
189
- ]
190
- ].forEach(([extraQueryParams, transformUrlBeforeRedirect]) => {
191
- add_extra_query_params: {
192
- if (extraQueryParams === undefined) {
193
- break add_extra_query_params;
194
- }
195
- Object.entries(extraQueryParams).forEach(([name, value]) => (url = (0, urlQueryParams_1.addQueryParamToUrl)({
196
- url,
197
- name,
198
- value
199
- }).newUrl));
200
- }
201
- url = transformUrlBeforeRedirect(url);
202
- });
203
- Object.defineProperty(window, "URL", { "value": URL_real });
204
- return url;
205
- }
206
- //@ts-expect-error
207
- return target[prop];
208
- }
209
- });
210
- };
211
- Object.defineProperty(window, "URL", { "value": URL });
82
+ }
83
+ return to.concat(ar || Array.prototype.slice.call(from));
84
+ };
85
+ var __values = (this && this.__values) || function(o) {
86
+ var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
87
+ if (m) return m.call(o);
88
+ if (o && typeof o.length === "number") return {
89
+ next: function () {
90
+ if (o && i >= o.length) o = void 0;
91
+ return { value: o && o[i++], done: !o };
212
92
  }
213
- await oidcClientTsUserManager.signinRedirect({
214
- redirect_uri,
215
- // NOTE: This is for the behavior when the use presses the back button on the login pages.
216
- // This is what happens when the user gave up the login process.
217
- // We want to that to redirect to the last public page.
218
- "redirectMethod": (() => {
219
- switch (rest.action) {
220
- case "login":
221
- return rest.doesCurrentHrefRequiresAuth ? "replace" : "assign";
222
- case "go to auth server":
223
- return "assign";
224
- }
225
- })()
226
- });
227
- return new Promise(() => { });
228
93
  };
229
- const resultOfLoginProcess = await (async function getUser() {
230
- read_successful_login_query_params: {
231
- let url = window.location.href;
232
- {
233
- const result = (0, urlQueryParams_1.retrieveQueryParamFromUrl)({ "name": CONFIG_HASH_KEY, url });
234
- if (!result.wasPresent || result.value !== configHash) {
235
- break read_successful_login_query_params;
236
- }
237
- url = result.newUrl;
238
- }
239
- let loginSuccessUrl = "https://dummy.com";
240
- let missingMandatoryParams = [];
241
- for (const name of PARAMS_TO_RETRIEVE_FROM_SUCCESSFUL_LOGIN) {
242
- const result = (0, urlQueryParams_1.retrieveQueryParamFromUrl)({ name, url });
243
- if (!result.wasPresent) {
244
- if (name === "iss") {
245
- continue;
246
- }
247
- missingMandatoryParams.push(name);
248
- continue;
249
- }
250
- loginSuccessUrl = (0, urlQueryParams_1.addQueryParamToUrl)({
251
- "url": loginSuccessUrl,
252
- "name": name,
253
- "value": result.value
254
- }).newUrl;
255
- url = result.newUrl;
256
- }
257
- window.history.pushState(null, "", url);
258
- {
259
- const result = (0, urlQueryParams_1.retrieveQueryParamFromUrl)({ "name": "error", url });
260
- if (result.wasPresent) {
261
- throw new Error([
262
- "The OIDC server responded with an error passed as query parameter after the login process",
263
- `this error is: ${result.value}`
264
- ].join(" "));
265
- }
266
- }
267
- if (missingMandatoryParams.length !== 0) {
268
- throw new Error([
269
- "After the login process the following mandatory OIDC query parameters where missing:",
270
- missingMandatoryParams.join(", ")
271
- ].join(" "));
272
- }
273
- let oidcClientTsUser = undefined;
274
- try {
275
- oidcClientTsUser = await oidcClientTsUserManager.signinRedirectCallback(loginSuccessUrl);
276
- }
277
- catch (error) {
278
- (0, tsafe_2.assert)(error instanceof Error);
279
- if (error.message === "Failed to fetch") {
280
- // If it's a fetch error here we know that the web server is not down and the login was successful,
281
- // we just where redirected from the login pages.
282
- // This means it's likely a "Web origins" misconfiguration.
283
- throw new OidcInitializationError_1.OidcInitializationError({
284
- "type": "bad configuration",
285
- "likelyCause": {
286
- "type": "not in Web Origins",
287
- clientId
288
- }
289
- });
290
- }
291
- //NOTE: The user has likely pressed the back button just after logging in.
292
- //UPDATE: I don't remember how to reproduce this case and I don't know if it's still relevant.
293
- return undefined;
294
- }
295
- return {
296
- "loginScenario": "backFromLoginPages",
297
- oidcClientTsUser
298
- };
299
- }
300
- restore_from_session: {
301
- const oidcClientTsUser = await oidcClientTsUserManager.getUser();
302
- if (oidcClientTsUser === null) {
303
- break restore_from_session;
304
- }
305
- // The server might have restarted and the session might have been lost.
306
- try {
307
- await oidcClientTsUserManager.signinSilent();
308
- }
309
- catch (error) {
310
- (0, tsafe_2.assert)(error instanceof Error);
311
- if (error.message === "Failed to fetch") {
312
- // Here it could be web origins as well but it's less likely because
313
- // it would mean that there was once a valid configuration and it has been
314
- // changed to an invalid one before the token expired.
315
- // but the server is not necessarily down, the issuerUri could be wrong.
316
- // So the error that we return should be either "server down" if fetching the
317
- // well known configuration endpoint failed without returning any status code
318
- // or "bad configuration" if the endpoint returned a 404 or an other status code.
319
- throw new OidcInitializationError_1.OidcInitializationError({
320
- "type": "server down",
321
- issuerUri
322
- });
323
- }
324
- return undefined;
325
- }
326
- return {
327
- "loginScenario": "sessionStorageRestoration",
328
- oidcClientTsUser
329
- };
330
- }
331
- restore_from_http_only_cookie: {
332
- const dLoginSuccessUrl = new Deferred_1.Deferred();
333
- const timeoutDelayMs = (() => {
334
- const downlinkAndRtt = (0, getDownlinkAndRtt_1.getDownlinkAndRtt)();
335
- if (downlinkAndRtt === undefined) {
336
- return 5000;
337
- }
338
- const { downlink, rtt } = downlinkAndRtt;
339
- // Base delay is the minimum delay we're willing to tolerate
340
- const baseDelay = 3000;
341
- // Calculate dynamic delay based on RTT and downlink
342
- // Add 1 to downlink to avoid division by zero
343
- const dynamicDelay = rtt * 2.5 + 3000 / (downlink + 1);
344
- return Math.max(baseDelay, dynamicDelay);
345
- })();
346
- const timeout = (0, worker_timers_1.setTimeout)(async () => {
347
- let dedicatedSilentSsoHtmlFileCsp = undefined;
348
- silent_sso_html_unreachable: {
349
- if (!silentSso.hasDedicatedHtmlFile) {
350
- break silent_sso_html_unreachable;
351
- }
352
- const isSilentSsoHtmlReachable = await fetch(silentSso.redirectUri).then(async (response) => {
353
- dedicatedSilentSsoHtmlFileCsp =
354
- response.headers.get("Content-Security-Policy");
355
- const content = await response.text();
356
- return (content.length < 250 &&
357
- content.includes("parent.postMessage(location.href"));
358
- }, () => false);
359
- if (isSilentSsoHtmlReachable) {
360
- break silent_sso_html_unreachable;
361
- }
362
- dLoginSuccessUrl.reject(new OidcInitializationError_1.OidcInitializationError({
363
- "type": "bad configuration",
364
- "likelyCause": {
365
- "type": "silent-sso.html not reachable",
366
- "silentSsoHtmlUrl": silentSso.redirectUri
94
+ throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
95
+ };
96
+ Object.defineProperty(exports, "__esModule", { value: true });
97
+ exports.createOidc = createOidc;
98
+ var oidc_client_ts_and_jwt_decode_1 = require("./vendor/frontend/oidc-client-ts-and-jwt-decode");
99
+ var tsafe_1 = require("./vendor/frontend/tsafe");
100
+ var readExpirationTimeInJwt_1 = require("./tools/readExpirationTimeInJwt");
101
+ var tsafe_2 = require("./vendor/frontend/tsafe");
102
+ var urlQueryParams_1 = require("./tools/urlQueryParams");
103
+ var fnv1aHashToHex_1 = require("./tools/fnv1aHashToHex");
104
+ var Deferred_1 = require("./tools/Deferred");
105
+ var decodeJwt_1 = require("./tools/decodeJwt");
106
+ var getDownlinkAndRtt_1 = require("./tools/getDownlinkAndRtt");
107
+ var createIsUserActive_1 = require("./tools/createIsUserActive");
108
+ var startCountdown_1 = require("./tools/startCountdown");
109
+ var worker_timers_1 = require("./vendor/frontend/worker-timers");
110
+ var OidcInitializationError_1 = require("./OidcInitializationError");
111
+ var PARAMS_TO_RETRIEVE_FROM_SUCCESSFUL_LOGIN = ["code", "state", "session_state", "iss"];
112
+ var $isUserActive = undefined;
113
+ var prOidcByConfigHash = new Map();
114
+ var URL_real = window.URL;
115
+ /** @see: https://github.com/garronej/oidc-spa#option-1-usage-without-involving-the-ui-framework */
116
+ function createOidc(params) {
117
+ return __awaiter(this, void 0, void 0, function () {
118
+ var issuerUri, clientId, clientSecret, _a, scopes, _b, transformUrlBeforeRedirect, extraQueryParamsOrGetter, publicUrl_params, decodedIdTokenSchema, __unsafe_ssoSessionIdleSeconds, _c, autoLogoutParams, _d, isAuthGloballyRequired, postLoginRedirectUrl, getExtraQueryParams, publicUrl, configHash, prOidc, dOidc, silentSso, SILENT_SSO_KEY, CONFIG_HASH_KEY, result, oidcClientTsUserManager, lastPublicRoute, startTrackingLastPublicRoute, hasLoginBeenCalled, loginOrGoToAuthServer, resultOfLoginProcess, common, error, initializationError, oidc_1, oidc_2, currentTokens, autoLogoutCountdownTickCallbacks, onTokenChanges, oidc, getMsBeforeExpiration_1, startCountdown_2, stopCountdown_1;
119
+ var _this = this;
120
+ return __generator(this, function (_e) {
121
+ switch (_e.label) {
122
+ case 0:
123
+ issuerUri = params.issuerUri, clientId = params.clientId, clientSecret = params.clientSecret, _a = params.scopes, scopes = _a === void 0 ? ["profile"] : _a, _b = params.transformUrlBeforeRedirect, transformUrlBeforeRedirect = _b === void 0 ? function (url) { return url; } : _b, extraQueryParamsOrGetter = params.extraQueryParams, publicUrl_params = params.publicUrl, decodedIdTokenSchema = params.decodedIdTokenSchema, __unsafe_ssoSessionIdleSeconds = params.__unsafe_ssoSessionIdleSeconds, _c = params.autoLogoutParams, autoLogoutParams = _c === void 0 ? { "redirectTo": "current page" } : _c, _d = params.isAuthGloballyRequired, isAuthGloballyRequired = _d === void 0 ? false : _d, postLoginRedirectUrl = params.postLoginRedirectUrl;
124
+ getExtraQueryParams = (function () {
125
+ if (typeof extraQueryParamsOrGetter === "function") {
126
+ return extraQueryParamsOrGetter;
367
127
  }
368
- }));
369
- return;
370
- }
371
- frame_ancestors_none: {
372
- const csp = await (async () => {
373
- if (silentSso.hasDedicatedHtmlFile) {
374
- (0, tsafe_2.assert)(dedicatedSilentSsoHtmlFileCsp !== undefined);
375
- return dedicatedSilentSsoHtmlFileCsp;
128
+ if (extraQueryParamsOrGetter !== undefined) {
129
+ return function () { return extraQueryParamsOrGetter; };
376
130
  }
377
- const csp = await fetch(silentSso.redirectUri).then(response => response.headers.get("Content-Security-Policy"), error => (0, tsafe_1.id)(error));
378
- if (csp instanceof Error) {
379
- dLoginSuccessUrl.reject(new Error(`Failed to fetch ${silentSso.redirectUri}: ${csp.message}`));
380
- return new Promise(() => { });
131
+ return undefined;
132
+ })();
133
+ publicUrl = (function () {
134
+ if (publicUrl_params === undefined) {
135
+ return undefined;
381
136
  }
382
- return csp;
137
+ return (publicUrl_params.startsWith("http")
138
+ ? publicUrl_params
139
+ : "".concat(window.location.origin).concat(publicUrl_params)).replace(/\/$/, "");
383
140
  })();
384
- if (csp === null) {
385
- break frame_ancestors_none;
386
- }
387
- const hasFrameAncestorsNone = csp
388
- .replace(/["']/g, "")
389
- .replace(/\s+/g, " ")
390
- .toLowerCase()
391
- .includes("frame-ancestors none");
392
- if (!hasFrameAncestorsNone) {
393
- break frame_ancestors_none;
394
- }
395
- dLoginSuccessUrl.reject(new OidcInitializationError_1.OidcInitializationError({
396
- "type": "bad configuration",
397
- "likelyCause": {
398
- "type": "frame-ancestors none",
399
- silentSso
141
+ configHash = (0, fnv1aHashToHex_1.fnv1aHashToHex)("".concat(issuerUri, " ").concat(clientId, " ").concat(clientSecret !== null && clientSecret !== void 0 ? clientSecret : "", " ").concat(scopes.join(" ")));
142
+ use_previous_instance: {
143
+ prOidc = prOidcByConfigHash.get(configHash);
144
+ if (prOidc === undefined) {
145
+ break use_previous_instance;
400
146
  }
401
- }));
402
- return;
403
- }
404
- // Here we know that the server is not down and that the issuer_uri is correct
405
- // otherwise we would have had a fetch error when loading the iframe.
406
- // So this means that it's very likely a OIDC client misconfiguration.
407
- // It could also be a very slow network but this risk is mitigated by the fact that we check
408
- // for the network speed to adjust the timeout delay.
409
- dLoginSuccessUrl.reject(new OidcInitializationError_1.OidcInitializationError({
410
- "type": "bad configuration",
411
- "likelyCause": {
412
- "type": "misconfigured OIDC client",
413
- clientId,
414
- timeoutDelayMs,
415
- publicUrl
416
- }
417
- }));
418
- }, timeoutDelayMs);
419
- const listener = (event) => {
420
- if (typeof event.data !== "string") {
421
- return;
422
- }
423
- const url = event.data;
424
- {
425
- let result;
426
- try {
427
- result = (0, urlQueryParams_1.retrieveQueryParamFromUrl)({ "name": CONFIG_HASH_KEY, url });
428
- }
429
- catch (_a) {
430
- // This could possibly happen if url is not a valid url.
431
- return;
147
+ console.warn([
148
+ "oidc-spa has been instantiated more than once with the same configuration.",
149
+ "If you are in development mode with hot module replacement this is expected you can ignore this warning.",
150
+ "In production however this is something that should be addressed."
151
+ ].join(" "));
152
+ return [2 /*return*/, prOidc];
432
153
  }
433
- if (!result.wasPresent || result.value !== configHash) {
434
- return;
435
- }
436
- }
437
- (0, worker_timers_1.clearTimeout)(timeout);
438
- window.removeEventListener("message", listener);
439
- {
440
- const result = (0, urlQueryParams_1.retrieveQueryParamFromUrl)({ "name": "error", url });
441
- if (result.wasPresent) {
442
- dLoginSuccessUrl.resolve(undefined);
443
- return;
444
- }
445
- }
446
- let loginSuccessUrl = "https://dummy.com";
447
- const missingMandatoryParams = [];
448
- for (const name of PARAMS_TO_RETRIEVE_FROM_SUCCESSFUL_LOGIN) {
449
- const result = (0, urlQueryParams_1.retrieveQueryParamFromUrl)({ name, url });
450
- if (!result.wasPresent) {
451
- if (name === "iss") {
452
- continue;
154
+ dOidc = new Deferred_1.Deferred();
155
+ prOidcByConfigHash.set(configHash, dOidc.pr);
156
+ silentSso = publicUrl === undefined
157
+ ? {
158
+ "hasDedicatedHtmlFile": false,
159
+ "redirectUri": window.location.href
453
160
  }
454
- missingMandatoryParams.push(name);
455
- continue;
161
+ : {
162
+ "hasDedicatedHtmlFile": true,
163
+ "redirectUri": "".concat(publicUrl, "/silent-sso.html")
164
+ };
165
+ SILENT_SSO_KEY = "oidcSpaSilentSso";
166
+ CONFIG_HASH_KEY = "configHash";
167
+ if (!(0, urlQueryParams_1.retrieveQueryParamFromUrl)({
168
+ "url": window.location.href,
169
+ "name": SILENT_SSO_KEY
170
+ }).wasPresent) {
171
+ return [3 /*break*/, 4];
456
172
  }
457
- loginSuccessUrl = (0, urlQueryParams_1.addQueryParamToUrl)({
458
- "url": loginSuccessUrl,
459
- "name": name,
460
- "value": result.value
461
- }).newUrl;
462
- }
463
- if (missingMandatoryParams.length !== 0) {
464
- dLoginSuccessUrl.reject(new Error([
465
- "After the silent signin process the following mandatory OIDC query parameters where missing:",
466
- missingMandatoryParams.join(", ")
467
- ].join(" ")));
468
- return;
469
- }
470
- dLoginSuccessUrl.resolve(loginSuccessUrl);
471
- };
472
- window.addEventListener("message", listener, false);
473
- oidcClientTsUserManager
474
- .signinSilent({ "silentRequestTimeoutInSeconds": timeoutDelayMs / 1000 })
475
- .catch((error) => {
476
- if (error.message === "Failed to fetch") {
477
- (0, worker_timers_1.clearTimeout)(timeout);
478
- // Here we know it's not web origin because it's not the token we are fetching
479
- // but just the well known configuration endpoint that is not subject to CORS.
480
- dLoginSuccessUrl.reject(new OidcInitializationError_1.OidcInitializationError({
481
- "type": "server down",
482
- issuerUri
483
- }));
484
- }
485
- });
486
- const loginSuccessUrl = await dLoginSuccessUrl.pr;
487
- if (loginSuccessUrl === undefined) {
488
- break restore_from_http_only_cookie;
489
- }
490
- let oidcClientTsUser = undefined;
491
- try {
492
- oidcClientTsUser = await oidcClientTsUserManager.signinRedirectCallback(loginSuccessUrl);
493
- }
494
- catch (error) {
495
- (0, tsafe_2.assert)(error instanceof Error);
496
- if (error.message === "Failed to fetch") {
497
- // If we have a fetch error here. We know for sure that the server isn't down,
498
- // the silent sign-in was successful. We also know that the issuer_uri is correct.
499
- // so it's very likely the web origins that are misconfigured.
500
- throw new OidcInitializationError_1.OidcInitializationError({
501
- "type": "bad configuration",
502
- "likelyCause": {
503
- "type": "not in Web Origins",
504
- clientId
173
+ {
174
+ result = (0, urlQueryParams_1.retrieveQueryParamFromUrl)({
175
+ "url": window.location.href,
176
+ "name": CONFIG_HASH_KEY
177
+ });
178
+ if (!result.wasPresent || result.value !== configHash) {
179
+ return [3 /*break*/, 4];
505
180
  }
181
+ }
182
+ if (!silentSso.hasDedicatedHtmlFile) return [3 /*break*/, 2];
183
+ // Here the user forget to create the silent-sso.html file or or the web server is not serving it correctly
184
+ // we shouldn't fall back to the SPA page.
185
+ // In this case we want to let the timeout of the parent expire to provide the correct error message.
186
+ return [4 /*yield*/, new Promise(function () { })];
187
+ case 1:
188
+ // Here the user forget to create the silent-sso.html file or or the web server is not serving it correctly
189
+ // we shouldn't fall back to the SPA page.
190
+ // In this case we want to let the timeout of the parent expire to provide the correct error message.
191
+ _e.sent();
192
+ _e.label = 2;
193
+ case 2:
194
+ parent.postMessage(location.href, location.origin);
195
+ return [4 /*yield*/, new Promise(function () { })];
196
+ case 3:
197
+ _e.sent();
198
+ _e.label = 4;
199
+ case 4:
200
+ oidcClientTsUserManager = new oidc_client_ts_and_jwt_decode_1.UserManager({
201
+ "authority": issuerUri,
202
+ "client_id": clientId,
203
+ "client_secret": clientSecret,
204
+ "redirect_uri": "" /* provided when calling login */,
205
+ "response_type": "code",
206
+ "scope": Array.from(new Set(__spreadArray(["openid"], __read(scopes), false))).join(" "),
207
+ "automaticSilentRenew": false,
208
+ "silent_redirect_uri": (function () {
209
+ var redirectUri = silentSso.redirectUri;
210
+ redirectUri = (0, urlQueryParams_1.addQueryParamToUrl)({
211
+ "url": redirectUri,
212
+ "name": CONFIG_HASH_KEY,
213
+ "value": configHash
214
+ }).newUrl;
215
+ redirectUri = (0, urlQueryParams_1.addQueryParamToUrl)({
216
+ "url": redirectUri,
217
+ "name": SILENT_SSO_KEY,
218
+ "value": "true"
219
+ }).newUrl;
220
+ return redirectUri;
221
+ })()
506
222
  });
507
- }
508
- throw error;
509
- }
510
- return {
511
- "loginScenario": "silentSignin",
512
- oidcClientTsUser
513
- };
514
- }
515
- return undefined;
516
- })().then(result => {
517
- if (result === undefined) {
518
- return undefined;
519
- }
520
- const { oidcClientTsUser, loginScenario } = result;
521
- const tokens = oidcClientTsUserToTokens({
522
- oidcClientTsUser,
523
- decodedIdTokenSchema
524
- });
525
- if (tokens.refreshTokenExpirationTime < tokens.accessTokenExpirationTime) {
526
- console.warn([
527
- "The OIDC refresh token shorter than the one of the access token.",
528
- "This is very unusual and probably a misconfiguration.",
529
- `Check your oidc server configuration for ${clientId} ${issuerUri}`
530
- ].join(" "));
531
- }
532
- return { tokens, loginScenario };
533
- }, error => {
534
- (0, tsafe_2.assert)(error instanceof Error);
535
- return error;
536
- });
537
- const common = {
538
- "params": {
539
- issuerUri,
540
- clientId
541
- }
542
- };
543
- if (resultOfLoginProcess instanceof Error) {
544
- const error = resultOfLoginProcess;
545
- const initializationError = error instanceof OidcInitializationError_1.OidcInitializationError
546
- ? error
547
- : new OidcInitializationError_1.OidcInitializationError({
548
- "type": "unknown",
549
- "cause": error
550
- });
551
- if (isAuthGloballyRequired) {
552
- throw initializationError;
553
- }
554
- console.error(`OIDC initialization error of type "${initializationError.type}": ${initializationError.message}`);
555
- startTrackingLastPublicRoute();
556
- const oidc = (0, tsafe_1.id)({
557
- ...common,
558
- "isUserLoggedIn": false,
559
- "login": async () => {
560
- alert("Authentication is currently unavailable. Please try again later.");
561
- return new Promise(() => { });
562
- },
563
- initializationError
564
- });
565
- dOidc.resolve(oidc);
566
- // @ts-expect-error: We know what we are doing.
567
- return oidc;
568
- }
569
- if (resultOfLoginProcess === undefined) {
570
- if (isAuthGloballyRequired) {
571
- await loginOrGoToAuthServer({
572
- "action": "login",
573
- "doesCurrentHrefRequiresAuth": true,
574
- "redirectUrl": postLoginRedirectUrl
575
- });
576
- }
577
- startTrackingLastPublicRoute();
578
- const oidc = (0, tsafe_1.id)({
579
- ...common,
580
- "isUserLoggedIn": false,
581
- "login": params => loginOrGoToAuthServer({ "action": "login", ...params }),
582
- "initializationError": undefined
583
- });
584
- dOidc.resolve(oidc);
585
- // @ts-expect-error: We know what we are doing.
586
- return oidc;
587
- }
588
- let currentTokens = resultOfLoginProcess.tokens;
589
- const autoLogoutCountdownTickCallbacks = new Set();
590
- const onTokenChanges = new Set();
591
- const oidc = (0, tsafe_1.id)({
592
- ...common,
593
- "isUserLoggedIn": true,
594
- "getTokens": () => currentTokens,
595
- "logout": async (params) => {
596
- await oidcClientTsUserManager.signoutRedirect({
597
- "id_token_hint": currentTokens.idToken,
598
- "post_logout_redirect_uri": (() => {
599
- switch (params.redirectTo) {
600
- case "current page":
601
- return window.location.href;
602
- case "home":
603
- if (publicUrl === undefined) {
604
- throw new Error([
605
- "Since you've opted out of the `silent-sso.html` file you are probably in a",
606
- "setup a bit less standard. To avoid any confusion on where the users should be",
607
- "redirected after logout please explicitly specify the url to redirect to.",
608
- "With `logout({ redirectTo: 'specific url', url: '/my-home' })` or use",
609
- "`logout({ redirectTo: 'current page' })` if you want to redirect to the current page."
223
+ lastPublicRoute = undefined;
224
+ startTrackingLastPublicRoute = function () {
225
+ var realPushState = history.pushState.bind(history);
226
+ history.pushState = function pushState() {
227
+ var args = [];
228
+ for (var _i = 0; _i < arguments.length; _i++) {
229
+ args[_i] = arguments[_i];
230
+ }
231
+ lastPublicRoute = window.location.href;
232
+ return realPushState.apply(void 0, __spreadArray([], __read(args), false));
233
+ };
234
+ };
235
+ hasLoginBeenCalled = false;
236
+ loginOrGoToAuthServer = function (params) { return __awaiter(_this, void 0, void 0, function () {
237
+ var extraQueryParams_fromLoginFn, redirectUrl, _a, transformUrlBeforeRedirect_fromLoginFn, rest, redirect_uri, callback_1, URL_1;
238
+ return __generator(this, function (_b) {
239
+ switch (_b.label) {
240
+ case 0:
241
+ extraQueryParams_fromLoginFn = params.extraQueryParams, redirectUrl = params.redirectUrl, _a = params.transformUrlBeforeRedirect, transformUrlBeforeRedirect_fromLoginFn = _a === void 0 ? function (url) { return url; } : _a, rest = __rest(params, ["extraQueryParams", "redirectUrl", "transformUrlBeforeRedirect"]);
242
+ login_only: {
243
+ if (rest.action !== "login") {
244
+ break login_only;
245
+ }
246
+ if (hasLoginBeenCalled) {
247
+ return [2 /*return*/, new Promise(function () { })];
248
+ }
249
+ hasLoginBeenCalled = true;
250
+ }
251
+ redirect_uri = (0, urlQueryParams_1.addQueryParamToUrl)({
252
+ "url": (function () {
253
+ if (redirectUrl === undefined) {
254
+ return window.location.href;
255
+ }
256
+ return redirectUrl.startsWith("/")
257
+ ? "".concat(window.location.origin).concat(redirectUrl)
258
+ : redirectUrl;
259
+ })(),
260
+ "name": CONFIG_HASH_KEY,
261
+ "value": configHash
262
+ }).newUrl;
263
+ // NOTE: This is for handling cases when user press the back button on the login pages.
264
+ // When the app is hosted on https (so not in dev mode) the browser will restore the state of the app
265
+ // instead of reloading the page.
266
+ login_only: {
267
+ if (rest.action !== "login") {
268
+ break login_only;
269
+ }
270
+ callback_1 = function () {
271
+ if (document.visibilityState === "visible") {
272
+ document.removeEventListener("visibilitychange", callback_1);
273
+ if (rest.doesCurrentHrefRequiresAuth) {
274
+ if (lastPublicRoute !== undefined) {
275
+ window.location.href = lastPublicRoute;
276
+ }
277
+ else {
278
+ window.history.back();
279
+ }
280
+ }
281
+ else {
282
+ hasLoginBeenCalled = false;
283
+ }
284
+ }
285
+ };
286
+ document.addEventListener("visibilitychange", callback_1);
287
+ }
288
+ //NOTE: We know there is a extraQueryParameter option but it doesn't allow
289
+ // to control the encoding so we have to highjack global URL Class that is
290
+ // used internally by oidc-client-ts. It's save to do so since this is the
291
+ // last thing that will be done before the redirect.
292
+ {
293
+ URL_1 = function () {
294
+ var args = [];
295
+ for (var _i = 0; _i < arguments.length; _i++) {
296
+ args[_i] = arguments[_i];
297
+ }
298
+ var urlInstance = new (URL_real.bind.apply(URL_real, __spreadArray([void 0], __read(args), false)))();
299
+ return new Proxy(urlInstance, {
300
+ "get": function (target, prop) {
301
+ if (prop === "href") {
302
+ var url_1 = urlInstance.href;
303
+ [
304
+ [getExtraQueryParams === null || getExtraQueryParams === void 0 ? void 0 : getExtraQueryParams(), transformUrlBeforeRedirect],
305
+ [
306
+ extraQueryParams_fromLoginFn,
307
+ transformUrlBeforeRedirect_fromLoginFn
308
+ ]
309
+ ].forEach(function (_a) {
310
+ var _b = __read(_a, 2), extraQueryParams = _b[0], transformUrlBeforeRedirect = _b[1];
311
+ add_extra_query_params: {
312
+ if (extraQueryParams === undefined) {
313
+ break add_extra_query_params;
314
+ }
315
+ Object.entries(extraQueryParams).forEach(function (_a) {
316
+ var _b = __read(_a, 2), name = _b[0], value = _b[1];
317
+ return (url_1 = (0, urlQueryParams_1.addQueryParamToUrl)({
318
+ url: url_1,
319
+ name: name,
320
+ value: value
321
+ }).newUrl);
322
+ });
323
+ }
324
+ url_1 = transformUrlBeforeRedirect(url_1);
325
+ });
326
+ Object.defineProperty(window, "URL", { "value": URL_real });
327
+ return url_1;
328
+ }
329
+ //@ts-expect-error
330
+ return target[prop];
331
+ }
332
+ });
333
+ };
334
+ Object.defineProperty(window, "URL", { "value": URL_1 });
335
+ }
336
+ return [4 /*yield*/, oidcClientTsUserManager.signinRedirect({
337
+ redirect_uri: redirect_uri,
338
+ // NOTE: This is for the behavior when the use presses the back button on the login pages.
339
+ // This is what happens when the user gave up the login process.
340
+ // We want to that to redirect to the last public page.
341
+ "redirectMethod": (function () {
342
+ switch (rest.action) {
343
+ case "login":
344
+ return rest.doesCurrentHrefRequiresAuth ? "replace" : "assign";
345
+ case "go to auth server":
346
+ return "assign";
347
+ }
348
+ })()
349
+ })];
350
+ case 1:
351
+ _b.sent();
352
+ return [2 /*return*/, new Promise(function () { })];
353
+ }
354
+ });
355
+ }); };
356
+ return [4 /*yield*/, (function getUser() {
357
+ return __awaiter(this, void 0, void 0, function () {
358
+ var url, result, loginSuccessUrl, missingMandatoryParams, PARAMS_TO_RETRIEVE_FROM_SUCCESSFUL_LOGIN_1, PARAMS_TO_RETRIEVE_FROM_SUCCESSFUL_LOGIN_1_1, name_1, result, result, oidcClientTsUser, error_1, oidcClientTsUser, error_2, dLoginSuccessUrl_1, timeoutDelayMs_1, timeout_1, listener_1, loginSuccessUrl, oidcClientTsUser, error_3;
359
+ var e_1, _a;
360
+ var _this = this;
361
+ return __generator(this, function (_b) {
362
+ switch (_b.label) {
363
+ case 0:
364
+ url = window.location.href;
365
+ {
366
+ result = (0, urlQueryParams_1.retrieveQueryParamFromUrl)({ "name": CONFIG_HASH_KEY, url: url });
367
+ if (!result.wasPresent || result.value !== configHash) {
368
+ return [3 /*break*/, 5];
369
+ }
370
+ url = result.newUrl;
371
+ }
372
+ loginSuccessUrl = "https://dummy.com";
373
+ missingMandatoryParams = [];
374
+ try {
375
+ for (PARAMS_TO_RETRIEVE_FROM_SUCCESSFUL_LOGIN_1 = __values(PARAMS_TO_RETRIEVE_FROM_SUCCESSFUL_LOGIN), PARAMS_TO_RETRIEVE_FROM_SUCCESSFUL_LOGIN_1_1 = PARAMS_TO_RETRIEVE_FROM_SUCCESSFUL_LOGIN_1.next(); !PARAMS_TO_RETRIEVE_FROM_SUCCESSFUL_LOGIN_1_1.done; PARAMS_TO_RETRIEVE_FROM_SUCCESSFUL_LOGIN_1_1 = PARAMS_TO_RETRIEVE_FROM_SUCCESSFUL_LOGIN_1.next()) {
376
+ name_1 = PARAMS_TO_RETRIEVE_FROM_SUCCESSFUL_LOGIN_1_1.value;
377
+ result = (0, urlQueryParams_1.retrieveQueryParamFromUrl)({ name: name_1, url: url });
378
+ if (!result.wasPresent) {
379
+ if (name_1 === "iss") {
380
+ continue;
381
+ }
382
+ missingMandatoryParams.push(name_1);
383
+ continue;
384
+ }
385
+ loginSuccessUrl = (0, urlQueryParams_1.addQueryParamToUrl)({
386
+ "url": loginSuccessUrl,
387
+ "name": name_1,
388
+ "value": result.value
389
+ }).newUrl;
390
+ url = result.newUrl;
391
+ }
392
+ }
393
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
394
+ finally {
395
+ try {
396
+ if (PARAMS_TO_RETRIEVE_FROM_SUCCESSFUL_LOGIN_1_1 && !PARAMS_TO_RETRIEVE_FROM_SUCCESSFUL_LOGIN_1_1.done && (_a = PARAMS_TO_RETRIEVE_FROM_SUCCESSFUL_LOGIN_1.return)) _a.call(PARAMS_TO_RETRIEVE_FROM_SUCCESSFUL_LOGIN_1);
397
+ }
398
+ finally { if (e_1) throw e_1.error; }
399
+ }
400
+ window.history.pushState(null, "", url);
401
+ {
402
+ result = (0, urlQueryParams_1.retrieveQueryParamFromUrl)({ "name": "error", url: url });
403
+ if (result.wasPresent) {
404
+ throw new Error([
405
+ "The OIDC server responded with an error passed as query parameter after the login process",
406
+ "this error is: ".concat(result.value)
407
+ ].join(" "));
408
+ }
409
+ }
410
+ if (missingMandatoryParams.length !== 0) {
411
+ throw new Error([
412
+ "After the login process the following mandatory OIDC query parameters where missing:",
413
+ missingMandatoryParams.join(", ")
414
+ ].join(" "));
415
+ }
416
+ oidcClientTsUser = undefined;
417
+ _b.label = 1;
418
+ case 1:
419
+ _b.trys.push([1, 3, , 4]);
420
+ return [4 /*yield*/, oidcClientTsUserManager.signinRedirectCallback(loginSuccessUrl)];
421
+ case 2:
422
+ oidcClientTsUser = _b.sent();
423
+ return [3 /*break*/, 4];
424
+ case 3:
425
+ error_1 = _b.sent();
426
+ (0, tsafe_2.assert)(error_1 instanceof Error);
427
+ if (error_1.message === "Failed to fetch") {
428
+ // If it's a fetch error here we know that the web server is not down and the login was successful,
429
+ // we just where redirected from the login pages.
430
+ // This means it's likely a "Web origins" misconfiguration.
431
+ throw new OidcInitializationError_1.OidcInitializationError({
432
+ "type": "bad configuration",
433
+ "likelyCause": {
434
+ "type": "not in Web Origins",
435
+ clientId: clientId
436
+ }
437
+ });
438
+ }
439
+ //NOTE: The user has likely pressed the back button just after logging in.
440
+ //UPDATE: I don't remember how to reproduce this case and I don't know if it's still relevant.
441
+ return [2 /*return*/, undefined];
442
+ case 4: return [2 /*return*/, {
443
+ "loginScenario": "backFromLoginPages",
444
+ oidcClientTsUser: oidcClientTsUser
445
+ }];
446
+ case 5: return [4 /*yield*/, oidcClientTsUserManager.getUser()];
447
+ case 6:
448
+ oidcClientTsUser = _b.sent();
449
+ if (oidcClientTsUser === null) {
450
+ return [3 /*break*/, 11];
451
+ }
452
+ _b.label = 7;
453
+ case 7:
454
+ _b.trys.push([7, 9, , 10]);
455
+ return [4 /*yield*/, oidcClientTsUserManager.signinSilent()];
456
+ case 8:
457
+ _b.sent();
458
+ return [3 /*break*/, 10];
459
+ case 9:
460
+ error_2 = _b.sent();
461
+ (0, tsafe_2.assert)(error_2 instanceof Error);
462
+ if (error_2.message === "Failed to fetch") {
463
+ // Here it could be web origins as well but it's less likely because
464
+ // it would mean that there was once a valid configuration and it has been
465
+ // changed to an invalid one before the token expired.
466
+ // but the server is not necessarily down, the issuerUri could be wrong.
467
+ // So the error that we return should be either "server down" if fetching the
468
+ // well known configuration endpoint failed without returning any status code
469
+ // or "bad configuration" if the endpoint returned a 404 or an other status code.
470
+ throw new OidcInitializationError_1.OidcInitializationError({
471
+ "type": "server down",
472
+ issuerUri: issuerUri
473
+ });
474
+ }
475
+ return [2 /*return*/, undefined];
476
+ case 10: return [2 /*return*/, {
477
+ "loginScenario": "sessionStorageRestoration",
478
+ oidcClientTsUser: oidcClientTsUser
479
+ }];
480
+ case 11:
481
+ dLoginSuccessUrl_1 = new Deferred_1.Deferred();
482
+ timeoutDelayMs_1 = (function () {
483
+ var downlinkAndRtt = (0, getDownlinkAndRtt_1.getDownlinkAndRtt)();
484
+ if (downlinkAndRtt === undefined) {
485
+ return 5000;
486
+ }
487
+ var downlink = downlinkAndRtt.downlink, rtt = downlinkAndRtt.rtt;
488
+ // Base delay is the minimum delay we're willing to tolerate
489
+ var baseDelay = 3000;
490
+ // Calculate dynamic delay based on RTT and downlink
491
+ // Add 1 to downlink to avoid division by zero
492
+ var dynamicDelay = rtt * 2.5 + 3000 / (downlink + 1);
493
+ return Math.max(baseDelay, dynamicDelay);
494
+ })();
495
+ timeout_1 = (0, worker_timers_1.setTimeout)(function () { return __awaiter(_this, void 0, void 0, function () {
496
+ var dedicatedSilentSsoHtmlFileCsp, isSilentSsoHtmlReachable, csp, hasFrameAncestorsNone;
497
+ var _this = this;
498
+ return __generator(this, function (_a) {
499
+ switch (_a.label) {
500
+ case 0:
501
+ dedicatedSilentSsoHtmlFileCsp = undefined;
502
+ if (!silentSso.hasDedicatedHtmlFile) {
503
+ return [3 /*break*/, 2];
504
+ }
505
+ return [4 /*yield*/, fetch(silentSso.redirectUri).then(function (response) { return __awaiter(_this, void 0, void 0, function () {
506
+ var content;
507
+ return __generator(this, function (_a) {
508
+ switch (_a.label) {
509
+ case 0:
510
+ dedicatedSilentSsoHtmlFileCsp =
511
+ response.headers.get("Content-Security-Policy");
512
+ return [4 /*yield*/, response.text()];
513
+ case 1:
514
+ content = _a.sent();
515
+ return [2 /*return*/, (content.length < 250 &&
516
+ content.includes("parent.postMessage(location.href"))];
517
+ }
518
+ });
519
+ }); }, function () { return false; })];
520
+ case 1:
521
+ isSilentSsoHtmlReachable = _a.sent();
522
+ if (isSilentSsoHtmlReachable) {
523
+ return [3 /*break*/, 2];
524
+ }
525
+ dLoginSuccessUrl_1.reject(new OidcInitializationError_1.OidcInitializationError({
526
+ "type": "bad configuration",
527
+ "likelyCause": {
528
+ "type": "silent-sso.html not reachable",
529
+ "silentSsoHtmlUrl": silentSso.redirectUri
530
+ }
531
+ }));
532
+ return [2 /*return*/];
533
+ case 2: return [4 /*yield*/, (function () { return __awaiter(_this, void 0, void 0, function () {
534
+ var csp;
535
+ return __generator(this, function (_a) {
536
+ switch (_a.label) {
537
+ case 0:
538
+ if (silentSso.hasDedicatedHtmlFile) {
539
+ (0, tsafe_2.assert)(dedicatedSilentSsoHtmlFileCsp !== undefined);
540
+ return [2 /*return*/, dedicatedSilentSsoHtmlFileCsp];
541
+ }
542
+ return [4 /*yield*/, fetch(silentSso.redirectUri).then(function (response) { return response.headers.get("Content-Security-Policy"); }, function (error) { return (0, tsafe_1.id)(error); })];
543
+ case 1:
544
+ csp = _a.sent();
545
+ if (csp instanceof Error) {
546
+ dLoginSuccessUrl_1.reject(new Error("Failed to fetch ".concat(silentSso.redirectUri, ": ").concat(csp.message)));
547
+ return [2 /*return*/, new Promise(function () { })];
548
+ }
549
+ return [2 /*return*/, csp];
550
+ }
551
+ });
552
+ }); })()];
553
+ case 3:
554
+ csp = _a.sent();
555
+ if (csp === null) {
556
+ return [3 /*break*/, 4];
557
+ }
558
+ hasFrameAncestorsNone = csp
559
+ .replace(/["']/g, "")
560
+ .replace(/\s+/g, " ")
561
+ .toLowerCase()
562
+ .includes("frame-ancestors none");
563
+ if (!hasFrameAncestorsNone) {
564
+ return [3 /*break*/, 4];
565
+ }
566
+ dLoginSuccessUrl_1.reject(new OidcInitializationError_1.OidcInitializationError({
567
+ "type": "bad configuration",
568
+ "likelyCause": {
569
+ "type": "frame-ancestors none",
570
+ silentSso: silentSso
571
+ }
572
+ }));
573
+ return [2 /*return*/];
574
+ case 4:
575
+ // Here we know that the server is not down and that the issuer_uri is correct
576
+ // otherwise we would have had a fetch error when loading the iframe.
577
+ // So this means that it's very likely a OIDC client misconfiguration.
578
+ // It could also be a very slow network but this risk is mitigated by the fact that we check
579
+ // for the network speed to adjust the timeout delay.
580
+ dLoginSuccessUrl_1.reject(new OidcInitializationError_1.OidcInitializationError({
581
+ "type": "bad configuration",
582
+ "likelyCause": {
583
+ "type": "misconfigured OIDC client",
584
+ clientId: clientId,
585
+ timeoutDelayMs: timeoutDelayMs_1,
586
+ publicUrl: publicUrl
587
+ }
588
+ }));
589
+ return [2 /*return*/];
590
+ }
591
+ });
592
+ }); }, timeoutDelayMs_1);
593
+ listener_1 = function (event) {
594
+ var e_2, _a;
595
+ if (typeof event.data !== "string") {
596
+ return;
597
+ }
598
+ var url = event.data;
599
+ {
600
+ var result = void 0;
601
+ try {
602
+ result = (0, urlQueryParams_1.retrieveQueryParamFromUrl)({ "name": CONFIG_HASH_KEY, url: url });
603
+ }
604
+ catch (_b) {
605
+ // This could possibly happen if url is not a valid url.
606
+ return;
607
+ }
608
+ if (!result.wasPresent || result.value !== configHash) {
609
+ return;
610
+ }
611
+ }
612
+ (0, worker_timers_1.clearTimeout)(timeout_1);
613
+ window.removeEventListener("message", listener_1);
614
+ {
615
+ var result = (0, urlQueryParams_1.retrieveQueryParamFromUrl)({ "name": "error", url: url });
616
+ if (result.wasPresent) {
617
+ dLoginSuccessUrl_1.resolve(undefined);
618
+ return;
619
+ }
620
+ }
621
+ var loginSuccessUrl = "https://dummy.com";
622
+ var missingMandatoryParams = [];
623
+ try {
624
+ for (var PARAMS_TO_RETRIEVE_FROM_SUCCESSFUL_LOGIN_2 = __values(PARAMS_TO_RETRIEVE_FROM_SUCCESSFUL_LOGIN), PARAMS_TO_RETRIEVE_FROM_SUCCESSFUL_LOGIN_2_1 = PARAMS_TO_RETRIEVE_FROM_SUCCESSFUL_LOGIN_2.next(); !PARAMS_TO_RETRIEVE_FROM_SUCCESSFUL_LOGIN_2_1.done; PARAMS_TO_RETRIEVE_FROM_SUCCESSFUL_LOGIN_2_1 = PARAMS_TO_RETRIEVE_FROM_SUCCESSFUL_LOGIN_2.next()) {
625
+ var name_2 = PARAMS_TO_RETRIEVE_FROM_SUCCESSFUL_LOGIN_2_1.value;
626
+ var result = (0, urlQueryParams_1.retrieveQueryParamFromUrl)({ name: name_2, url: url });
627
+ if (!result.wasPresent) {
628
+ if (name_2 === "iss") {
629
+ continue;
630
+ }
631
+ missingMandatoryParams.push(name_2);
632
+ continue;
633
+ }
634
+ loginSuccessUrl = (0, urlQueryParams_1.addQueryParamToUrl)({
635
+ "url": loginSuccessUrl,
636
+ "name": name_2,
637
+ "value": result.value
638
+ }).newUrl;
639
+ }
640
+ }
641
+ catch (e_2_1) { e_2 = { error: e_2_1 }; }
642
+ finally {
643
+ try {
644
+ if (PARAMS_TO_RETRIEVE_FROM_SUCCESSFUL_LOGIN_2_1 && !PARAMS_TO_RETRIEVE_FROM_SUCCESSFUL_LOGIN_2_1.done && (_a = PARAMS_TO_RETRIEVE_FROM_SUCCESSFUL_LOGIN_2.return)) _a.call(PARAMS_TO_RETRIEVE_FROM_SUCCESSFUL_LOGIN_2);
645
+ }
646
+ finally { if (e_2) throw e_2.error; }
647
+ }
648
+ if (missingMandatoryParams.length !== 0) {
649
+ dLoginSuccessUrl_1.reject(new Error([
650
+ "After the silent signin process the following mandatory OIDC query parameters where missing:",
651
+ missingMandatoryParams.join(", ")
652
+ ].join(" ")));
653
+ return;
654
+ }
655
+ dLoginSuccessUrl_1.resolve(loginSuccessUrl);
656
+ };
657
+ window.addEventListener("message", listener_1, false);
658
+ oidcClientTsUserManager
659
+ .signinSilent({ "silentRequestTimeoutInSeconds": timeoutDelayMs_1 / 1000 })
660
+ .catch(function (error) {
661
+ if (error.message === "Failed to fetch") {
662
+ (0, worker_timers_1.clearTimeout)(timeout_1);
663
+ // Here we know it's not web origin because it's not the token we are fetching
664
+ // but just the well known configuration endpoint that is not subject to CORS.
665
+ dLoginSuccessUrl_1.reject(new OidcInitializationError_1.OidcInitializationError({
666
+ "type": "server down",
667
+ issuerUri: issuerUri
668
+ }));
669
+ }
670
+ });
671
+ return [4 /*yield*/, dLoginSuccessUrl_1.pr];
672
+ case 12:
673
+ loginSuccessUrl = _b.sent();
674
+ if (loginSuccessUrl === undefined) {
675
+ return [3 /*break*/, 17];
676
+ }
677
+ oidcClientTsUser = undefined;
678
+ _b.label = 13;
679
+ case 13:
680
+ _b.trys.push([13, 15, , 16]);
681
+ return [4 /*yield*/, oidcClientTsUserManager.signinRedirectCallback(loginSuccessUrl)];
682
+ case 14:
683
+ oidcClientTsUser = _b.sent();
684
+ return [3 /*break*/, 16];
685
+ case 15:
686
+ error_3 = _b.sent();
687
+ (0, tsafe_2.assert)(error_3 instanceof Error);
688
+ if (error_3.message === "Failed to fetch") {
689
+ // If we have a fetch error here. We know for sure that the server isn't down,
690
+ // the silent sign-in was successful. We also know that the issuer_uri is correct.
691
+ // so it's very likely the web origins that are misconfigured.
692
+ throw new OidcInitializationError_1.OidcInitializationError({
693
+ "type": "bad configuration",
694
+ "likelyCause": {
695
+ "type": "not in Web Origins",
696
+ clientId: clientId
697
+ }
698
+ });
699
+ }
700
+ throw error_3;
701
+ case 16: return [2 /*return*/, {
702
+ "loginScenario": "silentSignin",
703
+ oidcClientTsUser: oidcClientTsUser
704
+ }];
705
+ case 17: return [2 /*return*/, undefined];
706
+ }
707
+ });
708
+ });
709
+ })().then(function (result) {
710
+ if (result === undefined) {
711
+ return undefined;
712
+ }
713
+ var oidcClientTsUser = result.oidcClientTsUser, loginScenario = result.loginScenario;
714
+ var tokens = oidcClientTsUserToTokens({
715
+ oidcClientTsUser: oidcClientTsUser,
716
+ decodedIdTokenSchema: decodedIdTokenSchema
717
+ });
718
+ if (tokens.refreshTokenExpirationTime < tokens.accessTokenExpirationTime) {
719
+ console.warn([
720
+ "The OIDC refresh token shorter than the one of the access token.",
721
+ "This is very unusual and probably a misconfiguration.",
722
+ "Check your oidc server configuration for ".concat(clientId, " ").concat(issuerUri)
610
723
  ].join(" "));
611
724
  }
612
- return publicUrl;
613
- case "specific url":
614
- return params.url.startsWith("/")
615
- ? `${window.location.origin}${params.url}`
616
- : params.url;
725
+ return { tokens: tokens, loginScenario: loginScenario };
726
+ }, function (error) {
727
+ (0, tsafe_2.assert)(error instanceof Error);
728
+ return error;
729
+ })];
730
+ case 5:
731
+ resultOfLoginProcess = _e.sent();
732
+ common = {
733
+ "params": {
734
+ issuerUri: issuerUri,
735
+ clientId: clientId
736
+ }
737
+ };
738
+ if (resultOfLoginProcess instanceof Error) {
739
+ error = resultOfLoginProcess;
740
+ initializationError = error instanceof OidcInitializationError_1.OidcInitializationError
741
+ ? error
742
+ : new OidcInitializationError_1.OidcInitializationError({
743
+ "type": "unknown",
744
+ "cause": error
745
+ });
746
+ if (isAuthGloballyRequired) {
747
+ throw initializationError;
748
+ }
749
+ console.error("OIDC initialization error of type \"".concat(initializationError.type, "\": ").concat(initializationError.message));
750
+ startTrackingLastPublicRoute();
751
+ oidc_1 = (0, tsafe_1.id)(__assign(__assign({}, common), { "isUserLoggedIn": false, "login": function () { return __awaiter(_this, void 0, void 0, function () {
752
+ return __generator(this, function (_a) {
753
+ alert("Authentication is currently unavailable. Please try again later.");
754
+ return [2 /*return*/, new Promise(function () { })];
755
+ });
756
+ }); }, initializationError: initializationError }));
757
+ dOidc.resolve(oidc_1);
758
+ // @ts-expect-error: We know what we are doing.
759
+ return [2 /*return*/, oidc_1];
760
+ }
761
+ if (!(resultOfLoginProcess === undefined)) return [3 /*break*/, 8];
762
+ if (!isAuthGloballyRequired) return [3 /*break*/, 7];
763
+ return [4 /*yield*/, loginOrGoToAuthServer({
764
+ "action": "login",
765
+ "doesCurrentHrefRequiresAuth": true,
766
+ "redirectUrl": postLoginRedirectUrl
767
+ })];
768
+ case 6:
769
+ _e.sent();
770
+ _e.label = 7;
771
+ case 7:
772
+ startTrackingLastPublicRoute();
773
+ oidc_2 = (0, tsafe_1.id)(__assign(__assign({}, common), { "isUserLoggedIn": false, "login": function (params) { return loginOrGoToAuthServer(__assign({ "action": "login" }, params)); }, "initializationError": undefined }));
774
+ dOidc.resolve(oidc_2);
775
+ // @ts-expect-error: We know what we are doing.
776
+ return [2 /*return*/, oidc_2];
777
+ case 8:
778
+ currentTokens = resultOfLoginProcess.tokens;
779
+ autoLogoutCountdownTickCallbacks = new Set();
780
+ onTokenChanges = new Set();
781
+ oidc = (0, tsafe_1.id)(__assign(__assign({}, common), { "isUserLoggedIn": true, "getTokens": function () { return currentTokens; }, "logout": function (params) { return __awaiter(_this, void 0, void 0, function () {
782
+ return __generator(this, function (_a) {
783
+ switch (_a.label) {
784
+ case 0: return [4 /*yield*/, oidcClientTsUserManager.signoutRedirect({
785
+ "id_token_hint": currentTokens.idToken,
786
+ "post_logout_redirect_uri": (function () {
787
+ switch (params.redirectTo) {
788
+ case "current page":
789
+ return window.location.href;
790
+ case "home":
791
+ if (publicUrl === undefined) {
792
+ throw new Error([
793
+ "Since you've opted out of the `silent-sso.html` file you are probably in a",
794
+ "setup a bit less standard. To avoid any confusion on where the users should be",
795
+ "redirected after logout please explicitly specify the url to redirect to.",
796
+ "With `logout({ redirectTo: 'specific url', url: '/my-home' })` or use",
797
+ "`logout({ redirectTo: 'current page' })` if you want to redirect to the current page."
798
+ ].join(" "));
799
+ }
800
+ return publicUrl;
801
+ case "specific url":
802
+ return params.url.startsWith("/")
803
+ ? "".concat(window.location.origin).concat(params.url)
804
+ : params.url;
805
+ }
806
+ (0, tsafe_2.assert)(false);
807
+ })()
808
+ })];
809
+ case 1:
810
+ _a.sent();
811
+ return [2 /*return*/, new Promise(function () { })];
812
+ }
813
+ });
814
+ }); }, "renewTokens": function () { return __awaiter(_this, void 0, void 0, function () {
815
+ var oidcClientTsUser, decodedIdTokenPropertyDescriptor;
816
+ return __generator(this, function (_a) {
817
+ switch (_a.label) {
818
+ case 0: return [4 /*yield*/, oidcClientTsUserManager.signinSilent()];
819
+ case 1:
820
+ oidcClientTsUser = _a.sent();
821
+ (0, tsafe_2.assert)(oidcClientTsUser !== null);
822
+ decodedIdTokenPropertyDescriptor = Object.getOwnPropertyDescriptor(currentTokens, "decodedIdToken");
823
+ (0, tsafe_2.assert)(decodedIdTokenPropertyDescriptor !== undefined);
824
+ currentTokens = oidcClientTsUserToTokens({
825
+ oidcClientTsUser: oidcClientTsUser,
826
+ decodedIdTokenSchema: decodedIdTokenSchema
827
+ });
828
+ // NOTE: We do that to preserve the cache and the object reference.
829
+ Object.defineProperty(currentTokens, "decodedIdToken", decodedIdTokenPropertyDescriptor);
830
+ Array.from(onTokenChanges).forEach(function (onTokenChange) { return onTokenChange(); });
831
+ return [2 /*return*/];
832
+ }
833
+ });
834
+ }); }, "subscribeToTokensChange": function (onTokenChange) {
835
+ onTokenChanges.add(onTokenChange);
836
+ return {
837
+ "unsubscribe": function () {
838
+ onTokenChanges.delete(onTokenChange);
839
+ }
840
+ };
841
+ }, "subscribeToAutoLogoutCountdown": function (tickCallback) {
842
+ autoLogoutCountdownTickCallbacks.add(tickCallback);
843
+ var unsubscribeFromAutoLogoutCountdown = function () {
844
+ autoLogoutCountdownTickCallbacks.delete(tickCallback);
845
+ };
846
+ return { unsubscribeFromAutoLogoutCountdown: unsubscribeFromAutoLogoutCountdown };
847
+ }, "loginScenario": resultOfLoginProcess.loginScenario, "goToAuthServer": function (params) { return loginOrGoToAuthServer(__assign({ "action": "go to auth server" }, params)); } }));
848
+ {
849
+ getMsBeforeExpiration_1 = function () {
850
+ // NOTE: In general the access token is supposed to have a shorter
851
+ // lifespan than the refresh token but we don't want to make any
852
+ // assumption here.
853
+ var tokenExpirationTime = Math.min(currentTokens.accessTokenExpirationTime, currentTokens.refreshTokenExpirationTime);
854
+ return Math.min(tokenExpirationTime - Date.now(),
855
+ // NOTE: We want to make sure we do not overflow the setTimeout
856
+ // that must be a 32 bit unsigned integer.
857
+ // This can happen if the tokenExpirationTime is more than 24.8 days in the future.
858
+ Math.pow(2, 31) - 1);
859
+ };
860
+ (function scheduleRenew() {
861
+ var _this = this;
862
+ // NOTE: We refresh the token 25 seconds before it expires.
863
+ // If the token expiration time is less than 25 seconds we refresh the token when
864
+ // only 1/10 of the token time is left.
865
+ var renewMsBeforeExpires = Math.min(25000, getMsBeforeExpiration_1() * 0.1);
866
+ var timer = (0, worker_timers_1.setTimeout)(function () { return __awaiter(_this, void 0, void 0, function () {
867
+ var _a;
868
+ return __generator(this, function (_b) {
869
+ switch (_b.label) {
870
+ case 0:
871
+ tokenChangeUnsubscribe();
872
+ _b.label = 1;
873
+ case 1:
874
+ _b.trys.push([1, 3, , 5]);
875
+ return [4 /*yield*/, oidc.renewTokens()];
876
+ case 2:
877
+ _b.sent();
878
+ return [3 /*break*/, 5];
879
+ case 3:
880
+ _a = _b.sent();
881
+ // NOTE: Here semantically `"doesCurrentHrefRequiresAuth": false` is wrong.
882
+ // The user may very well be on a page that require auth.
883
+ // However there's no way to enforce the browser to redirect back to
884
+ // the last public route if the user press back on the login page.
885
+ // This is due to the fact that pushing to history only works if it's
886
+ // triggered by a user interaction.
887
+ return [4 /*yield*/, loginOrGoToAuthServer({
888
+ "action": "login",
889
+ "doesCurrentHrefRequiresAuth": false
890
+ })];
891
+ case 4:
892
+ // NOTE: Here semantically `"doesCurrentHrefRequiresAuth": false` is wrong.
893
+ // The user may very well be on a page that require auth.
894
+ // However there's no way to enforce the browser to redirect back to
895
+ // the last public route if the user press back on the login page.
896
+ // This is due to the fact that pushing to history only works if it's
897
+ // triggered by a user interaction.
898
+ _b.sent();
899
+ return [3 /*break*/, 5];
900
+ case 5: return [2 /*return*/];
901
+ }
902
+ });
903
+ }); }, getMsBeforeExpiration_1() - renewMsBeforeExpires);
904
+ var tokenChangeUnsubscribe = oidc.subscribeToTokensChange(function () {
905
+ (0, worker_timers_1.clearTimeout)(timer);
906
+ tokenChangeUnsubscribe();
907
+ scheduleRenew();
908
+ }).unsubscribe;
909
+ })();
910
+ }
911
+ {
912
+ startCountdown_2 = (0, startCountdown_1.createStartCountdown)({
913
+ "getCountdownEndTime": function () {
914
+ return __unsafe_ssoSessionIdleSeconds !== undefined
915
+ ? Date.now() + __unsafe_ssoSessionIdleSeconds * 1000
916
+ : currentTokens.refreshTokenExpirationTime;
917
+ },
918
+ "tickCallback": function (_a) {
919
+ var secondsLeft = _a.secondsLeft;
920
+ Array.from(autoLogoutCountdownTickCallbacks).forEach(function (tickCallback) {
921
+ return tickCallback({ secondsLeft: secondsLeft });
922
+ });
923
+ if (secondsLeft === 0) {
924
+ oidc.logout(autoLogoutParams);
925
+ }
926
+ }
927
+ }).startCountdown;
928
+ stopCountdown_1 = undefined;
929
+ if ($isUserActive === undefined) {
930
+ $isUserActive = (0, createIsUserActive_1.createIsUserActive)({
931
+ "theUserIsConsideredInactiveAfterMsOfInactivity": 5000
932
+ }).$isUserActive;
933
+ }
934
+ $isUserActive.subscribe(function (isUserActive) {
935
+ if (isUserActive) {
936
+ if (stopCountdown_1 !== undefined) {
937
+ stopCountdown_1();
938
+ stopCountdown_1 = undefined;
939
+ }
940
+ }
941
+ else {
942
+ (0, tsafe_2.assert)(stopCountdown_1 === undefined);
943
+ stopCountdown_1 = startCountdown_2().stopCountdown;
944
+ }
945
+ });
617
946
  }
618
- (0, tsafe_2.assert)(false);
619
- })()
620
- });
621
- return new Promise(() => { });
622
- },
623
- "renewTokens": async () => {
624
- const oidcClientTsUser = await oidcClientTsUserManager.signinSilent();
625
- (0, tsafe_2.assert)(oidcClientTsUser !== null);
626
- const decodedIdTokenPropertyDescriptor = Object.getOwnPropertyDescriptor(currentTokens, "decodedIdToken");
627
- (0, tsafe_2.assert)(decodedIdTokenPropertyDescriptor !== undefined);
628
- currentTokens = oidcClientTsUserToTokens({
629
- oidcClientTsUser,
630
- decodedIdTokenSchema
631
- });
632
- // NOTE: We do that to preserve the cache and the object reference.
633
- Object.defineProperty(currentTokens, "decodedIdToken", decodedIdTokenPropertyDescriptor);
634
- Array.from(onTokenChanges).forEach(onTokenChange => onTokenChange());
635
- },
636
- "subscribeToTokensChange": onTokenChange => {
637
- onTokenChanges.add(onTokenChange);
638
- return {
639
- "unsubscribe": () => {
640
- onTokenChanges.delete(onTokenChange);
641
- }
642
- };
643
- },
644
- "subscribeToAutoLogoutCountdown": tickCallback => {
645
- autoLogoutCountdownTickCallbacks.add(tickCallback);
646
- const unsubscribeFromAutoLogoutCountdown = () => {
647
- autoLogoutCountdownTickCallbacks.delete(tickCallback);
648
- };
649
- return { unsubscribeFromAutoLogoutCountdown };
650
- },
651
- "loginScenario": resultOfLoginProcess.loginScenario,
652
- "goToAuthServer": params => loginOrGoToAuthServer({ "action": "go to auth server", ...params })
653
- });
654
- {
655
- const getMsBeforeExpiration = () => {
656
- // NOTE: In general the access token is supposed to have a shorter
657
- // lifespan than the refresh token but we don't want to make any
658
- // assumption here.
659
- const tokenExpirationTime = Math.min(currentTokens.accessTokenExpirationTime, currentTokens.refreshTokenExpirationTime);
660
- return Math.min(tokenExpirationTime - Date.now(),
661
- // NOTE: We want to make sure we do not overflow the setTimeout
662
- // that must be a 32 bit unsigned integer.
663
- // This can happen if the tokenExpirationTime is more than 24.8 days in the future.
664
- Math.pow(2, 31) - 1);
665
- };
666
- (function scheduleRenew() {
667
- // NOTE: We refresh the token 25 seconds before it expires.
668
- // If the token expiration time is less than 25 seconds we refresh the token when
669
- // only 1/10 of the token time is left.
670
- const renewMsBeforeExpires = Math.min(25000, getMsBeforeExpiration() * 0.1);
671
- const timer = (0, worker_timers_1.setTimeout)(async () => {
672
- tokenChangeUnsubscribe();
673
- try {
674
- await oidc.renewTokens();
675
- }
676
- catch (_a) {
677
- // NOTE: Here semantically `"doesCurrentHrefRequiresAuth": false` is wrong.
678
- // The user may very well be on a page that require auth.
679
- // However there's no way to enforce the browser to redirect back to
680
- // the last public route if the user press back on the login page.
681
- // This is due to the fact that pushing to history only works if it's
682
- // triggered by a user interaction.
683
- await loginOrGoToAuthServer({
684
- "action": "login",
685
- "doesCurrentHrefRequiresAuth": false
686
- });
687
- }
688
- }, getMsBeforeExpiration() - renewMsBeforeExpires);
689
- const { unsubscribe: tokenChangeUnsubscribe } = oidc.subscribeToTokensChange(() => {
690
- (0, worker_timers_1.clearTimeout)(timer);
691
- tokenChangeUnsubscribe();
692
- scheduleRenew();
693
- });
694
- })();
695
- }
696
- {
697
- const { startCountdown } = (0, startCountdown_1.createStartCountdown)({
698
- "getCountdownEndTime": () => __unsafe_ssoSessionIdleSeconds !== undefined
699
- ? Date.now() + __unsafe_ssoSessionIdleSeconds * 1000
700
- : currentTokens.refreshTokenExpirationTime,
701
- "tickCallback": ({ secondsLeft }) => {
702
- Array.from(autoLogoutCountdownTickCallbacks).forEach(tickCallback => tickCallback({ secondsLeft }));
703
- if (secondsLeft === 0) {
704
- oidc.logout(autoLogoutParams);
705
- }
947
+ return [2 /*return*/, oidc];
706
948
  }
707
949
  });
708
- let stopCountdown = undefined;
709
- if ($isUserActive === undefined) {
710
- $isUserActive = (0, createIsUserActive_1.createIsUserActive)({
711
- "theUserIsConsideredInactiveAfterMsOfInactivity": 5000
712
- }).$isUserActive;
713
- }
714
- $isUserActive.subscribe(isUserActive => {
715
- if (isUserActive) {
716
- if (stopCountdown !== undefined) {
717
- stopCountdown();
718
- stopCountdown = undefined;
719
- }
720
- }
721
- else {
722
- (0, tsafe_2.assert)(stopCountdown === undefined);
723
- stopCountdown = startCountdown().stopCountdown;
724
- }
725
- });
726
- }
727
- return oidc;
950
+ });
728
951
  }
729
952
  function oidcClientTsUserToTokens(params) {
730
- const { oidcClientTsUser, decodedIdTokenSchema } = params;
731
- const accessToken = oidcClientTsUser.access_token;
732
- const accessTokenExpirationTime = (() => {
953
+ var oidcClientTsUser = params.oidcClientTsUser, decodedIdTokenSchema = params.decodedIdTokenSchema;
954
+ var accessToken = oidcClientTsUser.access_token;
955
+ var accessTokenExpirationTime = (function () {
733
956
  read_from_metadata: {
734
- const { expires_at } = oidcClientTsUser;
957
+ var expires_at = oidcClientTsUser.expires_at;
735
958
  if (expires_at === undefined) {
736
959
  break read_from_metadata;
737
960
  }
738
961
  return expires_at * 1000;
739
962
  }
740
963
  read_from_jwt: {
741
- const expirationTime = (0, readExpirationTimeInJwt_1.readExpirationTimeInJwt)(accessToken);
964
+ var expirationTime = (0, readExpirationTimeInJwt_1.readExpirationTimeInJwt)(accessToken);
742
965
  if (expirationTime === undefined) {
743
966
  break read_from_jwt;
744
967
  }
@@ -746,11 +969,11 @@ function oidcClientTsUserToTokens(params) {
746
969
  }
747
970
  (0, tsafe_2.assert)(false, "Failed to get access token expiration time");
748
971
  })();
749
- const refreshToken = oidcClientTsUser.refresh_token;
972
+ var refreshToken = oidcClientTsUser.refresh_token;
750
973
  (0, tsafe_2.assert)(refreshToken !== undefined, "No refresh token provided by the oidc server");
751
- const refreshTokenExpirationTime = (() => {
974
+ var refreshTokenExpirationTime = (function () {
752
975
  read_from_jwt: {
753
- const expirationTime = (0, readExpirationTimeInJwt_1.readExpirationTimeInJwt)(refreshToken);
976
+ var expirationTime = (0, readExpirationTimeInJwt_1.readExpirationTimeInJwt)(refreshToken);
754
977
  if (expirationTime === undefined) {
755
978
  break read_from_jwt;
756
979
  }
@@ -758,29 +981,29 @@ function oidcClientTsUserToTokens(params) {
758
981
  }
759
982
  (0, tsafe_2.assert)(false, "Failed to get refresh token expiration time");
760
983
  })();
761
- const idToken = oidcClientTsUser.id_token;
984
+ var idToken = oidcClientTsUser.id_token;
762
985
  (0, tsafe_2.assert)(idToken !== undefined, "No id token provided by the oidc server");
763
- const tokens = {
764
- accessToken,
765
- accessTokenExpirationTime,
766
- refreshToken,
767
- refreshTokenExpirationTime,
768
- idToken,
986
+ var tokens = {
987
+ accessToken: accessToken,
988
+ accessTokenExpirationTime: accessTokenExpirationTime,
989
+ refreshToken: refreshToken,
990
+ refreshTokenExpirationTime: refreshTokenExpirationTime,
991
+ idToken: idToken,
769
992
  "decodedIdToken": null
770
993
  };
771
- let cache = undefined;
994
+ var cache = undefined;
772
995
  Object.defineProperty(tokens, "decodedIdToken", {
773
996
  "get": function () {
774
997
  if (cache !== undefined && cache.idToken === this.idToken) {
775
998
  return cache.decodedIdToken;
776
999
  }
777
- let decodedIdToken = (0, decodeJwt_1.decodeJwt)(this.idToken);
1000
+ var decodedIdToken = (0, decodeJwt_1.decodeJwt)(this.idToken);
778
1001
  if (decodedIdTokenSchema !== undefined) {
779
1002
  decodedIdToken = decodedIdTokenSchema.parse(decodedIdToken);
780
1003
  }
781
1004
  cache = {
782
1005
  "idToken": this.idToken,
783
- decodedIdToken
1006
+ decodedIdToken: decodedIdToken
784
1007
  };
785
1008
  return decodedIdToken;
786
1009
  },