@schibsted/account-sdk-browser 6.0.0-alpha.7 → 6.0.0-alpha.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -56,6 +56,7 @@ const account = createAccountSdk({
56
56
  redirectUri: 'https://awesomenews.site/callback',
57
57
  sessionDomain: 'https://id.awesomenews.site',
58
58
  env: 'PRE',
59
+ defaultProductIds: ['product-id'],
59
60
  });
60
61
  ```
61
62
 
@@ -70,6 +71,7 @@ Optional configuration:
70
71
  - `env`: defaults to `PRE`; supported keys include `LOCAL`, `DEV`, `PRE`, `PRO`, `PRO_NO`,
71
72
  `PRO_FI`, and `PRO_DK`
72
73
  - `callbackBeforeRedirect`: called before a full-page session refresh redirect
74
+ - `defaultProductIds`: product or feature ids used when `hasAccess()` is called without arguments
73
75
  - `log`: receives SDK debug log lines
74
76
  - `varnish`: enables Varnish cookie handling
75
77
  - `window`: overrides the browser window object, mostly useful in tests
@@ -176,7 +178,10 @@ Use these methods to inspect the current Session Service state:
176
178
  - `account.isLoggedIn()` returns whether the browser has a Schibsted Account session
177
179
  - `account.isConnected()` returns whether the user is connected to your client
178
180
  - `account.getUser()` returns the connected user session data
179
- - `account.getUserId()` returns the realm-specific user id as a string
181
+ - `account.getUserId()` returns the realm-specific user id as a number
182
+ - `account.getExternalId()` returns an identifier specific to the configured client and supplied
183
+ external party; this method is deprecated and retained only for compatibility with existing
184
+ integrations
180
185
  - `account.getUserUuid()` returns the globally unique user id
181
186
  - `account.getUserSDRN()` returns the user SDRN
182
187
  - `account.getSpId()` returns the Varnish `sp_id` value when present
@@ -221,8 +226,7 @@ window.location.href = account.accountUrl('https://awesomenews.site/account-retu
221
226
  Use `account.hasAccess()` to check access to Schibsted Account product ids or Zuora feature ids:
222
227
 
223
228
  ```js
224
- const userId = await account.getUserId();
225
- const access = await account.hasAccess(['product-id'], userId);
229
+ const access = await account.hasAccess();
226
230
 
227
231
  if (access?.entitled) {
228
232
  showPremiumContent();
@@ -231,8 +235,15 @@ if (access?.entitled) {
231
235
  }
232
236
  ```
233
237
 
238
+ Pass product ids to override the configured defaults for a specific check:
239
+
240
+ ```js
241
+ const access = await account.hasAccess(['other-product-id']);
242
+ ```
243
+
234
244
  `hasAccess()` requires `sessionDomain`. Results are cached according to the Session Service TTL.
235
- Use `account.clearCachedAccessResult(productIds, userId)` when you need to invalidate that cache.
245
+ If no product ids are passed to the method, `defaultProductIds` must be configured. Use
246
+ `account.clearCachedAccessResult(productIds, userId)` when you need to invalidate that cache.
236
247
 
237
248
  ## Simplified Login Widget
238
249
 
package/dist/account.d.ts CHANGED
@@ -43,13 +43,24 @@ export declare class Account {
43
43
  */
44
44
  getUser(): Promise<ConnectedSessionResponse>;
45
45
  /**
46
- * Returns the realm-specific Schibsted Account user id as a string.
46
+ * Returns the realm-specific Schibsted Account user id as a number.
47
47
  *
48
48
  * Use `getUserUuid()` when you need the globally unique user id.
49
49
  *
50
50
  * @throws {SDKError} If the user is not connected to the configured client.
51
51
  */
52
- getUserId(): Promise<string>;
52
+ getUserId(): Promise<number>;
53
+ /**
54
+ * Returns an external identifier for the authenticated user, scoped to the configured client
55
+ * and external party.
56
+ *
57
+ * @param externalParty - External party for which the identifier is generated.
58
+ * @param optionalSuffix - Optional suffix included when generating the identifier.
59
+ * @throws {SDKError} If the session lookup fails, the session does not contain a `pairId`, or
60
+ * `externalParty` is empty.
61
+ * @deprecated Retained for compatibility with existing integrations. Avoid new usage.
62
+ */
63
+ getExternalId(externalParty: string, optionalSuffix?: string): Promise<string>;
53
64
  /**
54
65
  * Returns the globally unique user id from the current session.
55
66
  *
@@ -128,16 +139,17 @@ export declare class Account {
128
139
  */
129
140
  clearCachedUserSession(): void;
130
141
  /**
131
- * Checks whether a user has access to any of the requested products or features.
142
+ * Checks whether the current user has access to any of the requested products or features.
132
143
  *
144
+ * When `productIds` is omitted, the ids configured as `defaultProductIds` are used.
133
145
  * Results are cached according to the TTL returned by Session Service.
134
146
  *
135
- * @param productIds - Product or feature ids to check.
136
- * @param userId - Current user id, usually from `getUserId()`.
147
+ * @param productIds - Product or feature ids to check instead of the configured defaults.
137
148
  * @returns Access data, or `null` when the user is not entitled.
138
- * @throws {SDKError} If `sessionDomain` is missing, input is invalid, or the request fails.
149
+ * @throws {SDKError} If product ids are not provided or configured, `sessionDomain` is missing,
150
+ * the current user cannot be resolved, input is invalid, or the request fails.
139
151
  */
140
- hasAccess(productIds: string[], userId: SessionUserId): Promise<HasAccessResult | null>;
152
+ hasAccess(productIds?: string[] | undefined): Promise<HasAccessResult | null>;
141
153
  /**
142
154
  * Removes a cached access-check result.
143
155
  *
@@ -160,7 +160,29 @@ export declare class Identity {
160
160
  * @throws {SDKError} If the user isn't connected to the merchant
161
161
  * @return The `userId` field (not to be confused with the `uuid`)
162
162
  */
163
- getUserId(): Promise<string>;
163
+ getUserId(): Promise<number>;
164
+ /**
165
+ * @function
166
+ * @summary
167
+ * Retrieves the external identifier (`externalId`) for the authenticated user.
168
+ *
169
+ * In Schibsted Account there are multiple ways of identifying users, however for integrations with
170
+ * third-parties it's recommended to use `externalId` as it does not disclose
171
+ * any critical data whilst allowing for user identification.
172
+ *
173
+ * `externalId` is merchant-scoped using a pairwise identifier (`pairId`),
174
+ * meaning the same user's ID will differ between merchants.
175
+ * Additionally, this identifier is bound to the external party provided as argument.
176
+ *
177
+ * @param externalParty
178
+ * @param optionalSuffix
179
+ * @remarks This function calls {@link Identity#hasSession} internally and thus has the side
180
+ * effect that it might perform an auto-login on the user
181
+ * @throws {SDKError} If the `pairId` is missing in user session.
182
+ * @throws {SDKError} If the `externalParty` is not defined
183
+ * @return The merchant- and 3rd-party-specific `externalId`
184
+ */
185
+ getExternalId(externalParty: string, optionalSuffix?: string): Promise<string>;
164
186
  /**
165
187
  * @summary Enables brands to programmatically get the current the SDRN based on the user's session.
166
188
  * @remarks This function calls {@link Identity#hasSession} internally and thus has the side
package/dist/index.d.ts CHANGED
@@ -2,6 +2,8 @@ export { Account } from './account.js';
2
2
  export { createAccountSdk, getAccountSdk } from './account-sdk.js';
3
3
  export * from './globals.js';
4
4
  export { default as SDKError } from './sdk-error.js';
5
+ /** session response type guards */
6
+ export { isConnectedSessionResponse, isConnectedSessionWithUserIdResponse, isSessionFailureResponse, isSessionSuccessResponse, } from './session-response.js';
5
7
  export type { AccountConfig, AccountEventListener, AccountEventName, } from './types/account.js';
6
8
  export type { AccountEnvironment, LogFunction } from './types/common.js';
7
9
  export type { LoginOptions, SimplifiedLoginData, SimplifiedLoginWidgetLoginOptions, SimplifiedLoginWidgetOptions, } from './types/login.js';
package/dist/index.js CHANGED
@@ -178,10 +178,10 @@ function y(e) {
178
178
  }
179
179
  //#endregion
180
180
  //#region src/popup.ts
181
- function ee(e) {
181
+ function b(e) {
182
182
  return u(p(e), `Object must be an object but it is '${e}'`), Object.keys(e).map((t) => `${t}=${e[t]}`).join(",");
183
183
  }
184
- var te = {
184
+ var ee = {
185
185
  scrollbars: "yes",
186
186
  location: "yes",
187
187
  status: "no",
@@ -189,11 +189,11 @@ var te = {
189
189
  toolbar: "no",
190
190
  resizable: "yes"
191
191
  };
192
- function b(e, t, n = "", r = {}) {
192
+ function te(e, t, n = "", r = {}) {
193
193
  u(p(e), `window was supposed to be an object but it is ${e}`), u(p(e.screen), "window should be a valid Window object but it lacks a 'screen' property"), u(g(e.open), "window should be a valid Window object but it lacks an 'open' function"), u(h(t), "Invalid URL for popup");
194
- let { height: i, width: a } = e.screen, o = v(te, r), { width: s, height: c } = o;
194
+ let { height: i, width: a } = e.screen, o = v(ee, r), { width: s, height: c } = o;
195
195
  typeof s == "number" && Number.isFinite(s) && Number.isFinite(a) && (o.left = (a - s) / 2), typeof c == "number" && Number.isFinite(c) && Number.isFinite(i) && (o.top = (i - c) / 2);
196
- let l = ee(o);
196
+ let l = b(o);
197
197
  return e.open(t, n, l);
198
198
  }
199
199
  //#endregion
@@ -218,14 +218,14 @@ function C(e) {
218
218
  };
219
219
  return encodeURIComponent(e).replace(/[!'()~]|%20|%00/g, (e) => t[e]);
220
220
  }
221
- var w = () => window.fetch && window.fetch.bind(window), T = () => {
221
+ var re = () => window.fetch && window.fetch.bind(window), w = () => {
222
222
  throw new t("fetch is not available in this environment");
223
- }, E = class e {
223
+ }, T = class e {
224
224
  url;
225
225
  defaultParams;
226
226
  log;
227
227
  fetch;
228
- constructor({ serverUrl: e = "PRE", envDic: t, fetch: n = w() ?? T, log: r, defaultParams: i = {} }) {
228
+ constructor({ serverUrl: e = "PRE", envDic: t, fetch: n = re() ?? w, log: r, defaultParams: i = {} }) {
229
229
  u(p(i), "defaultParams should be a non-null object");
230
230
  let a = x(e, t ?? {}), o = a.endsWith("/") ? a : `${a}/`;
231
231
  this.url = new URL(o), this.defaultParams = i, r && (u(g(r), `log must be a function but it is ${r}`), this.log = r), this.fetch = n;
@@ -270,7 +270,7 @@ var w = () => window.fetch && window.fetch.bind(window), T = () => {
270
270
  let r = t ? v(n, e) : v(e);
271
271
  return Object.keys(r).filter((e) => r[e] !== "").map((e) => `${C(e)}=${C(String(r[e]))}`).join("&");
272
272
  }
273
- }, re = (e) => Object.hasOwn(l, e), D = (e, t) => (u(f(t), "clientId parameter is required"), u(re(e), `env parameter is invalid: ${e}`), `sdrn:${l[e]}:client:${t}`), O = ({ serverUrl: e, log: t, defaultParams: n }) => new E({
273
+ }, E = (e) => Object.hasOwn(l, e), D = (e, t) => (u(f(t), "clientId parameter is required"), u(E(e), `env parameter is invalid: ${e}`), `sdrn:${l[e]}:client:${t}`), O = ({ serverUrl: e, log: t, defaultParams: n }) => new T({
274
274
  serverUrl: e,
275
275
  log: t,
276
276
  defaultParams: n
@@ -290,7 +290,7 @@ function M(e) {
290
290
  return p(e) && Object.keys(e).length === 1 && d(e.redirectURL);
291
291
  }
292
292
  function N(e) {
293
- return A(e) && (typeof e.userId == "number" || typeof e.userId == "string");
293
+ return A(e) && typeof e.userId == "number";
294
294
  }
295
295
  function P(e) {
296
296
  return M(e) || j(e) || k(e) || p(e) ? e : {};
@@ -302,7 +302,7 @@ function F(e) {
302
302
  }
303
303
  //#endregion
304
304
  //#region src/types/login.ts
305
- var I = (e) => typeof e.openSimplifiedLoginWidget == "function", L = "6.0.0-alpha.7", R = "hasSession-cache", z = "sessionCallBlocked-cache", B = 1e3 * 60 * 5, V = "tab-id-cache", H = Math.floor(Math.random() * 1e5), U = 1e3 * 60 * 60 * 24 * 30, W = () => window, G = class {
305
+ var I = (e) => typeof e.openSimplifiedLoginWidget == "function", L = "6.0.0-alpha.8", R = "hasSession-cache", z = "sessionCallBlocked-cache", B = 1e3 * 60 * 5, V = "tab-id-cache", H = Math.floor(Math.random() * 1e5), U = 1e3 * 60 * 60 * 24 * 30, W = () => window, G = class {
306
306
  eventTarget = new EventTarget();
307
307
  window;
308
308
  clientId;
@@ -479,9 +479,16 @@ var I = (e) => typeof e.openSimplifiedLoginWidget == "function", L = "6.0.0-alph
479
479
  }
480
480
  async getUserId() {
481
481
  let e = await this.hasSession();
482
- if (N(e)) return String(e.userId);
482
+ if (N(e)) return e.userId;
483
483
  throw new t("The user is not connected to this merchant");
484
484
  }
485
+ async getExternalId(e, n = "") {
486
+ let r = await this.hasSession(), i = k(r) ? r.pairId : void 0;
487
+ if (!i) throw new t("pairId missing in user session!");
488
+ if (!e || e.length === 0) throw new t("externalParty cannot be empty");
489
+ let a = (e) => Array.from(new Uint8Array(e)).map((e) => e.toString(16).padStart(2, "0")).join(""), o = (e) => crypto.subtle.digest("SHA-256", e);
490
+ return (async (e) => o(new TextEncoder().encode(e)).then((e) => a(e)))(((e, t, n) => n ? `${e}:${t}:${n}` : `${e}:${t}`)(i, e, n));
491
+ }
485
492
  async getUserSDRN() {
486
493
  let e = await this.hasSession();
487
494
  if (k(e) && e.sdrn) return e.sdrn;
@@ -522,7 +529,7 @@ var I = (e) => typeof e.openSimplifiedLoginWidget == "function", L = "6.0.0-alph
522
529
  xEnvironmentId: p,
523
530
  originCampaign: m
524
531
  });
525
- return i && (this.popup = b(this.window, h, "Schibsted account", {
532
+ return i && (this.popup = te(this.window, h, "Schibsted account", {
526
533
  width: 360,
527
534
  height: 570
528
535
  }), this.popup) ? (this.eventTarget.dispatchEvent(new CustomEvent("login", { detail: {
@@ -645,7 +652,7 @@ var I = (e) => typeof e.openSimplifiedLoginWidget == "function", L = "6.0.0-alph
645
652
  function K(e) {
646
653
  if (!p(e)) throw new t("Invalid hasAccess response");
647
654
  let { entitled: n, ttl: r, allowedFeatures: i, userId: a, uuid: o, sig: s } = e;
648
- if (typeof n != "boolean" || typeof r != "number" || !Array.isArray(i) || typeof a != "number" && typeof a != "string" || !d(o) || !d(s)) throw new t("Invalid hasAccess response");
655
+ if (typeof n != "boolean" || typeof r != "number" || !Array.isArray(i) || typeof a != "number" || !d(o) || !d(s)) throw new t("Invalid hasAccess response");
649
656
  return {
650
657
  entitled: n,
651
658
  ttl: r,
@@ -700,11 +707,12 @@ var q = () => window, J = class {
700
707
  }, Y = (e) => e || (typeof window > "u" ? void 0 : window), X = class {
701
708
  #e;
702
709
  #t;
710
+ #n;
703
711
  constructor(e) {
704
712
  let n = Y(e.window);
705
713
  if (!n) throw new t("Schibsted Account SDK is not available in this browser context");
706
714
  if (n.schAccount) throw new t("Schibsted Account SDK has already been initialized");
707
- let { log: r, callbackBeforeRedirect: i, varnish: a } = e, o = {
715
+ let { log: r, callbackBeforeRedirect: i, defaultProductIds: a, varnish: o } = e, s = {
708
716
  clientId: e.clientId,
709
717
  redirectUri: e.redirectUri,
710
718
  sessionDomain: e.sessionDomain,
@@ -712,14 +720,15 @@ var q = () => window, J = class {
712
720
  window: n
713
721
  };
714
722
  if (this.#e = new G({
715
- ...o,
723
+ ...s,
716
724
  log: r,
717
725
  callbackBeforeRedirect: i
718
- }), a) {
719
- if (typeof a != "object" || Array.isArray(a)) throw new t("Account varnish config must be an object");
720
- this.#e.enableVarnishCookie(a);
726
+ }), a !== void 0 && !Array.isArray(a)) throw new t("Account defaultProductIds config must be an array");
727
+ if (this.#n = a, o) {
728
+ if (typeof o != "object" || Array.isArray(o)) throw new t("Account varnish config must be an object");
729
+ this.#e.enableVarnishCookie(o);
721
730
  }
722
- this.#t = new J(o), n.schAccount = this, n.dispatchEvent(new CustomEvent("schAccount:ready", { detail: { instance: this } }));
731
+ this.#t = new J(s), n.schAccount = this, n.dispatchEvent(new CustomEvent("schAccount:ready", { detail: { instance: this } }));
723
732
  }
724
733
  hasSession() {
725
734
  return this.#e.hasSession();
@@ -736,6 +745,9 @@ var q = () => window, J = class {
736
745
  getUserId() {
737
746
  return this.#e.getUserId();
738
747
  }
748
+ getExternalId(e, t = "") {
749
+ return this.#e.getExternalId(e, t);
750
+ }
739
751
  getUserUuid() {
740
752
  return this.#e.getUserUuid();
741
753
  }
@@ -772,8 +784,11 @@ var q = () => window, J = class {
772
784
  clearCachedUserSession() {
773
785
  this.#e.clearCachedUserSession();
774
786
  }
775
- hasAccess(e, t) {
776
- return this.#t.hasAccess(e, t);
787
+ async hasAccess(e = this.#n) {
788
+ if (!e) throw new t("hasAccess requires productIds or defaultProductIds in the Account config");
789
+ if (e.length === 0) return null;
790
+ let n = await this.#e.getUserId();
791
+ return this.#t.hasAccess(e, n);
777
792
  }
778
793
  clearCachedAccessResult(e, t) {
779
794
  this.#t.clearCachedAccessResult(e, t);
@@ -808,6 +823,6 @@ function se() {
808
823
  }), $);
809
824
  }
810
825
  //#endregion
811
- export { X as Account, t as SDKError, oe as createAccountSdk, se as getAccountSdk };
826
+ export { X as Account, t as SDKError, oe as createAccountSdk, se as getAccountSdk, A as isConnectedSessionResponse, N as isConnectedSessionWithUserIdResponse, j as isSessionFailureResponse, k as isSessionSuccessResponse };
812
827
 
813
828
  //# sourceMappingURL=index.js.map