@schibsted/account-sdk-browser 5.2.3 → 5.2.5

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
@@ -61,23 +61,38 @@ You can use that code as inspiration or just fork and play with it. The account-
61
61
  module is used for authenticating the user with Schibsted account. Take a look at how the SDK is
62
62
  initialized.
63
63
 
64
- When a user wants to log in to your site, you direct them to a UI flow hosted by **Schibsted Account**.
65
- We authenticate the user and redirect them back to your site. This final redirect back to your site is performed in accordance with the OAuth2 specification.
64
+ When a user wants to log in to your site, you direct them to a UI flow hosted by **Schibsted Account**.
65
+ We authenticate the user and redirect them back to your site. This final redirect back to your site is performed in accordance with the OAuth2 specification.
66
66
  This means we pass a `code` in the query string of that redirect URI.
67
- You can use that `code` on your site's backend, along with your client credentials (client ID and secret), to obtain an *Access Token* (AT) and a *Refresh Token* (RT).
68
- You should not send the AT (and **never** the RT!) to the browser. Instead, keep them on the server side and associate them with the specific user session.
67
+ You can use that `code` on your site's backend, along with your client credentials (client ID and secret), to obtain an *Access Token* (AT) and a *Refresh Token* (RT).
68
+ You should not send the AT (and **never** the RT!) to the browser. Instead, keep them on the server side and associate them with the specific user session.
69
69
  This allows you to call Schibsted Account APIs on behalf of that user.
70
70
 
71
-
72
71
  ## Events
73
72
 
74
- The SDK fires events when something we deem interesting is happening. For example the
73
+ The SDK fires events on the instances when something we deem interesting is happening. For example the
75
74
  [Identity](https://schibsted.github.io/account-sdk-browser/Identity.html) class
76
75
  emits some events when the user is logged in or logged out. This SDK uses a familar interface that's
77
76
  very similar to Node's [EventEmitter](https://nodejs.org/api/events.html). The most important
78
77
  methods are `.on(eventName, listener)` (to subscribe to an event) and `.off(eventName, listener)`
79
78
  (to unsubscribe to an event).
80
79
 
80
+ The SDK also emits global events on the `window` when a new instance is created.
81
+ Events are emitted for:
82
+
83
+ | Class | event name |
84
+ | ------------ | ----------------------- |
85
+ | Identity | `schIdentity:ready` |
86
+ | Monetization | `schMonetization:ready` |
87
+ | Payment | `schPayment:ready` |
88
+
89
+ ```js
90
+ window.addEventListener('schIdentity:ready', e => {
91
+ // The event contains the initialized instance (e.detail.instance);
92
+ }
93
+
94
+ ```
95
+
81
96
  ## Identity
82
97
 
83
98
  Let's start with a bit of example code:
@@ -85,29 +100,29 @@ Let's start with a bit of example code:
85
100
  #### Example
86
101
 
87
102
  ```javascript
88
- import { Identity } from '@schibsted/account-sdk-browser'
103
+ import { Identity } from '@schibsted/account-sdk-browser';
89
104
 
90
105
  const identity = new Identity({
91
106
  clientId: '56e9a5d1eee0000000000000',
92
107
  redirectUri: 'https://awesomenews.site', // ensure it's listed in selfservice
93
108
  env: 'PRE', // Schibsted account env. A url or a special key: 'PRE', 'PRO', 'PRO_NO', 'PRO_FI' or 'PRO_DK'
94
109
  sessionDomain: 'https://id.awesomenews.site', // client-configured session-service domain
95
- })
110
+ });
96
111
 
97
112
  async function whenSiteLoaded() {
98
- const loginContainer = document.getElementById('login-container')
113
+ const loginContainer = document.getElementById('login-container');
99
114
  if (await identity.isLoggedIn()) {
100
- const user = await identity.getUser()
101
- const span = document.createElement('span')
102
- span.textContent = `Hello ${user.givenName}`
103
- loginContainer.appendChild(span)
115
+ const user = await identity.getUser();
116
+ const span = document.createElement('span');
117
+ span.textContent = `Hello ${user.givenName}`;
118
+ loginContainer.appendChild(span);
104
119
  } else {
105
- loginContainer.innerHTML = '<button class="login-button">Log in</button>'
120
+ loginContainer.innerHTML = '<button class="login-button">Log in</button>';
106
121
  }
107
122
  }
108
123
 
109
124
  function userClicksLogIn() {
110
- identity.login({ state: 'some-random-string-1234-foobar-wonky-pig' })
125
+ identity.login({ state: 'some-random-string-1234-foobar-wonky-pig' });
111
126
  }
112
127
  ```
113
128
 
@@ -126,10 +141,11 @@ with the auth `code` parameter.
126
141
 
127
142
  It is recommended that you provide a unique identifier as part of the state, to prevent CSRF
128
143
  attacks. For example this can be accomplished by:
144
+
129
145
  1. Your backend generates random token: `1234abcd`, saves it in some tokenCache, and forwards to
130
146
  your browser frontend
131
147
  1. Your frontend calls `Identity.login` with `state = base64Urlencode({ token: '1234abcd', article:
132
- '1234', ... })`
148
+ '1234', ... })`
133
149
  1. When auth flow completes, the user is redirected back to your site. Then, your backend sees the
134
150
  query parameters `code` (which it can exchange for OAuth tokens for the user) and `state`
135
151
  1. Your backend can do `decodedState = base64Urldecode(query.state)` and then verify that its
@@ -143,21 +159,22 @@ Although Schibsted account abstracts away the details of how the users sign up o
143
159
  mentioning that your end users have a few ways to log in:
144
160
 
145
161
  * Username & password: pretty self-explanatory; users register using an email address and a
146
- self-chosen password
147
- * Passwordless - email: here, the users enter their email address and receive a one-time code that
148
- they can use to log in
149
- * Multifactor authentication: first client indicates which methods should be preferred, later these
150
- will be included (if fulfilled) in `AMR` claim of IDToken
162
+ self-chosen password
163
+ * Passwordless - email: here, the users enter their email address and receive a one-time code that
164
+ they can use to log in
165
+ * Multifactor authentication: first client indicates which methods should be preferred, later these
166
+ will be included (if fulfilled) in `AMR` claim of IDToken
151
167
 
152
168
  The default is username & password. If you wish to use one of the passwordless login methods, the
153
169
  `login()` function takes an optional parameter called `acrValues` (Authentication Context Class Reference).
154
170
  The `acrValues` parameter with multifactor authentication can take following values:
155
- - `eid` - authentication using BankID (for DEV and PRE environments you can choose between country specific solution by specifying `eid-no` or `eid-se` instead)
156
- - `otp-email` - passwordless authentication using code sent to registered email
157
- - `password` - force password authentication (even if user is already logged in)
158
- - `otp` - authentication using registered one time code generator (https://tools.ietf.org/html/rfc6238)
159
- - `sms` - authentication using SMS code sent to phone number
160
- - `password otp sms` - those authentication methods might be combined
171
+
172
+ * `eid` - authentication using BankID (for DEV and PRE environments you can choose between country specific solution by specifying `eid-no` or `eid-se` instead)
173
+ * `otp-email` - passwordless authentication using code sent to registered email
174
+ * `password` - force password authentication (even if user is already logged in)
175
+ * `otp` - authentication using registered one time code generator (https://tools.ietf.org/html/rfc6238)
176
+ * `sms` - authentication using SMS code sent to phone number
177
+ * `password otp sms` - those authentication methods might be combined
161
178
 
162
179
  The classic way to authenticate a user, is to send them from your site to the Schibsted account
163
180
  domain, let the user authenticate there, and then have us redirect them back to your site. If you
@@ -176,12 +193,13 @@ Schibsted account relies on browser cookies to determine whether a user is recog
176
193
  The SDK provides functions that can be used to check if the user that's visiting your site is
177
194
  already a Schibsted user or not.
178
195
 
179
- * [Identity#isLoggedIn](https://schibsted.github.io/account-sdk-browser/Identity.html#isLoggedIn)
180
- tells you if the user that is visiting your site is already logged in to Schibsted account or not.
181
- * [Identity#isConnected](https://schibsted.github.io/account-sdk-browser/Identity.html#isConnected)
182
- tells you if the user is connected to your client. A user might have `isLoggedIn=true` and at the
183
- same time `isConnected=false` if they have logged in to Schibsted account, but not accepted terms
184
- and privacy policy for your site.
196
+ * [Identity#isLoggedIn](https://schibsted.github.io/account-sdk-browser/Identity.html#isLoggedIn)
197
+ tells you if the user that is visiting your site is already logged in to Schibsted account or not.
198
+
199
+ * [Identity#isConnected](https://schibsted.github.io/account-sdk-browser/Identity.html#isConnected)
200
+ tells you if the user is connected to your client. A user might have `isLoggedIn=true` and at the
201
+ same time `isConnected=false` if they have logged in to Schibsted account, but not accepted terms
202
+ and privacy policy for your site.
185
203
 
186
204
  If you've lately changed your terms & conditions, maybe the user still hasn't accepted them. In that
187
205
  case they are considered *not connected*. In that case, if they click "Log in" from your site, we
@@ -201,8 +219,9 @@ It requires using Session Service, and supports both Schibsted account productId
201
219
  feature id's.
202
220
 
203
221
  #### Example
222
+
204
223
  ```javascript
205
- import { Monetization } from '@schibsted/account-sdk-browser'
224
+ import { Monetization } from '@schibsted/account-sdk-browser';
206
225
 
207
226
  const monetization = new Monetization({
208
227
  clientId: '56e9a5d1eee0000000000000',
@@ -215,9 +234,9 @@ try {
215
234
  // Check if the user has access to a a particular product
216
235
  const userId = await identity.getUserId();
217
236
  const data = await monetization.hasAccess([productId], userId);
218
- alert(`User has access to ${productId}? ${data.entitled}`)
237
+ alert(`User has access to ${productId}? ${data.entitled}`);
219
238
  } catch (err) {
220
- alert(`Could not query if the user has access to ${productId} because ${err}`)
239
+ alert(`Could not query if the user has access to ${productId} because ${err}`);
221
240
  }
222
241
  ```
223
242
 
@@ -229,20 +248,20 @@ pages for redeeming voucher codes, reviewing payment history, and more.
229
248
  #### Example
230
249
 
231
250
  ```javascript
232
- import { Payment } from '@schibsted/account-sdk-browser'
251
+ import { Payment } from '@schibsted/account-sdk-browser';
233
252
 
234
253
  const paymentSDK = new Payment({
235
254
  clientId: '56e9a5d1eee0000000000000',
236
255
  redirectUri: 'https://awesomenews.site', // ensure it's listed in selfservice
237
256
  env: 'PRE', // Schibsted account env. A url or a special key: 'PRE', 'PRO' or 'PRO_NO'
238
- })
257
+ });
239
258
 
240
259
  // Get the url to paymentSDK with paylink
241
- const paylink = '...'
242
- const paylinkUrl = paymentSDK.purchasePaylinkUrl(paylink)
260
+ const paylink = '...';
261
+ const paylinkUrl = paymentSDK.purchasePaylinkUrl(paylink);
243
262
 
244
263
  // Or another example --- pay with paylink in a popup
245
- paymentSDK.payWithPaylink(paylink)
264
+ paymentSDK.payWithPaylink(paylink);
246
265
  ```
247
266
 
248
267
  ## Appendix
@@ -273,27 +292,28 @@ browser side. Nevertheless, here is a short description of them.
273
292
  production environments is `vgs_email`, because reasons (on PRE, it is called `spid-pre-data`).
274
293
  It's a JSON string that's encoded using the standard `encodeURIComponent()` function and is an
275
294
  object that contains two pieces of information that's important:
276
- * `remember`: if set to `true`, the user chose to be remembered and this means we usually support
277
- auto-login (that is, if you call the Schibsted account hassession service, and no session can
278
- be found in the session database, it will automatically create a new one for the user so that
279
- they don't have to authenticate again. If it is `false`, it should be interpreted as the user
280
- does not want to be automatically logged in to any site when their session expires
281
- * `v`: the version number
295
+ * `remember`: if set to `true`, the user chose to be remembered and this means we usually support
296
+ auto-login (that is, if you call the Schibsted account hassession service, and no session can
297
+ be found in the session database, it will automatically create a new one for the user so that
298
+ they don't have to authenticate again. If it is `false`, it should be interpreted as the user
299
+ does not want to be automatically logged in to any site when their session expires
300
+ * `v`: the version number
282
301
  1. The **session** cookies: Cookie names in production environments are `identity`, and `SPID_SE` or
283
302
  `SPID_NO`. It contains:
284
- * `user`: an object (if it's missing, a call to hassession will return a `401` with a
285
- `UserException` that says `No session found`)
286
- * `userId` identifies the user. We use this property to compare "old" user with "new" user and
287
- fire events that indicate that the user has changed
288
- * `is_logged_in` indicates if the user is logged in
289
- * `user_tags`: a map that contains some flags about the user; namely:
290
- * `is_logged_in` indicates if the user is logged in (this seems to be a duplicate of a
291
- property with a similar name in the parent `user` object)
292
- * `terms`: a map of term ids that indicate if they've been accepted by the user.
293
- * `referer` (yep, missing the double "rr"..): If this is missing, a call to hassession will
294
- return a `401` with a `UserException` that says `No session found`.
303
+ * `user`: an object (if it's missing, a call to hassession will return a `401` with a
304
+ `UserException` that says `No session found`)
305
+ * `userId` identifies the user. We use this property to compare "old" user with "new" user and
306
+ fire events that indicate that the user has changed
307
+ * `is_logged_in` indicates if the user is logged in
308
+ * `user_tags`: a map that contains some flags about the user; namely:
309
+ * `is_logged_in` indicates if the user is logged in (this seems to be a duplicate of a
310
+ property with a similar name in the parent `user` object)
311
+ * `terms`: a map of term ids that indicate if they've been accepted by the user.
312
+ * `referer` (yep, missing the double "rr"..): If this is missing, a call to hassession will
313
+ return a `401` with a `UserException` that says `No session found`.
295
314
 
296
315
  ## Releasing
316
+
297
317
  Tags are pushed to NPM via Travis. To release a new version, run in master
298
318
 
299
319
  ```bash
package/es5/global.js CHANGED
@@ -976,9 +976,9 @@ module.exports = function (argument) {
976
976
  window.regeneratorRuntime = __webpack_require__(50);
977
977
  var _require = __webpack_require__(51),
978
978
  Identity = _require.Identity;
979
- var _require2 = __webpack_require__(225),
979
+ var _require2 = __webpack_require__(226),
980
980
  Monetization = _require2.Monetization;
981
- var _require3 = __webpack_require__(227),
981
+ var _require3 = __webpack_require__(228),
982
982
  Payment = _require3.Payment;
983
983
  module.exports = {
984
984
  Identity: Identity,
@@ -1766,6 +1766,7 @@ __webpack_require__.r(__webpack_exports__);
1766
1766
  /* harmony import */ var _SDKError_js__WEBPACK_IMPORTED_MODULE_63__ = __webpack_require__(190);
1767
1767
  /* harmony import */ var _spidTalk_js__WEBPACK_IMPORTED_MODULE_64__ = __webpack_require__(223);
1768
1768
  /* harmony import */ var _version_js__WEBPACK_IMPORTED_MODULE_65__ = __webpack_require__(224);
1769
+ /* harmony import */ var _global_registry_js__WEBPACK_IMPORTED_MODULE_66__ = __webpack_require__(225);
1769
1770
  /* Copyright 2024 Schibsted Products & Technology AS. Licensed under the terms of the MIT license.
1770
1771
  * See LICENSE.md in the project root.
1771
1772
  */
@@ -1855,6 +1856,7 @@ function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.g
1855
1856
 
1856
1857
 
1857
1858
 
1859
+
1858
1860
  /**
1859
1861
  * @typedef {object} LoginOptions
1860
1862
  * @property {string} state - An opaque value used by the client to maintain state between
@@ -2063,6 +2065,7 @@ var Identity = /*#__PURE__*/function (_EventEmitter) {
2063
2065
  _this._setOauthServerUrl(env);
2064
2066
  _this._setGlobalSessionServiceUrl(env);
2065
2067
  _this._unblockSessionCall();
2068
+ Object(_global_registry_js__WEBPACK_IMPORTED_MODULE_66__["registerGlobal"])(window, 'Identity', _assertThisInitialized(_this));
2066
2069
  return _this;
2067
2070
  }
2068
2071
 
@@ -12200,19 +12203,49 @@ __webpack_require__.r(__webpack_exports__);
12200
12203
 
12201
12204
 
12202
12205
 
12203
- var version = '5.2.3';
12206
+ var version = '5.2.5';
12204
12207
  /* harmony default export */ __webpack_exports__["default"] = (version);
12205
12208
 
12206
12209
  /***/ }),
12207
12210
  /* 225 */
12208
12211
  /***/ (function(module, __webpack_exports__, __webpack_require__) {
12209
12212
 
12213
+ "use strict";
12214
+ __webpack_require__.r(__webpack_exports__);
12215
+ /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "registerGlobal", function() { return registerGlobal; });
12216
+ /**
12217
+ * Registers a component as a property on the provided global object, if not already registered, and dispatches an event to notify listeners.
12218
+ * The event is dispatched on `document` and will have the name `$sch${componentClassName}:ready` and a `detail` property with the instance.
12219
+ *
12220
+ * @param {any} global typically `window`
12221
+ * @param {string} componentClassName the name of the component to register, 'identity', 'monetization' or 'payment'
12222
+ * @param {any} instance the instance of the component to register
12223
+ * @returns {void}
12224
+ */
12225
+ var registerGlobal = function registerGlobal(global, componentClassName, instance) {
12226
+ var prefixedName = "sch".concat(componentClassName);
12227
+ if (!global[prefixedName]) {
12228
+ global[prefixedName] = instance;
12229
+ }
12230
+ if (typeof global.dispatchEvent === 'function') {
12231
+ global.dispatchEvent(new CustomEvent("".concat(prefixedName, ":ready"), {
12232
+ detail: {
12233
+ instance: instance
12234
+ }
12235
+ }));
12236
+ }
12237
+ };
12238
+
12239
+ /***/ }),
12240
+ /* 226 */
12241
+ /***/ (function(module, __webpack_exports__, __webpack_require__) {
12242
+
12210
12243
  "use strict";
12211
12244
  __webpack_require__.r(__webpack_exports__);
12212
12245
  /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Monetization", function() { return Monetization; });
12213
12246
  /* harmony import */ var core_js_modules_es_array_concat_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(52);
12214
12247
  /* harmony import */ var core_js_modules_es_array_concat_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_array_concat_js__WEBPACK_IMPORTED_MODULE_0__);
12215
- /* harmony import */ var core_js_modules_es_array_sort_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(226);
12248
+ /* harmony import */ var core_js_modules_es_array_sort_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(227);
12216
12249
  /* harmony import */ var core_js_modules_es_array_sort_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_array_sort_js__WEBPACK_IMPORTED_MODULE_1__);
12217
12250
  /* harmony import */ var core_js_modules_es_array_join_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(73);
12218
12251
  /* harmony import */ var core_js_modules_es_array_join_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_array_join_js__WEBPACK_IMPORTED_MODULE_2__);
@@ -12268,6 +12301,7 @@ __webpack_require__.r(__webpack_exports__);
12268
12301
  /* harmony import */ var _spidTalk_js__WEBPACK_IMPORTED_MODULE_30__ = __webpack_require__(223);
12269
12302
  /* harmony import */ var _SDKError_js__WEBPACK_IMPORTED_MODULE_31__ = __webpack_require__(190);
12270
12303
  /* harmony import */ var _version_js__WEBPACK_IMPORTED_MODULE_32__ = __webpack_require__(224);
12304
+ /* harmony import */ var _global_registry_js__WEBPACK_IMPORTED_MODULE_33__ = __webpack_require__(225);
12271
12305
  /* Copyright 2024 Schibsted Products & Technology AS. Licensed under the terms of the MIT license.
12272
12306
  * See LICENSE.md in the project root.
12273
12307
  */
@@ -12323,6 +12357,7 @@ function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.g
12323
12357
 
12324
12358
 
12325
12359
 
12360
+
12326
12361
  var globalWindow = function globalWindow() {
12327
12362
  return window;
12328
12363
  };
@@ -12367,6 +12402,7 @@ var Monetization = /*#__PURE__*/function (_EventEmitter) {
12367
12402
  Object(_validate_js__WEBPACK_IMPORTED_MODULE_24__["assert"])(Object(_validate_js__WEBPACK_IMPORTED_MODULE_24__["isUrl"])(sessionDomain), 'sessionDomain parameter is not a valid URL');
12368
12403
  _this._setSessionServiceUrl(sessionDomain);
12369
12404
  }
12405
+ Object(_global_registry_js__WEBPACK_IMPORTED_MODULE_33__["registerGlobal"])(window, 'Monetization', _assertThisInitialized(_this));
12370
12406
  return _this;
12371
12407
  }
12372
12408
 
@@ -12542,7 +12578,7 @@ var Monetization = /*#__PURE__*/function (_EventEmitter) {
12542
12578
  /* harmony default export */ __webpack_exports__["default"] = (Monetization);
12543
12579
 
12544
12580
  /***/ }),
12545
- /* 226 */
12581
+ /* 227 */
12546
12582
  /***/ (function(module, exports, __webpack_require__) {
12547
12583
 
12548
12584
  "use strict";
@@ -12581,7 +12617,7 @@ $({
12581
12617
  });
12582
12618
 
12583
12619
  /***/ }),
12584
- /* 227 */
12620
+ /* 228 */
12585
12621
  /***/ (function(module, __webpack_exports__, __webpack_require__) {
12586
12622
 
12587
12623
  "use strict";
@@ -12613,6 +12649,7 @@ __webpack_require__.r(__webpack_exports__);
12613
12649
  /* harmony import */ var _popup_js__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(212);
12614
12650
  /* harmony import */ var _RESTClient_js__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(215);
12615
12651
  /* harmony import */ var _spidTalk_js__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(223);
12652
+ /* harmony import */ var _global_registry_js__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(225);
12616
12653
  /* Copyright 2024 Schibsted Products & Technology AS. Licensed under the terms of the MIT license.
12617
12654
  * See LICENSE.md in the project root.
12618
12655
  */
@@ -12641,6 +12678,7 @@ function _toPrimitive(input, hint) { if (_typeof(input) !== "object" || input ==
12641
12678
 
12642
12679
 
12643
12680
 
12681
+
12644
12682
  var globalWindow = function globalWindow() {
12645
12683
  return window;
12646
12684
  };
@@ -12676,6 +12714,7 @@ var Payment = /*#__PURE__*/function () {
12676
12714
  this.publisher = publisher;
12677
12715
  this._setSpidServerUrl(env);
12678
12716
  this._setBffServerUrl(env);
12717
+ Object(_global_registry_js__WEBPACK_IMPORTED_MODULE_16__["registerGlobal"])(window, 'Payment', this);
12679
12718
  }
12680
12719
 
12681
12720
  /**