@schibsted/account-sdk-browser 5.2.7 → 6.0.0-alpha.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 (90) hide show
  1. package/README.md +12 -59
  2. package/dist/RESTClient.d.ts +91 -0
  3. package/dist/SDKError.d.ts +27 -0
  4. package/dist/cache.d.ts +65 -0
  5. package/dist/config.d.ts +86 -0
  6. package/dist/global-registry.d.ts +23 -0
  7. package/dist/globals.d.ts +13 -0
  8. package/dist/identity-s4nofYmB.js +370 -0
  9. package/dist/identity-s4nofYmB.js.map +1 -0
  10. package/dist/identity.d.ts +523 -0
  11. package/dist/identity.js +2 -0
  12. package/dist/index.d.ts +3 -0
  13. package/dist/index.js +4 -0
  14. package/dist/monetization.d.ts +94 -0
  15. package/dist/monetization.js +72 -0
  16. package/dist/monetization.js.map +1 -0
  17. package/{src → dist}/object.d.ts +4 -9
  18. package/dist/popup.d.ts +9 -0
  19. package/{src → dist}/spidTalk.d.ts +4 -6
  20. package/dist/url.d.ts +8 -0
  21. package/dist/validate.d.ts +50 -0
  22. package/dist/version-spE-k97g.js +289 -0
  23. package/dist/version-spE-k97g.js.map +1 -0
  24. package/dist/version.d.ts +2 -0
  25. package/package.json +42 -49
  26. package/src/RESTClient.ts +226 -0
  27. package/src/SDKError.ts +59 -0
  28. package/src/{cache.js → cache.ts} +52 -37
  29. package/src/{config.js → config.ts} +7 -32
  30. package/src/global-registry.ts +39 -0
  31. package/src/globals.ts +10 -0
  32. package/src/{identity.js → identity.ts} +536 -437
  33. package/{index.js → src/index.ts} +1 -3
  34. package/src/{monetization.js → monetization.ts} +77 -48
  35. package/src/{object.js → object.ts} +8 -15
  36. package/src/popup.ts +74 -0
  37. package/src/{spidTalk.js → spidTalk.ts} +10 -12
  38. package/src/{url.js → url.ts} +6 -10
  39. package/src/{validate.js → validate.ts} +26 -42
  40. package/src/{version.js → version.ts} +1 -2
  41. package/es5/global.js +0 -12968
  42. package/es5/global.js.map +0 -1
  43. package/es5/global.min.js +0 -2
  44. package/es5/global.min.js.map +0 -1
  45. package/es5/identity.js +0 -12212
  46. package/es5/identity.js.map +0 -1
  47. package/es5/identity.min.js +0 -2
  48. package/es5/identity.min.js.map +0 -1
  49. package/es5/index.js +0 -12940
  50. package/es5/index.js.map +0 -1
  51. package/es5/index.min.js +0 -2
  52. package/es5/index.min.js.map +0 -1
  53. package/es5/monetization.js +0 -9176
  54. package/es5/monetization.js.map +0 -1
  55. package/es5/monetization.min.js +0 -2
  56. package/es5/monetization.min.js.map +0 -1
  57. package/es5/payment.js +0 -8853
  58. package/es5/payment.js.map +0 -1
  59. package/es5/payment.min.js +0 -2
  60. package/es5/payment.min.js.map +0 -1
  61. package/identity.d.ts +0 -1
  62. package/identity.js +0 -5
  63. package/index.d.ts +0 -4
  64. package/monetization.d.ts +0 -1
  65. package/monetization.js +0 -5
  66. package/payment.d.ts +0 -1
  67. package/payment.js +0 -5
  68. package/src/RESTClient.d.ts +0 -89
  69. package/src/RESTClient.js +0 -193
  70. package/src/SDKError.d.ts +0 -16
  71. package/src/SDKError.js +0 -55
  72. package/src/__mocks__/.eslintrc.yml +0 -8
  73. package/src/__mocks__/RESTClient.js +0 -54
  74. package/src/cache.d.ts +0 -64
  75. package/src/config.d.ts +0 -34
  76. package/src/es5/global.js +0 -13
  77. package/src/es5/identity.js +0 -10
  78. package/src/es5/index.js +0 -13
  79. package/src/es5/monetization.js +0 -10
  80. package/src/es5/payment.js +0 -10
  81. package/src/global-registry.js +0 -20
  82. package/src/identity.d.ts +0 -679
  83. package/src/monetization.d.ts +0 -80
  84. package/src/payment.d.ts +0 -115
  85. package/src/payment.js +0 -211
  86. package/src/popup.d.ts +0 -10
  87. package/src/popup.js +0 -59
  88. package/src/url.d.ts +0 -10
  89. package/src/validate.d.ts +0 -64
  90. package/src/version.d.ts +0 -2
@@ -0,0 +1,370 @@
1
+ import { _ as e, a as t, c as n, d as r, f as i, g as a, h as o, i as s, l as c, m as l, n as u, o as d, p as f, r as p, s as m, t as h, u as g, v as _, y as v } from "./version-spE-k97g.js";
2
+ //#region src/popup.ts
3
+ var y = v();
4
+ function b(e) {
5
+ return m(g(e), `Object must be an object but it is '${e}'`), Object.keys(e).map((t) => `${t}=${e[t]}`).join(",");
6
+ }
7
+ var x = {
8
+ scrollbars: "yes",
9
+ location: "yes",
10
+ status: "no",
11
+ menubar: "no",
12
+ toolbar: "no",
13
+ resizable: "yes"
14
+ };
15
+ function S(e, t, r = "", i = {}) {
16
+ m(g(e), `window was supposed to be an object but it is ${e}`), m(g(e.screen), "window should be a valid Window object but it lacks a 'screen' property"), m(n(e.open), "window should be a valid Window object but it lacks an 'open' function"), m(f(t), "Invalid URL for popup");
17
+ let { height: a, width: o } = e.screen, s = d(x, i), { width: c, height: l } = s;
18
+ typeof c == "number" && Number.isFinite(c) && Number.isFinite(o) && (s.left = (o - c) / 2), typeof l == "number" && Number.isFinite(l) && Number.isFinite(a) && (s.top = (a - l) / 2);
19
+ let u = b(s);
20
+ return e.open(t, r, u);
21
+ }
22
+ //#endregion
23
+ //#region src/identity.ts
24
+ var C = "hasSession-cache", w = "sessionCallBlocked-cache", T = 1e3 * 60 * 5, E = "tab-id-cache", D = Math.floor(Math.random() * 1e5), O = 1e3 * 60 * 60 * 24 * 30, k = () => window, A = class extends y.TinyEmitter {
25
+ _sessionInitiatedSent;
26
+ window;
27
+ clientId;
28
+ sessionStorageCache;
29
+ localStorageCache;
30
+ redirectUri;
31
+ env;
32
+ log;
33
+ callbackBeforeRedirect;
34
+ _sessionDomain;
35
+ _enableSessionCaching;
36
+ _session;
37
+ _spid;
38
+ _oauthService;
39
+ _bffService;
40
+ _sessionService;
41
+ _globalSessionService;
42
+ _usedSessionServiceGetSessionEndpoint;
43
+ _hasSessionInProgress;
44
+ popup;
45
+ setVarnishCookie;
46
+ varnishExpiresIn;
47
+ varnishCookieDomain;
48
+ constructor({ clientId: t, redirectUri: n, sessionDomain: r, env: i = "PRE", log: a, window: o = k(), callbackBeforeRedirect: s = () => {} }) {
49
+ super(), m(c(t), "clientId parameter is required"), m(g(o), "The reference to window is missing"), m(!n || f(n), "redirectUri parameter is invalid"), m(c(r) && f(r), "sessionDomain parameter is not a valid URL"), u(o), this._sessionInitiatedSent = !1, this.window = o, this.clientId = t, this.sessionStorageCache = new e(() => this.window && this.window.sessionStorage), this.localStorageCache = new e(() => this.window && this.window.localStorage), this.redirectUri = n, this.env = i, this.log = a, this.callbackBeforeRedirect = s, this._sessionDomain = r, this._enableSessionCaching = !0, this._session = {}, this._setSessionServiceUrl(r), this._usedSessionServiceGetSessionEndpoint = this._sessionService.url.pathname && this._sessionService.url.pathname.length <= 1 ? "v2/session" : "session", this._setSpidServerUrl(i), this._setBffServerUrl(i), this._setOauthServerUrl(i), this._setGlobalSessionServiceUrl(i), this._unblockSessionCall(), l(o, "schIdentity", this);
50
+ }
51
+ _getTabId() {
52
+ if (this._enableSessionCaching) return this.sessionStorageCache.get(E) || (this.sessionStorageCache.set(E, D, O), D);
53
+ }
54
+ _isSessionCallBlocked() {
55
+ return this.localStorageCache.get(w);
56
+ }
57
+ _blockSessionCall() {
58
+ this.localStorageCache.set(w, !0, T);
59
+ }
60
+ _unblockSessionCall() {
61
+ this.localStorageCache.delete(w);
62
+ }
63
+ _setSpidServerUrl(e) {
64
+ m(r(e), `url parameter is invalid: ${e}`), this._spid = new p({
65
+ serverUrl: s(e, o.SPiD),
66
+ log: this.log,
67
+ defaultParams: {
68
+ client_id: this.clientId,
69
+ redirect_uri: this.redirectUri
70
+ }
71
+ });
72
+ }
73
+ _setOauthServerUrl(e) {
74
+ m(r(e), `url parameter is invalid: ${e}`), this._oauthService = new p({
75
+ serverUrl: s(e, o.SPiD),
76
+ log: this.log,
77
+ defaultParams: {
78
+ client_id: this.clientId,
79
+ redirect_uri: this.redirectUri
80
+ }
81
+ });
82
+ }
83
+ _setBffServerUrl(e) {
84
+ m(r(e), `url parameter is invalid: ${e}`), this._bffService = new p({
85
+ serverUrl: s(e, o.BFF),
86
+ log: this.log,
87
+ defaultParams: {
88
+ client_id: this.clientId,
89
+ redirect_uri: this.redirectUri
90
+ }
91
+ });
92
+ }
93
+ _setSessionServiceUrl(e) {
94
+ m(r(e), `domain parameter is invalid: ${e}`);
95
+ let t = `sdrn:${a[this.env]}:client:${this.clientId}`;
96
+ this._sessionService = new p({
97
+ serverUrl: e,
98
+ log: this.log,
99
+ defaultParams: {
100
+ client_sdrn: t,
101
+ redirect_uri: this.redirectUri,
102
+ sdk_version: h
103
+ }
104
+ });
105
+ }
106
+ _setGlobalSessionServiceUrl(e) {
107
+ m(r(e), `url parameter is invalid: ${e}`);
108
+ let t = `sdrn:${a[this.env]}:client:${this.clientId}`;
109
+ this._globalSessionService = new p({
110
+ serverUrl: s(e, o.SESSION_SERVICE),
111
+ log: this.log,
112
+ defaultParams: {
113
+ client_sdrn: t,
114
+ sdk_version: h
115
+ }
116
+ });
117
+ }
118
+ _emitSessionEvent(e, t) {
119
+ t.userId && this.emit("login", t), e.userId && !t.userId && this.emit("logout", t), e.userId && t.userId && e.userId !== t.userId && this.emit("userChange", t), e.userId || t.userId ? this.emit("sessionChange", t) : this.emit("notLoggedin", t), t.userId && !this._sessionInitiatedSent && (this._sessionInitiatedSent = !0, this.emit("sessionInit", t)), e.userStatus !== t.userStatus && this.emit("statusChange", t);
120
+ }
121
+ _closePopup() {
122
+ this.popup &&= (this.popup.closed || this.popup.close(), null);
123
+ }
124
+ enableVarnishCookie(e) {
125
+ let t = 0, n;
126
+ Number.isInteger(e) ? t = e : typeof e == "object" && (t = e.expiresIn || t, n = e.domain || n), m(Number.isInteger(t), "'expiresIn' must be an integer"), m(t >= 0, "'expiresIn' cannot be negative"), this.setVarnishCookie = !0, this.varnishExpiresIn = t, this.varnishCookieDomain = n;
127
+ }
128
+ _maybeSetVarnishCookie(e) {
129
+ if (!this.setVarnishCookie) return;
130
+ let t = /* @__PURE__ */ new Date();
131
+ if (this.varnishExpiresIn || typeof e.expiresIn == "number" && e.expiresIn > 0) {
132
+ let n = this.varnishExpiresIn || e.expiresIn;
133
+ t.setTime(t.getTime() + n * 1e3);
134
+ } else t.setTime(0);
135
+ let n = this.varnishCookieDomain || (typeof e.baseDomain == "string" ? e.baseDomain : document.domain) || "", r = [
136
+ `SP_ID=${e.sp_id}`,
137
+ `expires=${t.toUTCString()}`,
138
+ "path=/",
139
+ `domain=.${n}`
140
+ ].join("; ");
141
+ document.cookie = r;
142
+ }
143
+ _maybeClearVarnishCookie() {
144
+ this.setVarnishCookie && this._clearVarnishCookie();
145
+ }
146
+ _clearVarnishCookie() {
147
+ let e = this._session && typeof this._session.baseDomain == "string" ? this._session.baseDomain : document.domain, t = this.varnishCookieDomain || e || "";
148
+ document.cookie = `SP_ID=nothing; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; domain=.${t}`;
149
+ }
150
+ logSettings() {
151
+ if (!this.log && !window.console) throw new _("You have to provide log method in constructor");
152
+ let e = this.log || console.log, t = {
153
+ clientId: this.clientId,
154
+ redirectUri: this.redirectUri,
155
+ env: this.env,
156
+ sessionDomain: this._sessionDomain,
157
+ sdkVersion: h
158
+ };
159
+ e(`Schibsted account SDK for browsers settings: \n${JSON.stringify(t, null, 2)}`);
160
+ }
161
+ hasSession() {
162
+ if (this._isSessionCallBlocked()) return this._session;
163
+ if (this._hasSessionInProgress) return this._hasSessionInProgress;
164
+ let e = (e) => {
165
+ if (e.error) throw new _("HasSession failed", e.error);
166
+ return this._maybeSetVarnishCookie(e), this._emitSessionEvent(this._session, e), this._session = e, e;
167
+ }, t = (e = {}) => {
168
+ let t = Object.keys(e);
169
+ return t.length === 1 && t[0] === "redirectURL";
170
+ }, n = async () => {
171
+ if (this._enableSessionCaching) {
172
+ let t = this.sessionStorageCache.get(C);
173
+ if (t) return e(t);
174
+ }
175
+ let n = null;
176
+ try {
177
+ n = await this._sessionService.get(this._usedSessionServiceGetSessionEndpoint, { tabId: this._getTabId() });
178
+ } catch (e) {
179
+ if (e && e.code === 400 && this._enableSessionCaching) {
180
+ let t = 1e3 * (e.expiresIn || 300);
181
+ this.sessionStorageCache.set(C, { error: e }, t);
182
+ } else e && e.code >= 500 && e.code < 600 && this._enableSessionCaching && this.sessionStorageCache.set(C, { error: e }, 30 * 1e3);
183
+ throw e;
184
+ }
185
+ if (n) {
186
+ if (t(n)) return this._blockSessionCall(), await this.callbackBeforeRedirect(), this._sessionService.makeUrl(n.redirectURL, { tabId: this._getTabId() });
187
+ if (this._enableSessionCaching) {
188
+ let e = 1e3 * (n.expiresIn || 300);
189
+ this.sessionStorageCache.set(C, n, e);
190
+ }
191
+ }
192
+ return e(n);
193
+ };
194
+ return this._hasSessionInProgress = n().then((e) => (this._hasSessionInProgress = !1, f(e) && (this.window.location.href = e), e), (e) => {
195
+ throw this.emit("error", e), this._hasSessionInProgress = !1, new _("HasSession failed", e);
196
+ }), this._hasSessionInProgress;
197
+ }
198
+ async isLoggedIn() {
199
+ try {
200
+ return "result" in await this.hasSession();
201
+ } catch {
202
+ return !1;
203
+ }
204
+ }
205
+ clearCachedUserSession() {
206
+ this.sessionStorageCache.delete(C);
207
+ }
208
+ async isConnected() {
209
+ try {
210
+ return !!(await this.hasSession()).result;
211
+ } catch {
212
+ return !1;
213
+ }
214
+ }
215
+ async getUser() {
216
+ let e = await this.hasSession();
217
+ if (!e.result) throw new _("The user is not connected to this merchant");
218
+ return t(e);
219
+ }
220
+ async getUserId() {
221
+ let e = await this.hasSession();
222
+ if (e.userId && e.result) return e.userId;
223
+ throw new _("The user is not connected to this merchant");
224
+ }
225
+ async getExternalId(e, t = "") {
226
+ let { pairId: n } = await this.hasSession();
227
+ if (!n) throw new _("pairId missing in user session!");
228
+ if (!e || e.length === 0) throw new _("externalParty cannot be empty");
229
+ let r = (e) => Array.from(new Uint8Array(e)).map((e) => e.toString(16).padStart(2, "0")).join(""), i = (e) => crypto.subtle.digest("SHA-256", e);
230
+ return (async (e) => i(new TextEncoder().encode(e)).then((e) => r(e)))(((e, t, n) => n ? `${e}:${t}:${n}` : `${e}:${t}`)(n, e, t));
231
+ }
232
+ async getUserSDRN() {
233
+ let { sdrn: e } = await this.hasSession();
234
+ if (e) return e;
235
+ throw new _("Failed to get SDRN from user session");
236
+ }
237
+ async getUserUuid() {
238
+ let e = await this.hasSession();
239
+ if (e.uuid && e.result) return e.uuid;
240
+ throw new _("The user is not connected to this merchant");
241
+ }
242
+ async getUserContextData() {
243
+ try {
244
+ return await this._globalSessionService.get("user-context");
245
+ } catch {
246
+ return null;
247
+ }
248
+ }
249
+ login({ state: e, acrValues: t = "", scope: n = "openid", redirectUri: r = this.redirectUri, preferPopup: i = !1, loginHint: a = "", tag: o = "", teaser: s = "", maxAge: c = "", locale: l = "", oneStepLogin: u = !1, prompt: d = "select_account", xDomainId: f = "", xEnvironmentId: p = "", originCampaign: m = "" }) {
250
+ this._closePopup(), this.sessionStorageCache.delete(C);
251
+ let h = this.loginUrl({
252
+ state: e,
253
+ acrValues: t,
254
+ scope: n,
255
+ redirectUri: r,
256
+ loginHint: a,
257
+ tag: o,
258
+ teaser: s,
259
+ maxAge: c,
260
+ locale: l,
261
+ oneStepLogin: u,
262
+ prompt: d,
263
+ xDomainId: f,
264
+ xEnvironmentId: p,
265
+ originCampaign: m
266
+ });
267
+ return i && (this.popup = S(this.window, h, "Schibsted account", {
268
+ width: 360,
269
+ height: 570
270
+ }), this.popup) ? this.popup : (this.window.location.href = h, null);
271
+ }
272
+ async getSpId() {
273
+ try {
274
+ return (await this.hasSession()).sp_id || null;
275
+ } catch {
276
+ return null;
277
+ }
278
+ }
279
+ logout(e = this.redirectUri) {
280
+ this.sessionStorageCache.delete(C), this._maybeClearVarnishCookie(), this.emit("logout"), this.window.location.href = this.logoutUrl(e);
281
+ }
282
+ loginUrl({ state: e, acrValues: t = "", scope: n = "openid", redirectUri: r = this.redirectUri, loginHint: a = "", tag: o = "", teaser: s = "", maxAge: l = "", locale: u = "", oneStepLogin: d = !1, prompt: p = "select_account", xDomainId: h = "", xEnvironmentId: g = "", originCampaign: _ = "" }, ...v) {
283
+ return typeof arguments[0] != "object" && (e = arguments[0], t = arguments[1], n = arguments[2] || n, r = arguments[3] || r, a = arguments[4] || a, o = arguments[5] || o, s = arguments[6] || s, l = isNaN(arguments[7]) ? l : arguments[7]), m(!t || i(t, ["", "otp-email"], !0) || t.split(" ").every((e) => i(e, [
284
+ "password",
285
+ "otp",
286
+ "sms",
287
+ "eid-dk",
288
+ "eid-no",
289
+ "eid-se",
290
+ "eid-fi",
291
+ "eid"
292
+ ], !0)), `The acrValues parameter is not acceptable: ${t}`), m(f(r), `loginUrl(): redirectUri must be a valid url but is ${r}`), m(c(e), `the state parameter should be a non empty string but it is ${e}`), this._oauthService.makeUrl("oauth/authorize", {
293
+ response_type: "code",
294
+ redirect_uri: r,
295
+ scope: n,
296
+ state: e,
297
+ acr_values: t,
298
+ login_hint: a,
299
+ tag: o,
300
+ teaser: s,
301
+ max_age: l,
302
+ locale: u,
303
+ one_step_login: d || "",
304
+ prompt: t ? "" : p,
305
+ x_domain_id: h,
306
+ x_env_id: g,
307
+ utm_campaign: _
308
+ });
309
+ }
310
+ logoutUrl(e = this.redirectUri) {
311
+ m(f(e), "logoutUrl(): redirectUri is invalid");
312
+ let t = { redirect_uri: e };
313
+ return this._sessionService.makeUrl("logout", t);
314
+ }
315
+ accountUrl(e = this.redirectUri) {
316
+ return this._spid.makeUrl("profile-pages", {
317
+ response_type: "code",
318
+ redirect_uri: e
319
+ });
320
+ }
321
+ phonesUrl(e = this.redirectUri) {
322
+ return this._spid.makeUrl("profile-pages/about-you/phone", {
323
+ response_type: "code",
324
+ redirect_uri: e
325
+ });
326
+ }
327
+ async showSimplifiedLoginWidget(e, t) {
328
+ let n = await this.getUserContextData(), r = { client_id: this.clientId };
329
+ t && t.encoding && (r.encoding = t.encoding);
330
+ let i = this._bffService.makeUrl("simplified-login-widget", r, !1), a = async (e) => (typeof e.state == "function" && (e.state = await e.state()), e);
331
+ return new Promise((r, o) => {
332
+ if (!n || !n.display_text || !n.identifier) return o(new _("Missing user data"));
333
+ let s = {
334
+ displayText: n.display_text,
335
+ env: this.env,
336
+ clientName: n.client_name,
337
+ clientId: this.clientId,
338
+ providerId: n.provider_id,
339
+ windowWidth: () => window.innerWidth,
340
+ windowOnResize: (e) => {
341
+ window.onresize = e;
342
+ }
343
+ };
344
+ t && t.locale && (s.locale = t.locale);
345
+ let c = async () => {
346
+ this.login(Object.assign(await a(e), { loginHint: n.identifier }));
347
+ }, l = async () => {
348
+ this.login(Object.assign(await a(e), {
349
+ loginHint: n.identifier,
350
+ prompt: "login"
351
+ }));
352
+ }, u = () => {
353
+ this.emit("simplifiedLoginOpened");
354
+ }, d = () => {
355
+ this.emit("simplifiedLoginCancelled");
356
+ };
357
+ if (window.openSimplifiedLoginWidget) return window.openSimplifiedLoginWidget(s, c, l, u, d), r(!0);
358
+ let f = document.createElement("script");
359
+ f.type = "text/javascript", f.src = i, f.onload = () => {
360
+ window.openSimplifiedLoginWidget(s, c, l, u, d), r(!0);
361
+ }, f.onerror = () => {
362
+ o(new _("Error when loading simplified login widget content"));
363
+ }, document.getElementsByTagName("body")[0].appendChild(f);
364
+ });
365
+ }
366
+ };
367
+ //#endregion
368
+ export { A as t };
369
+
370
+ //# sourceMappingURL=identity-s4nofYmB.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identity-s4nofYmB.js","names":[],"sources":["../src/popup.ts","../src/identity.ts"],"sourcesContent":["/* Copyright 2024 Schibsted Products & Technology AS. Licensed under the terms of the MIT license.\n * See LICENSE.md in the project root.\n */\n\nimport { cloneDefined } from './object.js';\nimport { assert, isFunction, isObject, isUrl } from './validate.js';\n\n/**\n * Serializes an object to string.\n * @private\n * @param obj - for example {a: 'b', c: 1}\n */\nfunction serialize(obj: Record<string, unknown>): string {\n assert(isObject(obj), `Object must be an object but it is '${obj}'`);\n return Object.keys(obj)\n .map((key) => `${key}=${obj[key]}`)\n .join(',');\n}\n\nconst defaultWindowFeatures = {\n scrollbars: 'yes',\n location: 'yes',\n status: 'no',\n menubar: 'no',\n toolbar: 'no',\n resizable: 'yes',\n};\n\n/**\n * Opens a popup\n * @param parentWindow - A reference to the window that will open the popup\n * @param url - The URL that the popup will open\n * @param windowName - A name for the window\n * @param windowFeatures - Window features for the popup (default ones are usually ok)\n * @private\n */\nexport function open(\n parentWindow: Window,\n url: string,\n windowName = '',\n windowFeatures: Record<string, string | number> = {},\n): Window | null {\n assert(isObject(parentWindow), `window was supposed to be an object but it is ${parentWindow}`);\n assert(\n isObject(parentWindow.screen),\n `window should be a valid Window object but it lacks a 'screen' property`,\n );\n assert(\n isFunction(parentWindow.open),\n `window should be a valid Window object but it lacks an 'open' function`,\n );\n assert(isUrl(url), 'Invalid URL for popup');\n\n const { height, width } = parentWindow.screen;\n\n const mergedFeatures = cloneDefined(defaultWindowFeatures, windowFeatures);\n const { width: featureWidth, height: featureHeight } = mergedFeatures;\n if (\n typeof featureWidth === 'number' &&\n Number.isFinite(featureWidth) &&\n Number.isFinite(width)\n ) {\n mergedFeatures.left = (width - featureWidth) / 2;\n }\n if (\n typeof featureHeight === 'number' &&\n Number.isFinite(featureHeight) &&\n Number.isFinite(height)\n ) {\n mergedFeatures.top = (height - featureHeight) / 2;\n }\n const features = serialize(mergedFeatures);\n return parentWindow.open(url, windowName, features);\n}\n","/* Copyright 2024 Schibsted Products & Technology AS. Licensed under the terms of the MIT license.\n * See LICENSE.md in the project root.\n */\n\nimport { TinyEmitter } from 'tiny-emitter';\nimport Cache from './cache.js';\nimport { ENDPOINTS, NAMESPACE } from './config.js';\nimport { registerAndDispatchInGlobal } from './global-registry.js';\nimport { cloneDeep } from './object.js';\nimport * as popup from './popup.js';\nimport RESTClient from './RESTClient.js';\nimport SDKError from './SDKError.js';\nimport * as spidTalk from './spidTalk.js';\nimport { urlMapper } from './url.js';\nimport { assert, isNonEmptyString, isObject, isStr, isStrIn, isUrl } from './validate.js';\nimport version from './version.js';\n\n/**\n * Options accepted by {@link Identity#login} and related login URL helpers.\n */\nexport type LoginOptions = {\n /**\n * An opaque value used by the client to maintain state between the request and callback.\n * It's also recommended to prevent CSRF {@link https://tools.ietf.org/html/rfc6749#section-10.12}\n */\n state: string;\n /**\n * Authentication Context Class Reference Values. If omitted, the user will be asked to\n * authenticate using username+password. For 2FA (Two-Factor Authentication) possible values\n * are `sms`, `otp` (one time password), `password` (will force password confirmation, even if\n * user is already logged in), `eid`. Those values might be mixed as space-separated string.\n * To make sure that user has authenticated with 2FA you need to verify AMR (Authentication\n * Methods References) claim in ID token. Might also be used to ensure additional acr\n * (sms, otp, eid) for already logged in users. Supported value is also 'otp-email' means one\n * time password using email.\n */\n acrValues?: string;\n /**\n * The OAuth scopes for the tokens. This is a list of scopes, separated by space. If the list\n * of scopes contains `openid`, the generated tokens includes the id token which can be useful\n * for getting information about the user. Omitting scope is allowed, while `invalid_scope` is\n * returned when the client asks for a scope you aren't allowed to request.\n * {@link https://tools.ietf.org/html/rfc6749#section-3.3}\n * Defaults to `openid`.\n */\n scope?: string;\n /**\n * Redirect uri that will receive the code. Must exactly match a redirectUri from your client\n * in self-service\n */\n redirectUri?: string;\n /** Should we try to open a popup window? Defaults to `false`. */\n preferPopup?: boolean;\n /** user email or UUID hint */\n loginHint?: string;\n /** Pulse tag */\n tag?: string;\n /** Teaser slug. Teaser with given slug will be displayed in place of default teaser */\n teaser?: string;\n /**\n * Specifies the allowable elapsed time in seconds since the last time the End-User was actively\n * authenticated. If last authentication time is more than maxAge seconds in the past,\n * re-authentication will be required. See the OpenID Connect spec section 3.1.2.1 for more\n * information\n */\n maxAge?: number | string;\n /**\n * Optional parameter to overwrite client locale setting.\n * New flows supports nb_NO, fi_FI, sv_SE, en_US\n */\n locale?: string;\n /** display username and password on one screen. Defaults to `false`. */\n oneStepLogin?: boolean;\n /**\n * String that specifies whether the Authorization Server prompts the End-User for\n * reauthentication or confirm account screen. Supported values: `select_account` or `login`.\n * Defaults to `select_account`.\n */\n prompt?: string;\n /** Identifier for cross-domain tracking in Pulse */\n xDomainId?: string;\n /** Environment for cross-domain tracking in Pulse */\n xEnvironmentId?: string;\n /** Campaign identifier for tracking in Pulse */\n originCampaign?: string;\n};\n\n/**\n * Identical to {@link LoginOptions} except that `state` may also be a (possibly async) function;\n * all other fields reuse the `LoginOptions` documentation.\n */\nexport type SimplifiedLoginWidgetLoginOptions = Omit<LoginOptions, 'state'> & {\n /**\n * An opaque value used by the client to maintain state between the request and callback.\n * It's also recommended to prevent CSRF {@link https://tools.ietf.org/html/rfc6749#section-10.12}\n */\n state: string | (() => string | Promise<string>);\n};\n\n/**\n * Successful response returned from {@link Identity#hasSession}.\n */\nexport type HasSessionSuccessResponse = {\n /**\n * Is the user connected to the merchant? (it means that the merchant id is in the list of\n * merchants listed of this user in the database)? Example: false\n */\n result: boolean;\n /** Example: 'notConnected' or 'connected'. Deprecated, use `Identity.isConnected()` */\n userStatus: string;\n /** Example: 'localhost' */\n baseDomain: string;\n /** Example: '58eca10fdbb9f6df72c3368f'. Obsolete */\n id: string;\n /** Example: 37162 */\n userId: number;\n /** Example: 'b3b23aa7-34f2-5d02-a10e-5a3455c6ab2c' */\n uuid: string;\n /** Example: 'eyJjbGllbnRfaWQ...' */\n sp_id: string;\n /** Example: 30 * 60 * 1000 (for 30 minutes) */\n expiresIn: number;\n /** Example: 1506285759 */\n serverTime: number;\n /**\n * Example: 'NCdzXaz4ZRb7...' The sig parameter is a concatenation of an HMAC SHA-256 signature\n * string, a dot (.) and a base64url encoded JSON object (session).\n * {@link http://techdocs.spid.no/sdks/js/response-signature-and-validation/}\n */\n sig: string;\n /** (Only for connected users) Example: 'batman' */\n displayName: string;\n /** (Only for connected users) Example: 'Bruce' */\n givenName: string;\n /** (Only for connected users) Example: 'Wayne' */\n familyName: string;\n /** (Only for connected users) Example: 'male', 'female', 'undisclosed' */\n gender: string;\n /** (Only for connected users) Example: 'http://www.srv.com/some/picture.jpg' */\n photo: string;\n /** (Only for connected users) */\n tracking: boolean;\n /** (Only for connected users) */\n clientAgreementAccepted: boolean;\n /** (Only for connected users) */\n defaultAgreementAccepted: boolean;\n pairId: string;\n sdrn: string;\n};\n\n/**\n * Failure response returned from {@link Identity#hasSession}.\n */\nexport type HasSessionFailureResponse = {\n error: {\n /** Typically an HTTP response code. Example: 401 */\n code: number;\n /** Example: \"No session found!\" */\n description: string;\n /** Example: \"UserException\" */\n type: string;\n };\n response: {\n /** Example: \"localhost\" */\n baseDomain: string;\n /** Time span in milliseconds. Example: 30 * 60 * 1000 (for 30 minutes) */\n expiresIn: number;\n result: boolean;\n /** Server time in seconds since the Unix Epoch. Example: 1506287788 */\n serverTime: number;\n };\n};\n\n/**\n * Minimal user information used by the simplified login widget flow.\n */\nexport type SimplifiedLoginData = {\n /** Deprecated: User UUID, to be be used as `loginHint` for {@link Identity#login} */\n identifier: string;\n /** Human-readable user identifier */\n display_text: string;\n /** Client name */\n client_name: string;\n};\n\n/**\n * Configuration options for {@link Identity#showSimplifiedLoginWidget}.\n */\nexport type SimplifiedLoginWidgetOptions = {\n /** expected encoding of simplified login widget. Could be utf-8 (default), iso-8859-1 or iso-8859-15 */\n encoding: string;\n /**\n * expected locale of simplified login widget. Should be provided in a short format like 'nb',\n * 'sv'. If not set, a value from the env variable is used.\n */\n locale?: 'nb' | 'sv' | 'fi' | 'da' | 'en';\n};\n\n/**\n * Emitted when an error happens (useful for debugging)\n * @event Identity#error\n */\n\nconst HAS_SESSION_CACHE_KEY = 'hasSession-cache';\nconst SESSION_CALL_BLOCKED_CACHE_KEY = 'sessionCallBlocked-cache';\nconst SESSION_CALL_BLOCKED_TTL = 1000 * 60 * 5;\n\nconst TAB_ID_KEY = 'tab-id-cache';\nconst TAB_ID = Math.floor(Math.random() * 100000);\nconst TAB_ID_TTL = 1000 * 60 * 60 * 24 * 30;\n\nconst globalWindow = () => window;\n\n/**\n * Provides Identity functionalty to a web page\n */\nexport class Identity extends TinyEmitter {\n _sessionInitiatedSent: boolean;\n window: any;\n clientId: string;\n sessionStorageCache: any;\n localStorageCache: any;\n redirectUri: string;\n env: string;\n log?: Function;\n callbackBeforeRedirect: Function;\n _sessionDomain: string;\n _enableSessionCaching: boolean;\n _session: any;\n _spid!: RESTClient;\n _oauthService!: RESTClient;\n _bffService!: RESTClient;\n _sessionService!: RESTClient;\n _globalSessionService!: RESTClient;\n _usedSessionServiceGetSessionEndpoint: any;\n _hasSessionInProgress?: boolean | Promise<any>;\n popup?: Window | null;\n setVarnishCookie?: boolean;\n varnishExpiresIn?: number;\n varnishCookieDomain?: string;\n\n /**\n * @param options\n * @param options.clientId - Example: \"1234567890abcdef12345678\"\n * @param options.sessionDomain - Example: \"https://id.site.com\"\n * @param options.redirectUri - Example: \"https://site.com\"\n * @param options.env - Schibsted account environment: `PRE` (default), `PRO`, `PRO_NO`, `PRO_FI` or `PRO_DK`\n * @param options.log - A function that receives debug log information. If not set,\n * no logging will be done\n * @param options.window - window object\n * @param options.callbackBeforeRedirect - callback triggered before session refresh redirect happen\n * @throws {SDKError} - If any of options are invalid\n */\n constructor({\n clientId,\n redirectUri,\n sessionDomain,\n env = 'PRE',\n log,\n window = globalWindow(),\n callbackBeforeRedirect = () => {},\n }: {\n clientId: string;\n sessionDomain: string;\n redirectUri: string;\n env?: string;\n log?: Function;\n window?: Window;\n callbackBeforeRedirect?: Function;\n }) {\n super();\n assert(isNonEmptyString(clientId), 'clientId parameter is required');\n assert(isObject(window), 'The reference to window is missing');\n assert(!redirectUri || isUrl(redirectUri), 'redirectUri parameter is invalid');\n assert(\n isNonEmptyString(sessionDomain) && isUrl(sessionDomain),\n 'sessionDomain parameter is not a valid URL',\n );\n\n spidTalk.emulate(window);\n this._sessionInitiatedSent = false;\n this.window = window;\n this.clientId = clientId;\n this.sessionStorageCache = new Cache(() => this.window && this.window.sessionStorage);\n this.localStorageCache = new Cache(() => this.window && this.window.localStorage);\n this.redirectUri = redirectUri;\n this.env = env;\n this.log = log;\n this.callbackBeforeRedirect = callbackBeforeRedirect;\n this._sessionDomain = sessionDomain;\n\n // Internal hack: set to false to always refresh from hassession\n this._enableSessionCaching = true;\n\n // Old session\n this._session = {};\n\n this._setSessionServiceUrl(sessionDomain);\n this._usedSessionServiceGetSessionEndpoint =\n this._sessionService.url.pathname && this._sessionService.url.pathname.length <= 1\n ? 'v2/session'\n : 'session';\n\n this._setSpidServerUrl(env);\n this._setBffServerUrl(env);\n this._setOauthServerUrl(env);\n this._setGlobalSessionServiceUrl(env);\n\n this._unblockSessionCall();\n\n registerAndDispatchInGlobal(window, 'schIdentity', this);\n }\n\n /**\n * Read tabId from session storage\n * @private\n */\n _getTabId(): number | undefined {\n if (this._enableSessionCaching) {\n const tabId = this.sessionStorageCache.get(TAB_ID_KEY);\n if (!tabId) {\n this.sessionStorageCache.set(TAB_ID_KEY, TAB_ID, TAB_ID_TTL);\n return TAB_ID;\n }\n\n return tabId;\n }\n }\n\n /**\n * Checks if getting session is blocked\n * @private\n *\n */\n _isSessionCallBlocked(): boolean | void {\n return this.localStorageCache.get(SESSION_CALL_BLOCKED_CACHE_KEY);\n }\n\n /**\n * Block calls to get session\n * @private\n *\n */\n _blockSessionCall(): void {\n const SESSION_CALL_BLOCKED = true;\n\n this.localStorageCache.set(\n SESSION_CALL_BLOCKED_CACHE_KEY,\n SESSION_CALL_BLOCKED,\n SESSION_CALL_BLOCKED_TTL,\n );\n }\n\n /**\n * Unblocks calls to get session\n * @private\n *\n */\n _unblockSessionCall(): void {\n this.localStorageCache.delete(SESSION_CALL_BLOCKED_CACHE_KEY);\n }\n\n /**\n * Set SPiD server URL\n * @private\n * @param url - real URL or 'PRE' style key\n */\n _setSpidServerUrl(url: string): void {\n assert(isStr(url), `url parameter is invalid: ${url}`);\n this._spid = new RESTClient({\n serverUrl: urlMapper(url, ENDPOINTS.SPiD),\n log: this.log,\n defaultParams: { client_id: this.clientId, redirect_uri: this.redirectUri },\n });\n }\n\n /**\n * Set OAuth server URL\n * @private\n * @param url - real URL or 'PRE' style key\n */\n _setOauthServerUrl(url: string): void {\n assert(isStr(url), `url parameter is invalid: ${url}`);\n this._oauthService = new RESTClient({\n serverUrl: urlMapper(url, ENDPOINTS.SPiD),\n log: this.log,\n defaultParams: { client_id: this.clientId, redirect_uri: this.redirectUri },\n });\n }\n\n /**\n * Set BFF server URL\n * @private\n * @param url - real URL or 'PRE' style key\n */\n _setBffServerUrl(url: string): void {\n assert(isStr(url), `url parameter is invalid: ${url}`);\n this._bffService = new RESTClient({\n serverUrl: urlMapper(url, ENDPOINTS.BFF),\n log: this.log,\n defaultParams: { client_id: this.clientId, redirect_uri: this.redirectUri },\n });\n }\n\n /**\n * Set site-specific session-service domain\n * @private\n * @param domain - real URL — (**not** 'PRE' style env key)\n */\n _setSessionServiceUrl(domain: string): void {\n assert(isStr(domain), `domain parameter is invalid: ${domain}`);\n const client_sdrn = `sdrn:${NAMESPACE[this.env as keyof typeof NAMESPACE]}:client:${this.clientId}`;\n this._sessionService = new RESTClient({\n serverUrl: domain,\n log: this.log,\n defaultParams: { client_sdrn, redirect_uri: this.redirectUri, sdk_version: version },\n });\n }\n\n /**\n * Set global session-service server URL\n * @private\n * @param url - real URL or 'PRE' style key\n */\n _setGlobalSessionServiceUrl(url: string): void {\n assert(isStr(url), `url parameter is invalid: ${url}`);\n const client_sdrn = `sdrn:${NAMESPACE[this.env as keyof typeof NAMESPACE]}:client:${this.clientId}`;\n this._globalSessionService = new RESTClient({\n serverUrl: urlMapper(url, ENDPOINTS.SESSION_SERVICE),\n log: this.log,\n defaultParams: { client_sdrn, sdk_version: version },\n });\n }\n\n /**\n * Emits the relevant events based on the previous and new reply from hassession\n * @private\n * @param previous\n * @param current\n */\n _emitSessionEvent(previous: any, current: any): void {\n /**\n * Emitted when the user is logged in (This happens as a result of calling\n * {@link Identity#hasSession}, so it is also emitted if the user was previously logged in)\n * @event Identity#login\n */\n if (current.userId) {\n this.emit('login', current);\n }\n /**\n * Emitted when the user logged out\n * @event Identity#logout\n */\n if (previous.userId && !current.userId) {\n this.emit('logout', current);\n }\n /**\n * Emitted when the user is changed. This happens as a result of calling\n * {@link Identity#hasSession}, and is emitted if there was a user both before and after\n * this invocation, and the userId has now changed\n * @event Identity#userChange\n */\n if (previous.userId && current.userId && previous.userId !== current.userId) {\n this.emit('userChange', current);\n }\n if (previous.userId || current.userId) {\n /**\n * Emitted when the session is changed. More accurately, this event is emitted if there\n * was a logged-in user either before or after {@link Identity#hasSession} was called.\n * In practice, this means the event is emitted a lot\n * @event Identity#sessionChange\n */\n this.emit('sessionChange', current);\n } else {\n /**\n * Emitted when there is no logged-in user. More specifically, it means that there was\n * no logged-in user neither before nor after {@link Identity#hasSession} was called\n * @event Identity#notLoggedin\n */\n this.emit('notLoggedin', current);\n }\n /**\n * Emitted when the session is first created\n * @event Identity#sessionInit\n */\n if (current.userId && !this._sessionInitiatedSent) {\n this._sessionInitiatedSent = true;\n this.emit('sessionInit', current);\n }\n /**\n * Emitted when the user status changes. This happens as a result of calling\n * {@link Identity#hasSession}\n * @event Identity#statusChange\n */\n if (previous.userStatus !== current.userStatus) {\n this.emit('statusChange', current);\n }\n }\n\n /**\n * Close this.popup if it exists and is open\n * @private\n */\n _closePopup(): void {\n if (this.popup) {\n if (!this.popup.closed) {\n this.popup.close();\n }\n this.popup = null;\n }\n }\n\n /**\n * Set the Varnish cookie (`SP_ID`) when hasSession() is called. Note that most browsers require\n * that you are on a \"real domain\" for this to work — so, **not** `localhost`\n * @param options\n * @param options.expiresIn Override this to set number of seconds before the varnish\n * cookie expires. The default is to use the same time that hasSession responses are cached for\n * @param options.domain Override cookie domain. E.g. «vg.no» instead of «www.vg.no»\n */\n enableVarnishCookie(options?: { expiresIn?: number; domain?: string }): void {\n let expiresIn = 0;\n let domain: string | undefined;\n if (Number.isInteger(options)) {\n expiresIn = options as any;\n } else if (typeof options == 'object') {\n expiresIn = (options as any).expiresIn || expiresIn;\n domain = (options as any).domain || domain;\n }\n\n assert(Number.isInteger(expiresIn), `'expiresIn' must be an integer`);\n assert(expiresIn >= 0, `'expiresIn' cannot be negative`);\n this.setVarnishCookie = true;\n this.varnishExpiresIn = expiresIn;\n this.varnishCookieDomain = domain;\n }\n\n /**\n * Set the Varnish cookie if configured\n * @private\n * @param sessionData\n */\n _maybeSetVarnishCookie(sessionData: HasSessionSuccessResponse): void {\n if (!this.setVarnishCookie) {\n return;\n }\n const date = new Date();\n const validExpires =\n this.varnishExpiresIn ||\n (typeof sessionData.expiresIn === 'number' && sessionData.expiresIn > 0);\n if (validExpires) {\n const expires = this.varnishExpiresIn || sessionData.expiresIn;\n date.setTime(date.getTime() + expires * 1000);\n } else {\n date.setTime(0);\n }\n\n // If the domain is missing or of the wrong type, we'll use document.domain\n const domain =\n this.varnishCookieDomain ||\n (typeof sessionData.baseDomain === 'string'\n ? sessionData.baseDomain\n : document.domain) ||\n '';\n\n const cookie = [\n `SP_ID=${sessionData.sp_id}`,\n `expires=${date.toUTCString()}`,\n `path=/`,\n `domain=.${domain}`,\n ].join('; ');\n document.cookie = cookie;\n }\n\n /**\n * Clear the Varnish cookie if configured\n * @private\n */\n _maybeClearVarnishCookie(): void {\n if (this.setVarnishCookie) {\n this._clearVarnishCookie();\n }\n }\n\n /**\n * Clear the Varnish cookie\n * @private\n */\n _clearVarnishCookie(): void {\n const baseDomain =\n this._session && typeof this._session.baseDomain === 'string'\n ? this._session.baseDomain\n : document.domain;\n\n const domain = this.varnishCookieDomain || baseDomain || '';\n\n document.cookie = `SP_ID=nothing; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; domain=.${domain}`;\n }\n\n /**\n * Log used settings and version\n * @throws {SDKError} - If log method is not provided\n */\n logSettings(): void {\n if (!this.log && !window.console) {\n throw new SDKError('You have to provide log method in constructor');\n }\n\n const log = this.log || console.log;\n\n const settings = {\n clientId: this.clientId,\n redirectUri: this.redirectUri,\n env: this.env,\n sessionDomain: this._sessionDomain,\n sdkVersion: version,\n };\n\n log(`Schibsted account SDK for browsers settings: \\n${JSON.stringify(settings, null, 2)}`);\n }\n\n /**\n * @summary Queries the hassession endpoint and returns information about the status of the user\n * @remarks When we send a request to this endpoint, cookies sent along with the request\n * determines the status of the user.\n * @throws {SDKError} - If the call to the hasSession service fails in any way (this will happen\n * if, say, the user is not logged in)\n * @fires Identity#login\n * @fires Identity#logout\n * @fires Identity#userChange\n * @fires Identity#sessionChange\n * @fires Identity#notLoggedin\n * @fires Identity#sessionInit\n * @fires Identity#statusChange\n * @fires Identity#error\n */\n hasSession(): Promise<HasSessionSuccessResponse | HasSessionFailureResponse> {\n const isSessionCallBlocked = this._isSessionCallBlocked();\n if (isSessionCallBlocked) {\n return this._session;\n }\n\n if (this._hasSessionInProgress) {\n return this._hasSessionInProgress as Promise<\n HasSessionSuccessResponse | HasSessionFailureResponse\n >;\n }\n\n const _postProcess = (sessionData: any) => {\n if (sessionData.error) {\n throw new SDKError('HasSession failed', sessionData.error);\n }\n this._maybeSetVarnishCookie(sessionData);\n this._emitSessionEvent(this._session, sessionData);\n this._session = sessionData;\n return sessionData;\n };\n\n const _checkRedirectionNeed = (sessionData: any = {}) => {\n const sessionDataKeys = Object.keys(sessionData);\n\n return sessionDataKeys.length === 1 && sessionDataKeys[0] === 'redirectURL';\n };\n\n const _getSession = async () => {\n if (this._enableSessionCaching) {\n // Try to resolve from cache (it has a TTL)\n const cachedSession = this.sessionStorageCache.get(HAS_SESSION_CACHE_KEY);\n if (cachedSession) {\n return _postProcess(cachedSession);\n }\n }\n let sessionData = null;\n try {\n sessionData = await this._sessionService.get(\n this._usedSessionServiceGetSessionEndpoint,\n { tabId: this._getTabId() },\n );\n } catch (err: any) {\n if (err && err.code === 400 && this._enableSessionCaching) {\n const expiresIn = 1000 * (err.expiresIn || 300);\n this.sessionStorageCache.set(HAS_SESSION_CACHE_KEY, { error: err }, expiresIn);\n } else if (err && err.code >= 500 && err.code < 600 && this._enableSessionCaching) {\n // Temporary fix: 30 seconds cache to limit number of calls when service is unavailable\n this.sessionStorageCache.set(HAS_SESSION_CACHE_KEY, { error: err }, 30 * 1000);\n }\n throw err;\n }\n\n if (sessionData) {\n // for expiring session and safari browser do full page redirect to gain new session\n if (_checkRedirectionNeed(sessionData)) {\n this._blockSessionCall();\n\n await this.callbackBeforeRedirect();\n\n return this._sessionService.makeUrl(sessionData.redirectURL, {\n tabId: this._getTabId(),\n });\n }\n\n if (this._enableSessionCaching) {\n const expiresIn = 1000 * (sessionData.expiresIn || 300);\n this.sessionStorageCache.set(HAS_SESSION_CACHE_KEY, sessionData, expiresIn);\n }\n }\n\n return _postProcess(sessionData);\n };\n this._hasSessionInProgress = _getSession().then(\n (sessionData) => {\n this._hasSessionInProgress = false;\n\n if (isUrl(sessionData)) {\n this.window.location.href = sessionData;\n return sessionData;\n }\n\n return sessionData;\n },\n (err) => {\n this.emit('error', err);\n this._hasSessionInProgress = false;\n throw new SDKError('HasSession failed', err);\n },\n );\n\n return this._hasSessionInProgress as Promise<\n HasSessionSuccessResponse | HasSessionFailureResponse\n >;\n }\n\n /**\n * @summary Allows the client app to check if the user is logged in to Schibsted account\n * @remarks This function calls {@link Identity#hasSession} internally and thus has the side\n * effect that it might perform an auto-login on the user\n */\n async isLoggedIn(): Promise<boolean> {\n try {\n const data = await this.hasSession();\n return 'result' in data;\n } catch (_) {\n return false;\n }\n }\n\n /**\n * Removes the cached user session.\n */\n clearCachedUserSession(): void {\n this.sessionStorageCache.delete(HAS_SESSION_CACHE_KEY);\n }\n\n /**\n * @summary Allows the caller to check if the current user is connected to the client_id in\n * Schibsted account. Being connected means that the user has agreed for their account to be\n * used by your web app and have accepted the required terms\n * @remarks This function calls {@link Identity#hasSession} internally and thus has the side\n * effect that it might perform an auto-login on the user\n * @summary Check if the user is connected to the client_id\n */\n async isConnected(): Promise<boolean> {\n try {\n const data = (await this.hasSession()) as any;\n // if data is not an object, the promise will fail.\n // if the result is present, it's boolean. But if it's not, it should be assumed false.\n return !!data.result;\n } catch (_) {\n return false;\n }\n }\n\n /**\n * @summary Returns information about the user\n * @remarks This function calls {@link Identity#hasSession} internally and thus has the side\n * effect that it might perform an auto-login on the user\n * @throws {SDKError} If the user isn't connected to the merchant\n * @throws {SDKError} If we couldn't get the user\n */\n async getUser(): Promise<HasSessionSuccessResponse> {\n const user = (await this.hasSession()) as any;\n if (!user.result) {\n throw new SDKError('The user is not connected to this merchant');\n }\n return cloneDeep(user);\n }\n\n /**\n * @summary\n * In Schibsted account, there are multiple ways of identifying a user; the `userId`,\n * `uuid` and `externalId` used for identifying a user-merchant pair (see {@link Identity#getExternalId}).\n * There are reasons for them all to exist. The `userId` is a numeric identifier, but\n * since Schibsted account is deployed separately in Norway and Sweden, there are a lot of\n * duplicates. The `userId` was introduced early, so many sites still need to use them for\n * legacy reasons. The `uuid` is universally unique, and so — if we could disregard a lot of\n * Schibsted components depending on the numeric `userId` — it would be a good identifier to use\n * @remarks This function calls {@link Identity#hasSession} internally and thus has the side\n * effect that it might perform an auto-login on the user\n * @throws {SDKError} If the user isn't connected to the merchant\n * @return The `userId` field (not to be confused with the `uuid`)\n */\n async getUserId(): Promise<string> {\n const user = (await this.hasSession()) as any;\n if (user.userId && user.result) {\n return user.userId;\n }\n throw new SDKError('The user is not connected to this merchant');\n }\n\n /**\n * @function\n * @summary\n * Retrieves the external identifier (`externalId`) for the authenticated user.\n *\n * In Schibsted Account there are multiple ways of identifying users, however for integrations with\n * third-parties it's recommended to use `externalId` as it does not disclose\n * any critical data whilst allowing for user identification.\n *\n * `externalId` is merchant-scoped using a pairwise identifier (`pairId`),\n * meaning the same user's ID will differ between merchants.\n * Additionally, this identifier is bound to the external party provided as argument.\n *\n * @param externalParty\n * @param optionalSuffix\n * @remarks This function calls {@link Identity#hasSession} internally and thus has the side\n * effect that it might perform an auto-login on the user\n * @throws {SDKError} If the `pairId` is missing in user session.\n * @throws {SDKError} If the `externalParty` is not defined\n * @return The merchant- and 3rd-party-specific `externalId`\n */\n async getExternalId(externalParty: string, optionalSuffix: string = ''): Promise<string> {\n const { pairId } = (await this.hasSession()) as any;\n\n if (!pairId) throw new SDKError('pairId missing in user session!');\n\n if (!externalParty || externalParty.length === 0) {\n throw new SDKError('externalParty cannot be empty');\n }\n const _toHexDigest = (hashBuffer: any) => {\n // convert buffer to byte array\n const hashArray = Array.from(new Uint8Array(hashBuffer));\n // convert bytes to hex string\n return hashArray.map((b) => b.toString(16).padStart(2, '0')).join('');\n };\n\n const _getSha256Digest = (data: any) => {\n return crypto.subtle.digest('SHA-256', data);\n };\n\n const _hashMessage = async (message: any) => {\n const msgUint8 = new TextEncoder().encode(message);\n return _getSha256Digest(msgUint8).then((it: any) => _toHexDigest(it));\n };\n\n const _constructMessage = (pairId: any, externalParty: any, optionalSuffix: any) => {\n return optionalSuffix\n ? `${pairId}:${externalParty}:${optionalSuffix}`\n : `${pairId}:${externalParty}`;\n };\n\n return _hashMessage(_constructMessage(pairId, externalParty, optionalSuffix));\n }\n\n /**\n * @summary Enables brands to programmatically get the current the SDRN based on the user's session.\n * @remarks This function calls {@link Identity#hasSession} internally and thus has the side\n * effect that it might perform an auto-login on the user\n * @throws {SDKError} If the SDRN is missing in user session object.\n */\n async getUserSDRN(): Promise<string> {\n const { sdrn } = (await this.hasSession()) as any;\n if (sdrn) {\n return sdrn;\n }\n throw new SDKError('Failed to get SDRN from user session');\n }\n\n /**\n * @summary In Schibsted account, there are two ways of identifying a user; the `userId` and the\n * `uuid`. There are reasons for them both existing. The `userId` is a numeric identifier, but\n * since Schibsted account is deployed separately in Norway and Sweden, there are a lot of\n * duplicates. The `userId` was introduced early, so many sites still need to use them for\n * legacy reasons. The `uuid` is universally unique, and so — if we could disregard a lot of\n * Schibsted components depending on the numeric `userId` — it would be a good identifier to use\n * @remarks This function calls {@link Identity#hasSession} internally and thus has the side\n * effect that it might perform an auto-login on the user\n * @throws {SDKError} If the user isn't connected to the merchant\n * @return The `uuid` field (not to be confused with the `userId`)\n */\n async getUserUuid(): Promise<string> {\n const user = (await this.hasSession()) as any;\n if (user.uuid && user.result) {\n return user.uuid;\n }\n throw new SDKError('The user is not connected to this merchant');\n }\n\n /**\n * @summary Get basic information about any user currently logged-in to their Schibsted account\n * in this browser. Can be used to provide context in a continue-as prompt.\n * @remarks This function relies on the global Schibsted account user session cookie, which\n * is a third-party cookie and hence might be blocked by the browser (for example due to ITP in\n * Safari). So there's no guarantee any data is returned, even though a user is logged-in in\n * the current browser.\n */\n async getUserContextData(): Promise<SimplifiedLoginData | null> {\n try {\n return await this._globalSessionService.get('user-context');\n } catch (_) {\n return null;\n }\n }\n\n /**\n * If a popup is desired, this function needs to be called in response to a user event (like\n * click or tap) in order to work correctly. Otherwise the popup will be blocked by the\n * browser's popup blockers and has to be explicitly authorized to be shown.\n * @summary Perform a login, either using a full-page redirect or a popup\n * @see https://tools.ietf.org/html/rfc6749#section-4.1.1\n *\n * @param options\n * @param options.state\n * @param options.acrValues\n * @param options.scope\n * @param options.redirectUri\n * @param options.preferPopup\n * @param options.loginHint\n * @param options.tag\n * @param options.teaser\n * @param options.maxAge\n * @param options.locale\n * @param options.oneStepLogin\n * @param options.prompt\n * @param options.xDomainId\n * @param options.xEnvironmentId\n * @param options.originCampaign\n * @return - Reference to popup window if created (or `null` otherwise)\n */\n login({\n state,\n acrValues = '',\n scope = 'openid',\n redirectUri = this.redirectUri,\n preferPopup = false,\n loginHint = '',\n tag = '',\n teaser = '',\n maxAge = '',\n locale = '',\n oneStepLogin = false,\n prompt = 'select_account',\n xDomainId = '',\n xEnvironmentId = '',\n originCampaign = '',\n }: LoginOptions): Window | null {\n this._closePopup();\n this.sessionStorageCache.delete(HAS_SESSION_CACHE_KEY);\n const url = this.loginUrl({\n state,\n acrValues,\n scope,\n redirectUri,\n loginHint,\n tag,\n teaser,\n maxAge,\n locale,\n oneStepLogin,\n prompt,\n xDomainId,\n xEnvironmentId,\n originCampaign,\n });\n\n if (preferPopup) {\n this.popup = popup.open(this.window, url, 'Schibsted account', {\n width: 360,\n height: 570,\n });\n if (this.popup) {\n return this.popup;\n }\n }\n this.window.location.href = url;\n return null;\n }\n\n /**\n * @summary Retrieve the sp_id (Varnish ID)\n * @remarks This function calls {@link Identity#hasSession} internally and thus has the side\n * effect that it might perform an auto-login on the user\n * @return - The sp_id string or null (if the server didn't return it)\n */\n async getSpId(): Promise<string | null> {\n try {\n const user = (await this.hasSession()) as any;\n return user.sp_id || null;\n } catch (_) {\n return null;\n }\n }\n\n /**\n * @summary Logs the user out from the Identity platform\n * @param redirectUri - Where to redirect the browser after logging out of Schibsted\n * account\n */\n logout(redirectUri: string = this.redirectUri): void {\n this.sessionStorageCache.delete(HAS_SESSION_CACHE_KEY);\n this._maybeClearVarnishCookie();\n this.emit('logout');\n this.window.location.href = this.logoutUrl(redirectUri);\n }\n\n /**\n * Generates the link to the new login page that'll be used in the popup or redirect flow\n * @param options\n * @param options.state\n * @param options.acrValues\n * @param options.scope\n * @param options.redirectUri\n * @param options.loginHint\n * @param options.tag\n * @param options.teaser\n * @param options.maxAge\n * @param options.locale\n * @param options.oneStepLogin\n * @param options.prompt\n * @param options.xDomainId\n * @param options.xEnvironmentId\n * @param options.originCampaign\n * @return - The url\n */\n loginUrl(\n {\n state,\n acrValues = '',\n scope = 'openid',\n redirectUri = this.redirectUri,\n loginHint = '',\n tag = '',\n teaser = '',\n maxAge = '',\n locale = '',\n oneStepLogin = false,\n prompt = 'select_account',\n xDomainId = '',\n xEnvironmentId = '',\n originCampaign = '',\n }: LoginOptions,\n ..._args: any[]\n ): string {\n if (typeof arguments[0] !== 'object') {\n // backward compatibility\n state = arguments[0];\n acrValues = arguments[1];\n scope = arguments[2] || scope;\n redirectUri = arguments[3] || redirectUri;\n loginHint = arguments[4] || loginHint;\n tag = arguments[5] || tag;\n teaser = arguments[6] || teaser;\n maxAge = isNaN(arguments[7]) ? maxAge : arguments[7];\n }\n const isValidAcrValue = (acrValue: any) =>\n isStrIn(\n acrValue,\n ['password', 'otp', 'sms', 'eid-dk', 'eid-no', 'eid-se', 'eid-fi', 'eid'],\n true,\n );\n assert(\n !acrValues ||\n isStrIn(acrValues, ['', 'otp-email'], true) ||\n acrValues.split(' ').every(isValidAcrValue),\n `The acrValues parameter is not acceptable: ${acrValues}`,\n );\n assert(\n isUrl(redirectUri as string),\n `loginUrl(): redirectUri must be a valid url but is ${redirectUri}`,\n );\n assert(\n isNonEmptyString(state),\n `the state parameter should be a non empty string but it is ${state}`,\n );\n\n return this._oauthService.makeUrl('oauth/authorize', {\n response_type: 'code',\n redirect_uri: redirectUri,\n scope,\n state,\n acr_values: acrValues,\n login_hint: loginHint,\n tag,\n teaser,\n max_age: maxAge,\n locale,\n one_step_login: oneStepLogin || '',\n prompt: acrValues ? '' : prompt,\n x_domain_id: xDomainId,\n x_env_id: xEnvironmentId,\n utm_campaign: originCampaign,\n });\n }\n\n /**\n * The url for logging the user out\n * @param redirectUri\n * @return url\n */\n logoutUrl(redirectUri: string = this.redirectUri): string {\n assert(isUrl(redirectUri), `logoutUrl(): redirectUri is invalid`);\n const params = { redirect_uri: redirectUri };\n return this._sessionService.makeUrl('logout', params);\n }\n\n /**\n * The account summary page url\n * @param redirectUri\n */\n accountUrl(redirectUri: string = this.redirectUri): string {\n return this._spid.makeUrl('profile-pages', {\n response_type: 'code',\n redirect_uri: redirectUri,\n });\n }\n\n /**\n * The phone editing page url\n * @param redirectUri\n */\n phonesUrl(redirectUri: string = this.redirectUri): string {\n return this._spid.makeUrl('profile-pages/about-you/phone', {\n response_type: 'code',\n redirect_uri: redirectUri,\n });\n }\n\n /**\n * Function responsible for loading and displaying simplified login widget. How often\n * widget will be display is up to you. Preferred way would be to show it once per user,\n * and store that info in localStorage. Widget will be display only if user is logged in to SSO.\n *\n * @param loginParams - the same as `options` param for login function. Login will be called on user\n * continue action. `state` might be string or async function.\n * @param options - additional configuration of Simplified Login Widget\n * @fires Identity#simplifiedLoginOpened\n * @fires Identity#simplifiedLoginCancelled\n * @return - will resolve to true if widget will be display. Otherwise, will throw SDKError\n */\n async showSimplifiedLoginWidget(\n loginParams: SimplifiedLoginWidgetLoginOptions,\n options?: SimplifiedLoginWidgetOptions,\n ): Promise<boolean | SDKError> {\n // getUserContextData doesn't throw exception\n const userData = await this.getUserContextData();\n\n const queryParams: Record<string, string> = { client_id: this.clientId };\n if (options && options.encoding) {\n queryParams.encoding = options.encoding;\n }\n const widgetUrl = this._bffService.makeUrl('simplified-login-widget', queryParams, false);\n\n const prepareLoginParams = async (loginPrams: any) => {\n if (typeof loginPrams.state === 'function') {\n loginPrams.state = await loginPrams.state();\n }\n\n return loginPrams;\n };\n\n return new Promise((resolve, reject) => {\n if (!userData || !userData.display_text || !userData.identifier) {\n return reject(new SDKError('Missing user data'));\n }\n\n const initialParams: Record<string, any> = {\n displayText: userData.display_text,\n env: this.env,\n clientName: userData.client_name,\n clientId: this.clientId,\n providerId: (userData as any).provider_id,\n windowWidth: () => window.innerWidth,\n windowOnResize: (f: () => void) => {\n window.onresize = f;\n },\n };\n\n if (options && options.locale) {\n initialParams.locale = options.locale;\n }\n\n const loginHandler = async () => {\n this.login(\n Object.assign(await prepareLoginParams(loginParams), {\n loginHint: userData.identifier,\n }) as LoginOptions,\n );\n };\n\n const loginNotYouHandler = async () => {\n this.login(\n Object.assign(await prepareLoginParams(loginParams), {\n loginHint: userData.identifier,\n prompt: 'login',\n }) as LoginOptions,\n );\n };\n\n const initHandler = () => {\n /**\n * Emitted when the simplified login widget is displayed on the screen\n * @event Identity#simplifiedLoginOpened\n */\n this.emit('simplifiedLoginOpened');\n };\n\n const cancelLoginHandler = () => {\n /**\n * Emitted when the user closes the simplified login widget\n * @event Identity#simplifiedLoginCancelled\n */\n this.emit('simplifiedLoginCancelled');\n };\n\n if ((window as any).openSimplifiedLoginWidget) {\n (window as any).openSimplifiedLoginWidget(\n initialParams,\n loginHandler,\n loginNotYouHandler,\n initHandler,\n cancelLoginHandler,\n );\n return resolve(true);\n }\n\n const simplifiedLoginWidget = document.createElement('script');\n simplifiedLoginWidget.type = 'text/javascript';\n simplifiedLoginWidget.src = widgetUrl;\n simplifiedLoginWidget.onload = () => {\n (window as any).openSimplifiedLoginWidget(\n initialParams,\n loginHandler,\n loginNotYouHandler,\n initHandler,\n cancelLoginHandler,\n );\n resolve(true);\n };\n simplifiedLoginWidget.onerror = () => {\n reject(new SDKError('Error when loading simplified login widget content'));\n };\n document.getElementsByTagName('body')[0].appendChild(simplifiedLoginWidget);\n });\n }\n}\n\nexport default Identity;\n"],"mappings":"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"}