@schibsted/account-sdk-browser 5.2.7 → 6.0.0-alpha.10

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 (109) hide show
  1. package/README.md +46 -301
  2. package/dist/account-sdk.d.ts +22 -0
  3. package/dist/account.d.ts +179 -0
  4. package/dist/cache.d.ts +65 -0
  5. package/dist/config.d.ts +86 -0
  6. package/dist/globals.d.ts +11 -0
  7. package/dist/has-access-response.d.ts +2 -0
  8. package/dist/identity.d.ts +302 -0
  9. package/dist/index.d.ts +11 -0
  10. package/dist/index.js +828 -0
  11. package/dist/index.js.map +1 -0
  12. package/dist/monetization.d.ts +39 -0
  13. package/{src → dist}/object.d.ts +4 -9
  14. package/dist/popup.d.ts +9 -0
  15. package/dist/resolve-browser-window.d.ts +1 -0
  16. package/dist/rest-client.d.ts +102 -0
  17. package/dist/rest-clients.d.ts +10 -0
  18. package/dist/sdk-error.d.ts +29 -0
  19. package/dist/session-response.d.ts +54 -0
  20. package/{src/spidTalk.d.ts → dist/spid-talk.d.ts} +4 -6
  21. package/dist/types/account.d.ts +48 -0
  22. package/dist/types/common.d.ts +28 -0
  23. package/dist/types/identity.d.ts +23 -0
  24. package/dist/types/login.d.ts +125 -0
  25. package/dist/types/monetization.d.ts +26 -0
  26. package/dist/types/session.d.ts +146 -0
  27. package/dist/url.d.ts +8 -0
  28. package/dist/validate.d.ts +50 -0
  29. package/dist/version.d.ts +2 -0
  30. package/package.json +34 -52
  31. package/src/account-sdk.ts +92 -0
  32. package/src/account.ts +332 -0
  33. package/src/{cache.js → cache.ts} +53 -38
  34. package/src/{config.js → config.ts} +7 -32
  35. package/src/globals.ts +8 -0
  36. package/src/has-access-response.ts +35 -0
  37. package/src/identity.ts +1023 -0
  38. package/src/index.ts +40 -0
  39. package/src/monetization.ts +128 -0
  40. package/src/{object.js → object.ts} +9 -16
  41. package/src/popup.ts +74 -0
  42. package/src/resolve-browser-window.ts +11 -0
  43. package/src/rest-client.ts +253 -0
  44. package/src/rest-clients.ts +30 -0
  45. package/src/sdk-error.ts +61 -0
  46. package/src/session-response.ts +100 -0
  47. package/src/{spidTalk.js → spid-talk.ts} +10 -12
  48. package/src/types/account.ts +55 -0
  49. package/src/types/common.ts +32 -0
  50. package/src/types/identity.ts +26 -0
  51. package/src/types/login.ts +150 -0
  52. package/src/types/monetization.ts +29 -0
  53. package/src/types/session.ts +169 -0
  54. package/src/{url.js → url.ts} +6 -10
  55. package/src/{validate.js → validate.ts} +27 -43
  56. package/src/{version.js → version.ts} +1 -2
  57. package/es5/global.js +0 -12968
  58. package/es5/global.js.map +0 -1
  59. package/es5/global.min.js +0 -2
  60. package/es5/global.min.js.map +0 -1
  61. package/es5/identity.js +0 -12212
  62. package/es5/identity.js.map +0 -1
  63. package/es5/identity.min.js +0 -2
  64. package/es5/identity.min.js.map +0 -1
  65. package/es5/index.js +0 -12940
  66. package/es5/index.js.map +0 -1
  67. package/es5/index.min.js +0 -2
  68. package/es5/index.min.js.map +0 -1
  69. package/es5/monetization.js +0 -9176
  70. package/es5/monetization.js.map +0 -1
  71. package/es5/monetization.min.js +0 -2
  72. package/es5/monetization.min.js.map +0 -1
  73. package/es5/payment.js +0 -8853
  74. package/es5/payment.js.map +0 -1
  75. package/es5/payment.min.js +0 -2
  76. package/es5/payment.min.js.map +0 -1
  77. package/identity.d.ts +0 -1
  78. package/identity.js +0 -5
  79. package/index.d.ts +0 -4
  80. package/index.js +0 -9
  81. package/monetization.d.ts +0 -1
  82. package/monetization.js +0 -5
  83. package/payment.d.ts +0 -1
  84. package/payment.js +0 -5
  85. package/src/RESTClient.d.ts +0 -89
  86. package/src/RESTClient.js +0 -193
  87. package/src/SDKError.d.ts +0 -16
  88. package/src/SDKError.js +0 -55
  89. package/src/__mocks__/.eslintrc.yml +0 -8
  90. package/src/__mocks__/RESTClient.js +0 -54
  91. package/src/cache.d.ts +0 -64
  92. package/src/config.d.ts +0 -34
  93. package/src/es5/global.js +0 -13
  94. package/src/es5/identity.js +0 -10
  95. package/src/es5/index.js +0 -13
  96. package/src/es5/monetization.js +0 -10
  97. package/src/es5/payment.js +0 -10
  98. package/src/global-registry.js +0 -20
  99. package/src/identity.d.ts +0 -679
  100. package/src/identity.js +0 -1157
  101. package/src/monetization.d.ts +0 -80
  102. package/src/monetization.js +0 -172
  103. package/src/payment.d.ts +0 -115
  104. package/src/payment.js +0 -211
  105. package/src/popup.d.ts +0 -10
  106. package/src/popup.js +0 -59
  107. package/src/url.d.ts +0 -10
  108. package/src/validate.d.ts +0 -64
  109. package/src/version.d.ts +0 -2
package/src/identity.js DELETED
@@ -1,1157 +0,0 @@
1
- /* Copyright 2024 Schibsted Products & Technology AS. Licensed under the terms of the MIT license.
2
- * See LICENSE.md in the project root.
3
- */
4
-
5
- 'use strict';
6
-
7
- import { assert, isStr, isNonEmptyString, isObject, isUrl, isStrIn } from './validate.js';
8
- import { cloneDeep } from './object.js';
9
- import { urlMapper } from './url.js';
10
- import { ENDPOINTS, NAMESPACE } from './config.js';
11
- import EventEmitter from 'tiny-emitter';
12
- import Cache from './cache.js';
13
- import * as popup from './popup.js';
14
- import RESTClient from './RESTClient.js';
15
- import SDKError from './SDKError.js';
16
- import * as spidTalk from './spidTalk.js';
17
- import version from './version.js';
18
- import { registerGlobal } from './global-registry.js';
19
-
20
- /**
21
- * @typedef {object} LoginOptions
22
- * @property {string} state - An opaque value used by the client to maintain state between
23
- * the request and callback. It's also recommended to prevent CSRF {@link https://tools.ietf.org/html/rfc6749#section-10.12}
24
- * @property {string} [acrValues] - Authentication Context Class Reference Values. If
25
- * omitted, the user will be asked to authenticate using username+password.
26
- * For 2FA (Two-Factor Authentication) possible values are `sms`, `otp` (one time password),
27
- * `password` (will force password confirmation, even if user is already logged in), `eid`. Those values might
28
- * be mixed as space-separated string. To make sure that user has authenticated with 2FA you need
29
- * to verify AMR (Authentication Methods References) claim in ID token.
30
- * Might also be used to ensure additional acr (sms, otp) for already logged-in users.
31
- * Supported value is also 'otp-email' means one time password using email.
32
- * @property {string} [scope] - The OAuth scopes for the tokens. This is a list of
33
- * scopes, separated by space. If the list of scopes contains `openid`, the generated tokens
34
- * includes the id token which can be useful for getting information about the user. Omitting
35
- * scope is allowed, while `invalid_scope` is returned when the client asks for a scope you
36
- * aren’t allowed to request. {@link https://tools.ietf.org/html/rfc6749#section-3.3}
37
- * @property {string} [redirectUri] - Redirect uri that will receive the
38
- * code. Must exactly match a redirectUri from your client in self-service
39
- * @property {boolean} [preferPopup] - Should we try to open a popup window?
40
- * @property {string} [loginHint] - User email or UUID hint
41
- * @property {string} [tag] - Pulse tag
42
- * @property {string} [teaser] - Teaser slug. Teaser with given slug will be displayed
43
- * in place of default teaser
44
- * @property {number|string} [maxAge] - Specifies the allowable elapsed time in seconds since
45
- * the last time the End-User was actively authenticated. If last authentication time is more
46
- * than maxAge seconds in the past, re-authentication will be required. See the OpenID Connect
47
- * spec section 3.1.2.1 for more information
48
- * @property {string} [locale] - Optional parameter to overwrite client locale setting.
49
- * New flows supports nb_NO, fi_FI, sv_SE, en_US
50
- * @property {boolean} [oneStepLogin] - Display username and password on one screen
51
- * @property {string} [prompt] - String that specifies whether the Authorization Server prompts the
52
- * End-User for re-authentication or confirm account screen. Supported values: `select_account` or `login`
53
- * @property {string} [xDomainId] - Identifier for cross-domain tracking in Pulse
54
- * @property {string} [xEnvironmentId] - Environment for cross-domain tracking in Pulse
55
- * @property {string} [originCampaign] - Campaign identifier for tracking in Pulse
56
- */
57
- /**
58
- * @typedef {object} SimplifiedLoginWidgetLoginOptions
59
- * @property {string|function(): (string|Promise<string>)} state - An opaque value used by the client to maintain state between
60
- * the request and callback. It's also recommended to prevent CSRF {@link https://tools.ietf.org/html/rfc6749#section-10.12}
61
- * @property {string} [acrValues] - Authentication Context Class Reference Values. If
62
- * omitted, the user will be asked to authenticate using username+password.
63
- * For 2FA (Two-Factor Authentication) possible values are `sms`, `otp` (one time password) and
64
- * `password` (will force password confirmation, even if user is already logged in). Those values might
65
- * be mixed as space-separated string. To make sure that user has authenticated with 2FA you need
66
- * to verify AMR (Authentication Methods References) claim in ID token.
67
- * Might also be used to ensure additional acr (sms, otp) for already logged-in users.
68
- * Supported value is also 'otp-email' means one time password using email.
69
- * @property {string} [scope] - The OAuth scopes for the tokens. This is a list of
70
- * scopes, separated by space. If the list of scopes contains `openid`, the generated tokens
71
- * includes the id token which can be useful for getting information about the user. Omitting
72
- * scope is allowed, while `invalid_scope` is returned when the client asks for a scope you
73
- * aren’t allowed to request. {@link https://tools.ietf.org/html/rfc6749#section-3.3}
74
- * @property {string} [redirectUri] - Redirect uri that will receive the
75
- * code. Must exactly match a redirectUri from your client in self-service
76
- * @property {boolean} [preferPopup] - Should we try to open a popup window?
77
- * @property {string} [loginHint] - User email or UUID hint
78
- * @property {string} [tag] - Pulse tag
79
- * @property {string} [teaser] - Teaser slug. Teaser with given slug will be displayed
80
- * in place of default teaser
81
- * @property {number|string} [maxAge] - Specifies the allowable elapsed time in seconds since
82
- * the last time the End-User was actively authenticated. If last authentication time is more
83
- * than maxAge seconds in the past, re-authentication will be required. See the OpenID Connect
84
- * spec section 3.1.2.1 for more information
85
- * @property {string} [locale] - Optional parameter to overwrite client locale setting.
86
- * New flows supports nb_NO, fi_FI, sv_SE, en_US
87
- * @property {boolean} [oneStepLogin] - Display username and password on one screen
88
- * @property {string} [prompt] - String that specifies whether the Authorization Server prompts the
89
- * End-User for reauthentication or confirm account screen. Supported values: `select_account` or `login`
90
- * @property {string} [xDomainId] - Identifier for cross-domain tracking in Pulse
91
- * @property {string} [xEnvironmentId] - Environment for cross-domain tracking in Pulse
92
- * @property {string} [originCampaign] - Campaign identifier for tracking in Pulse
93
- */
94
-
95
- /**
96
- * @typedef {object} HasSessionSuccessResponse
97
- * @property {boolean} result - Is the user connected to the merchant? (it means that the merchant
98
- * id is in the list of merchants listed of this user in the database)? Example: false
99
- * @property {string} userStatus - Example: 'notConnected' or 'connected'. Deprecated, use
100
- * `Identity.isConnected()`
101
- * @property {string} baseDomain - Example: 'localhost'
102
- * @property {string} id - Example: '58eca10fdbb9f6df72c3368f'. Obsolete
103
- * @property {number} userId - Example: 37162
104
- * @property {string} uuid - Example: 'b3b23aa7-34f2-5d02-a10e-5a3455c6ab2c'
105
- * @property {string} sp_id - Example: 'eyJjbGllbnRfaWQ...'
106
- * @property {number} expiresIn - Example: 30 * 60 * 1000 (for 30 minutes)
107
- * @property {number} serverTime - Example: 1506285759
108
- * @property {string} sig - Example: 'NCdzXaz4ZRb7...' The sig parameter is a concatenation of an
109
- * HMAC SHA-256 signature string, a dot (.) and a base64url encoded JSON object (session).
110
- * {@link http://techdocs.spid.no/sdks/js/response-signature-and-validation/}
111
- * @property {string} displayName - (Only for connected users) Example: 'batman'
112
- * @property {string} givenName - (Only for connected users) Example: 'Bruce'
113
- * @property {string} familyName - (Only for connected users) Example: 'Wayne'
114
- * @property {string} gender - (Only for connected users) Example: 'male', 'female', 'undisclosed'
115
- * @property {string} photo - (Only for connected users) Example:
116
- * 'http://www.srv.com/some/picture.jpg'
117
- * @property {boolean} tracking - (Only for connected users)
118
- * @property {boolean} clientAgreementAccepted - (Only for connected users)
119
- * @property {boolean} defaultAgreementAccepted - (Only for connected users)
120
- * @property {string} pairId
121
- * @property {string} sdrn
122
- */
123
-
124
- /**
125
- * Emitted when an error happens (useful for debugging)
126
- * @event Identity#error
127
- */
128
-
129
- /**
130
- * @typedef {object} HasSessionFailureResponse
131
- * @property {object} error
132
- * @property {number} error.code - Typically an HTTP response code. Example: 401
133
- * @property {string} error.description - Example: "No session found!"
134
- * @property {string} error.type - Example: "UserException"
135
- * @property {object} response
136
- * @property {string} response.baseDomain - Example: "localhost"
137
- * @property {number} response.expiresIn - Time span in milliseconds. Example: 30 * 60 * 1000 (for 30 minutes)
138
- * @property {boolean} response.result
139
- * @property {number} response.serverTime - Server time in seconds since the Unix Epoch. Example: 1506287788
140
- */
141
-
142
- /**
143
- * @typedef {object} SimplifiedLoginData
144
- * @property {string} identifier - Deprecated: User UUID, to be be used as `loginHint` for {@link Identity#login}
145
- * @property {string} display_text - Human-readable user identifier
146
- * @property {string} client_name - Client name
147
- */
148
-
149
- /**
150
- * @typedef {object} SimplifiedLoginWidgetOptions
151
- * @property {string} encoding - expected encoding of simplified login widget. Could be utf-8 (default), iso-8859-1 or iso-8859-15
152
- */
153
-
154
- const HAS_SESSION_CACHE_KEY = 'hasSession-cache';
155
- const SESSION_CALL_BLOCKED_CACHE_KEY = 'sessionCallBlocked-cache';
156
- const SESSION_CALL_BLOCKED_TTL = 1000 * 60 * 5;
157
-
158
- const TAB_ID_KEY = 'tab-id-cache';
159
- const TAB_ID = Math.floor(Math.random() * 100000)
160
- const TAB_ID_TTL = 1000 * 60 * 60 * 24 * 30;
161
-
162
- const globalWindow = () => window;
163
-
164
- /**
165
- * Provides Identity functionalty to a web page
166
- */
167
- export class Identity extends EventEmitter {
168
- /**
169
- * @param {object} options
170
- * @param {string} options.clientId - Example: "1234567890abcdef12345678"
171
- * @param {string} options.sessionDomain - Example: "https://id.site.com"
172
- * @param {string} options.redirectUri - Example: "https://site.com"
173
- * @param {string} [options.env=PRE] - Schibsted account environment: `PRE`, `PRO`, `PRO_NO`, `PRO_FI` or `PRO_DK`
174
- * @param {function} [options.log] - A function that receives debug log information. If not set,
175
- * no logging will be done
176
- * @param {object} [options.window] - window object
177
- * @param {function} [options.callbackBeforeRedirect] - callback triggered before session refresh redirect happen
178
- * @throws {SDKError} - If any of options are invalid
179
- */
180
- constructor({
181
- clientId,
182
- redirectUri,
183
- sessionDomain,
184
- env = 'PRE',
185
- log,
186
- window = globalWindow(),
187
- callbackBeforeRedirect = ()=>{}
188
- }) {
189
- super();
190
- assert(isNonEmptyString(clientId), 'clientId parameter is required');
191
- assert(isObject(window), 'The reference to window is missing');
192
- assert(!redirectUri || isUrl(redirectUri), 'redirectUri parameter is invalid');
193
- assert(sessionDomain && isUrl(sessionDomain), 'sessionDomain parameter is not a valid URL');
194
-
195
- spidTalk.emulate(window);
196
- this._sessionInitiatedSent = false;
197
- this.window = window;
198
- this.clientId = clientId;
199
- this.sessionStorageCache = new Cache(() => this.window && this.window.sessionStorage);
200
- this.localStorageCache = new Cache(() => this.window && this.window.localStorage);
201
- this.redirectUri = redirectUri;
202
- this.env = env;
203
- this.log = log;
204
- this.callbackBeforeRedirect = callbackBeforeRedirect;
205
- this._sessionDomain = sessionDomain;
206
-
207
- // Internal hack: set to false to always refresh from hassession
208
- this._enableSessionCaching = true;
209
-
210
- // Old session
211
- this._session = {};
212
-
213
- this._setSessionServiceUrl(sessionDomain);
214
- this._usedSessionServiceGetSessionEndpoint = this._sessionService.url.pathname && this._sessionService.url.pathname.length <= 1 ? 'v2/session' : 'session';
215
-
216
- this._setSpidServerUrl(env);
217
- this._setBffServerUrl(env);
218
- this._setOauthServerUrl(env);
219
- this._setGlobalSessionServiceUrl(env);
220
-
221
- this._unblockSessionCall();
222
-
223
- registerGlobal(window, 'Identity', this);
224
-
225
- }
226
-
227
- /**
228
- * Read tabId from session storage
229
- * @returns {number}
230
- * @private
231
- */
232
- _getTabId() {
233
- if (this._enableSessionCaching) {
234
- const tabId = this.sessionStorageCache.get(TAB_ID_KEY);
235
- if (!tabId) {
236
- this.sessionStorageCache.set(TAB_ID_KEY, TAB_ID, TAB_ID_TTL);
237
- return TAB_ID;
238
- }
239
-
240
- return tabId;
241
- }
242
- }
243
-
244
- /**
245
- * Checks if getting session is blocked
246
- * @private
247
- *
248
- * @returns {boolean|void}
249
- */
250
- _isSessionCallBlocked(){
251
- return this.localStorageCache.get(SESSION_CALL_BLOCKED_CACHE_KEY);
252
- }
253
-
254
- /**
255
- * Block calls to get session
256
- * @private
257
- *
258
- * @returns {void}
259
- */
260
- _blockSessionCall(){
261
- const SESSION_CALL_BLOCKED = true;
262
-
263
- this.localStorageCache.set(
264
- SESSION_CALL_BLOCKED_CACHE_KEY,
265
- SESSION_CALL_BLOCKED,
266
- SESSION_CALL_BLOCKED_TTL
267
- );
268
- }
269
-
270
- /**
271
- * Unblocks calls to get session
272
- * @private
273
- *
274
- * @returns {void}
275
- */
276
- _unblockSessionCall(){
277
- this.localStorageCache.delete(SESSION_CALL_BLOCKED_CACHE_KEY);
278
- }
279
-
280
- /**
281
- * Set SPiD server URL
282
- * @private
283
- * @param {string} url - real URL or 'PRE' style key
284
- * @returns {void}
285
- */
286
- _setSpidServerUrl(url) {
287
- assert(isStr(url), `url parameter is invalid: ${url}`);
288
- this._spid = new RESTClient({
289
- serverUrl: urlMapper(url, ENDPOINTS.SPiD),
290
- log: this.log,
291
- defaultParams: { client_id: this.clientId, redirect_uri: this.redirectUri },
292
- });
293
- }
294
-
295
- /**
296
- * Set OAuth server URL
297
- * @private
298
- * @param {string} url - real URL or 'PRE' style key
299
- * @returns {void}
300
- */
301
- _setOauthServerUrl(url) {
302
- assert(isStr(url), `url parameter is invalid: ${url}`);
303
- this._oauthService = new RESTClient({
304
- serverUrl: urlMapper(url, ENDPOINTS.SPiD),
305
- log: this.log,
306
- defaultParams: { client_id: this.clientId, redirect_uri: this.redirectUri },
307
- });
308
- }
309
-
310
- /**
311
- * Set BFF server URL
312
- * @private
313
- * @param {string} url - real URL or 'PRE' style key
314
- * @returns {void}
315
- */
316
- _setBffServerUrl(url) {
317
- assert(isStr(url), `url parameter is invalid: ${url}`);
318
- this._bffService = new RESTClient({
319
- serverUrl: urlMapper(url, ENDPOINTS.BFF),
320
- log: this.log,
321
- defaultParams: { client_id: this.clientId, redirect_uri: this.redirectUri },
322
- });
323
- }
324
-
325
- /**
326
- * Set site-specific session-service domain
327
- * @private
328
- * @param {string} domain - real URL — (**not** 'PRE' style env key)
329
- * @returns {void}
330
- */
331
- _setSessionServiceUrl(domain) {
332
- assert(isStr(domain), `domain parameter is invalid: ${domain}`);
333
- const client_sdrn = `sdrn:${NAMESPACE[this.env]}:client:${this.clientId}`;
334
- this._sessionService = new RESTClient({
335
- serverUrl: domain,
336
- log: this.log,
337
- defaultParams: { client_sdrn, redirect_uri: this.redirectUri, sdk_version: version },
338
- });
339
- }
340
-
341
- /**
342
- * Set global session-service server URL
343
- * @private
344
- * @param {string} url - real URL or 'PRE' style key
345
- * @returns {void}
346
- */
347
- _setGlobalSessionServiceUrl(url) {
348
- assert(isStr(url), `url parameter is invalid: ${url}`);
349
- const client_sdrn = `sdrn:${NAMESPACE[this.env]}:client:${this.clientId}`;
350
- this._globalSessionService = new RESTClient({
351
- serverUrl: urlMapper(url, ENDPOINTS.SESSION_SERVICE),
352
- log: this.log,
353
- defaultParams: { client_sdrn, sdk_version: version },
354
- });
355
- }
356
-
357
- /**
358
- * Emits the relevant events based on the previous and new reply from hassession
359
- * @private
360
- * @param {object} previous
361
- * @param {object} current
362
- * @returns {void}
363
- */
364
- _emitSessionEvent(previous, current) {
365
- /**
366
- * Emitted when the user is logged in (This happens as a result of calling
367
- * {@link Identity#hasSession}, so it is also emitted if the user was previously logged in)
368
- * @event Identity#login
369
- */
370
- if (current.userId) {
371
- this.emit('login', current);
372
- }
373
- /**
374
- * Emitted when the user logged out
375
- * @event Identity#logout
376
- */
377
- if (previous.userId && !current.userId) {
378
- this.emit('logout', current);
379
- }
380
- /**
381
- * Emitted when the user is changed. This happens as a result of calling
382
- * {@link Identity#hasSession}, and is emitted if there was a user both before and after
383
- * this invocation, and the userId has now changed
384
- * @event Identity#userChange
385
- */
386
- if (previous.userId && current.userId && previous.userId !== current.userId) {
387
- this.emit('userChange', current);
388
- }
389
- if (previous.userId || current.userId) {
390
- /**
391
- * Emitted when the session is changed. More accurately, this event is emitted if there
392
- * was a logged-in user either before or after {@link Identity#hasSession} was called.
393
- * In practice, this means the event is emitted a lot
394
- * @event Identity#sessionChange
395
- */
396
- this.emit('sessionChange', current);
397
- } else {
398
- /**
399
- * Emitted when there is no logged-in user. More specifically, it means that there was
400
- * no logged-in user neither before nor after {@link Identity#hasSession} was called
401
- * @event Identity#notLoggedin
402
- */
403
- this.emit('notLoggedin', current);
404
- }
405
- /**
406
- * Emitted when the session is first created
407
- * @event Identity#sessionInit
408
- */
409
- if (current.userId && !this._sessionInitiatedSent) {
410
- this._sessionInitiatedSent = true;
411
- this.emit('sessionInit', current);
412
- }
413
- /**
414
- * Emitted when the user status changes. This happens as a result of calling
415
- * {@link Identity#hasSession}
416
- * @event Identity#statusChange
417
- */
418
- if (previous.userStatus !== current.userStatus) {
419
- this.emit('statusChange', current);
420
- }
421
- }
422
-
423
- /**
424
- * Close this.popup if it exists and is open
425
- * @private
426
- * @returns {void}
427
- */
428
- _closePopup() {
429
- if (this.popup) {
430
- if (!this.popup.closed) {
431
- this.popup.close();
432
- }
433
- this.popup = null;
434
- }
435
- }
436
-
437
- /**
438
- * Set the Varnish cookie (`SP_ID`) when hasSession() is called. Note that most browsers require
439
- * that you are on a "real domain" for this to work — so, **not** `localhost`
440
- * @param {object} [options]
441
- * @param {number} [options.expiresIn] Override this to set number of seconds before the varnish
442
- * cookie expires. The default is to use the same time that hasSession responses are cached for
443
- * @param {string} [options.domain] Override cookie domain. E.g. «vg.no» instead of «www.vg.no»
444
- * @returns {void}
445
- */
446
- enableVarnishCookie(options) {
447
- let expiresIn = 0;
448
- let domain;
449
- if (Number.isInteger(options)) {
450
- expiresIn = options;
451
- }
452
- else if (typeof options == 'object') {
453
- expiresIn = options.expiresIn || expiresIn;
454
- domain = options.domain || domain;
455
- }
456
-
457
- assert(Number.isInteger(expiresIn), `'expiresIn' must be an integer`);
458
- assert(expiresIn >= 0, `'expiresIn' cannot be negative`);
459
- this.setVarnishCookie = true;
460
- this.varnishExpiresIn = expiresIn;
461
- this.varnishCookieDomain = domain;
462
- }
463
-
464
- /**
465
- * Set the Varnish cookie if configured
466
- * @private
467
- * @param {HasSessionSuccessResponse} sessionData
468
- * @returns {void}
469
- */
470
- _maybeSetVarnishCookie(sessionData) {
471
- if (!this.setVarnishCookie) {
472
- return;
473
- }
474
- const date = new Date();
475
- const validExpires = this.varnishExpiresIn
476
- || typeof sessionData.expiresIn === 'number' && sessionData.expiresIn > 0;
477
- if (validExpires) {
478
- const expires = this.varnishExpiresIn || sessionData.expiresIn;
479
- date.setTime(date.getTime() + (expires * 1000));
480
- } else {
481
- date.setTime(0);
482
- }
483
-
484
- // If the domain is missing or of the wrong type, we'll use document.domain
485
- let domain = this.varnishCookieDomain ||
486
- (typeof sessionData.baseDomain === 'string'
487
- ? sessionData.baseDomain
488
- : document.domain) ||
489
- '';
490
-
491
- const cookie = [
492
- `SP_ID=${sessionData.sp_id}`,
493
- `expires=${date.toUTCString()}`,
494
- `path=/`,
495
- `domain=.${domain}`
496
- ].join('; ');
497
- document.cookie = cookie;
498
- }
499
-
500
- /**
501
- * Clear the Varnish cookie if configured
502
- * @private
503
- * @returns {void}
504
- */
505
- _maybeClearVarnishCookie() {
506
- if (this.setVarnishCookie) {
507
- this._clearVarnishCookie();
508
- }
509
- }
510
-
511
- /**
512
- * Clear the Varnish cookie
513
- * @private
514
- * @returns {void}
515
- */
516
- _clearVarnishCookie() {
517
- const baseDomain = this._session && typeof this._session.baseDomain === 'string'
518
- ? this._session.baseDomain
519
- : document.domain;
520
-
521
- let domain = this.varnishCookieDomain ||
522
- baseDomain ||
523
- '';
524
-
525
- document.cookie = `SP_ID=nothing; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; domain=.${domain}`;
526
- }
527
-
528
- /**
529
- * Log used settings and version
530
- * @throws {SDKError} - If log method is not provided
531
- * @return {void}
532
- */
533
- logSettings() {
534
- if (!this.log && !window.console) {
535
- throw new SDKError('You have to provide log method in constructor');
536
- }
537
-
538
- const log = this.log || console.log;
539
-
540
- const settings = {
541
- clientId: this.clientId,
542
- redirectUri: this.redirectUri,
543
- env: this.env,
544
- sessionDomain: this._sessionDomain,
545
- sdkVersion: version
546
- }
547
-
548
- log(`Schibsted account SDK for browsers settings: \n${JSON.stringify(settings, null, 2)}`);
549
- }
550
-
551
- /**
552
- * @summary Queries the hassession endpoint and returns information about the status of the user
553
- * @description When we send a request to this endpoint, cookies sent along with the request
554
- * determines the status of the user.
555
- * @throws {SDKError} - If the call to the hasSession service fails in any way (this will happen
556
- * if, say, the user is not logged in)
557
- * @fires Identity#login
558
- * @fires Identity#logout
559
- * @fires Identity#userChange
560
- * @fires Identity#sessionChange
561
- * @fires Identity#notLoggedin
562
- * @fires Identity#sessionInit
563
- * @fires Identity#statusChange
564
- * @fires Identity#error
565
- * @return {Promise<HasSessionSuccessResponse|HasSessionFailureResponse>}
566
- */
567
- hasSession() {
568
- const isSessionCallBlocked = this._isSessionCallBlocked()
569
- if (isSessionCallBlocked) {
570
- return this._session;
571
- }
572
-
573
- if (this._hasSessionInProgress) {
574
- return this._hasSessionInProgress;
575
- }
576
-
577
- const _postProcess = (sessionData) => {
578
- if (sessionData.error) {
579
- throw new SDKError('HasSession failed', sessionData.error);
580
- }
581
- this._maybeSetVarnishCookie(sessionData);
582
- this._emitSessionEvent(this._session, sessionData);
583
- this._session = sessionData;
584
- return sessionData;
585
- };
586
-
587
- const _checkRedirectionNeed = (sessionData={})=>{
588
- const sessionDataKeys = Object.keys(sessionData);
589
-
590
- return sessionDataKeys.length === 1 &&
591
- sessionDataKeys[0] === 'redirectURL';
592
- }
593
-
594
- const _getSession = async () => {
595
- if (this._enableSessionCaching) {
596
- // Try to resolve from cache (it has a TTL)
597
- let cachedSession = this.sessionStorageCache.get(HAS_SESSION_CACHE_KEY);
598
- if (cachedSession) {
599
- return _postProcess(cachedSession);
600
- }
601
- }
602
- let sessionData = null;
603
- try {
604
- sessionData = await this._sessionService.get(this._usedSessionServiceGetSessionEndpoint, {tabId: this._getTabId()});
605
- } catch (err) {
606
- if (err && err.code === 400 && this._enableSessionCaching) {
607
- const expiresIn = 1000 * (err.expiresIn || 300);
608
- this.sessionStorageCache.set(HAS_SESSION_CACHE_KEY, { error: err }, expiresIn);
609
- } else if (err && err.code >= 500 && err.code < 600 && this._enableSessionCaching) {
610
- // Temporary fix: 30 seconds cache to limit number of calls when service is unavailable
611
- this.sessionStorageCache.set(HAS_SESSION_CACHE_KEY, { error: err }, 30 * 1000);
612
- }
613
- throw err;
614
- }
615
-
616
- if (sessionData){
617
- // for expiring session and safari browser do full page redirect to gain new session
618
- if(_checkRedirectionNeed(sessionData)){
619
- this._blockSessionCall();
620
-
621
- await this.callbackBeforeRedirect();
622
-
623
- return this._sessionService.makeUrl(sessionData.redirectURL, {tabId: this._getTabId()});
624
- }
625
-
626
- if (this._enableSessionCaching) {
627
- const expiresIn = 1000 * (sessionData.expiresIn || 300);
628
- this.sessionStorageCache.set(HAS_SESSION_CACHE_KEY, sessionData, expiresIn);
629
- }
630
- }
631
-
632
- return _postProcess(sessionData);
633
- };
634
- this._hasSessionInProgress = _getSession()
635
- .then(
636
- sessionData => {
637
- this._hasSessionInProgress = false;
638
-
639
- if (isUrl(sessionData)) {
640
- return this.window.location.href = sessionData;
641
- }
642
-
643
- return sessionData;
644
- },
645
- err => {
646
- this.emit('error', err);
647
- this._hasSessionInProgress = false;
648
- throw new SDKError('HasSession failed', err);
649
- }
650
- );
651
-
652
- return this._hasSessionInProgress;
653
- }
654
-
655
- /**
656
- * @async
657
- * @summary Allows the client app to check if the user is logged in to Schibsted account
658
- * @description This function calls {@link Identity#hasSession} internally and thus has the side
659
- * effect that it might perform an auto-login on the user
660
- * @return {Promise<boolean>}
661
- */
662
- async isLoggedIn() {
663
- try {
664
- const data = await this.hasSession();
665
- return 'result' in data;
666
- } catch (_) {
667
- return false;
668
- }
669
- }
670
-
671
- /**
672
- * Removes the cached user session.
673
- * @returns {void}
674
- */
675
- clearCachedUserSession() {
676
- this.sessionStorageCache.delete(HAS_SESSION_CACHE_KEY);
677
- }
678
-
679
- /**
680
- * @async
681
- * @summary Allows the caller to check if the current user is connected to the client_id in
682
- * Schibsted account. Being connected means that the user has agreed for their account to be
683
- * used by your web app and have accepted the required terms
684
- * @description This function calls {@link Identity#hasSession} internally and thus has the side
685
- * effect that it might perform an auto-login on the user
686
- * @summary Check if the user is connected to the client_id
687
- * @return {Promise<boolean>}
688
- */
689
- async isConnected() {
690
- try {
691
- const data = await this.hasSession();
692
- // if data is not an object, the promise will fail.
693
- // if the result is present, it's boolean. But if it's not, it should be assumed false.
694
- return !!data.result;
695
- } catch (_) {
696
- return false;
697
- }
698
- }
699
-
700
- /**
701
- * @async
702
- * @summary Returns information about the user
703
- * @description This function calls {@link Identity#hasSession} internally and thus has the side
704
- * effect that it might perform an auto-login on the user
705
- * @throws {SDKError} If the user isn't connected to the merchant
706
- * @throws {SDKError} If we couldn't get the user
707
- * @return {Promise<HasSessionSuccessResponse>}
708
- */
709
- async getUser() {
710
- const user = await this.hasSession();
711
- if (!user.result) {
712
- throw new SDKError('The user is not connected to this merchant');
713
- }
714
- return cloneDeep(user);
715
- }
716
-
717
- /**
718
- * @async
719
- * @summary
720
- * In Schibsted account, there are multiple ways of identifying a user; the `userId`,
721
- * `uuid` and `externalId` used for identifying a user-merchant pair (see {@link Identity#getExternalId}).
722
- * There are reasons for them all to exist. The `userId` is a numeric identifier, but
723
- * since Schibsted account is deployed separately in Norway and Sweden, there are a lot of
724
- * duplicates. The `userId` was introduced early, so many sites still need to use them for
725
- * legacy reasons. The `uuid` is universally unique, and so — if we could disregard a lot of
726
- * Schibsted components depending on the numeric `userId` — it would be a good identifier to use
727
- * @description This function calls {@link Identity#hasSession} internally and thus has the side
728
- * effect that it might perform an auto-login on the user
729
- * @throws {SDKError} If the user isn't connected to the merchant
730
- * @return {Promise<string>} The `userId` field (not to be confused with the `uuid`)
731
- */
732
- async getUserId() {
733
- const user = await this.hasSession();
734
- if (user.userId && user.result) {
735
- return user.userId;
736
- }
737
- throw new SDKError('The user is not connected to this merchant');
738
- }
739
-
740
- /**
741
- * @async
742
- * @function
743
- * @summary
744
- * Retrieves the external identifier (`externalId`) for the authenticated user.
745
- *
746
- * In Schibsted Account there are multiple ways of identifying users, however for integrations with
747
- * third-parties it's recommended to use `externalId` as it does not disclose
748
- * any critical data whilst allowing for user identification.
749
- *
750
- * `externalId` is merchant-scoped using a pairwise identifier (`pairId`),
751
- * meaning the same user's ID will differ between merchants.
752
- * Additionally, this identifier is bound to the external party provided as argument.
753
- *
754
- * @param {string} externalParty
755
- * @param {string|null} optionalSuffix
756
- * @description This function calls {@link Identity#hasSession} internally and thus has the side
757
- * effect that it might perform an auto-login on the user
758
- * @throws {SDKError} If the `pairId` is missing in user session.
759
- * @throws {SDKError} If the `externalParty` is not defined
760
- * @return {Promise<string>} The merchant- and 3rd-party-specific `externalId`
761
- */
762
- async getExternalId(externalParty, optionalSuffix = "") {
763
- const { pairId } = await this.hasSession();
764
-
765
- if (!pairId)
766
- throw new SDKError('pairId missing in user session!');
767
-
768
- if(!externalParty || externalParty.length === 0) {
769
- throw new SDKError('externalParty cannot be empty');
770
- }
771
- const _toHexDigest = (hashBuffer) =>{
772
- // convert buffer to byte array
773
- const hashArray = Array.from(new Uint8Array(hashBuffer));
774
- // convert bytes to hex string
775
- return hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
776
- }
777
-
778
- const _getSha256Digest = (data) => {
779
- return crypto.subtle.digest('SHA-256', data);
780
- }
781
-
782
- const _hashMessage = async (message) => {
783
- const msgUint8 = new TextEncoder().encode(message);
784
- return _getSha256Digest(msgUint8).then( (it) => _toHexDigest(it));
785
- }
786
-
787
- const _constructMessage = (pairId, externalParty, optionalSuffix) => {
788
- return optionalSuffix
789
- ? `${pairId}:${externalParty}:${optionalSuffix}`
790
- : `${pairId}:${externalParty}`;
791
- }
792
-
793
- return _hashMessage(_constructMessage(pairId, externalParty, optionalSuffix))
794
- }
795
-
796
- /**
797
- * @async
798
- * @summary Enables brands to programmatically get the current the SDRN based on the user's session.
799
- * @description This function calls {@link Identity#hasSession} internally and thus has the side
800
- * effect that it might perform an auto-login on the user
801
- * @throws {SDKError} If the SDRN is missing in user session object.
802
- * @returns {Promise<string>}
803
- */
804
- async getUserSDRN() {
805
- const { sdrn } = await this.hasSession();
806
- if (sdrn) {
807
- return sdrn;
808
- }
809
- throw new SDKError('Failed to get SDRN from user session');
810
- }
811
-
812
- /**
813
- * @async
814
- * @summary In Schibsted account, there are two ways of identifying a user; the `userId` and the
815
- * `uuid`. There are reasons for them both existing. The `userId` is a numeric identifier, but
816
- * since Schibsted account is deployed separately in Norway and Sweden, there are a lot of
817
- * duplicates. The `userId` was introduced early, so many sites still need to use them for
818
- * legacy reasons. The `uuid` is universally unique, and so — if we could disregard a lot of
819
- * Schibsted components depending on the numeric `userId` — it would be a good identifier to use
820
- * @description This function calls {@link Identity#hasSession} internally and thus has the side
821
- * effect that it might perform an auto-login on the user
822
- * @throws {SDKError} If the user isn't connected to the merchant
823
- * @return {Promise<string>} The `uuid` field (not to be confused with the `userId`)
824
- */
825
- async getUserUuid() {
826
- const user = await this.hasSession();
827
- if (user.uuid && user.result) {
828
- return user.uuid;
829
- }
830
- throw new SDKError('The user is not connected to this merchant');
831
- }
832
-
833
- /**
834
- * @async
835
- * @summary Get basic information about any user currently logged-in to their Schibsted account
836
- * in this browser. Can be used to provide context in a continue-as prompt.
837
- * @description This function relies on the global Schibsted account user session cookie, which
838
- * is a third-party cookie and hence might be blocked by the browser (for example due to ITP in
839
- * Safari). So there's no guarantee any data is returned, even though a user is logged-in in
840
- * the current browser.
841
- * @return {Promise<SimplifiedLoginData|null>}
842
- */
843
- async getUserContextData() {
844
- try {
845
- return await this._globalSessionService.get('user-context');
846
- } catch (_) {
847
- return null;
848
- }
849
- }
850
-
851
- /**
852
- * If a popup is desired, this function needs to be called in response to a user event (like
853
- * click or tap) in order to work correctly. Otherwise the popup will be blocked by the
854
- * browser's popup blockers and has to be explicitly authorized to be shown.
855
- * @summary Perform a login, either using a full-page redirect or a popup
856
- * @see https://tools.ietf.org/html/rfc6749#section-4.1.1
857
- *
858
- * @param {LoginOptions} options
859
- * @param {string} options.state
860
- * @param {string} [options.acrValues]
861
- * @param {string} [options.scope=openid]
862
- * @param {string} [options.redirectUri]
863
- * @param {boolean} [options.preferPopup=false]
864
- * @param {string} [options.loginHint]
865
- * @param {string} [options.tag]
866
- * @param {string} [options.teaser]
867
- * @param {number|string} [options.maxAge]
868
- * @param {string} [options.locale]
869
- * @param {boolean} [options.oneStepLogin=false]
870
- * @param {string} [options.prompt=select_account]
871
- * @param {string} [options.xDomainId]
872
- * @param {string} [options.xEnvironmentId]
873
- * @param {string} [options.originCampaign]
874
- * @return {Window|null} - Reference to popup window if created (or `null` otherwise)
875
- */
876
- login({
877
- state,
878
- acrValues = '',
879
- scope = 'openid',
880
- redirectUri = this.redirectUri,
881
- preferPopup = false,
882
- loginHint = '',
883
- tag = '',
884
- teaser = '',
885
- maxAge = '',
886
- locale = '',
887
- oneStepLogin = false,
888
- prompt = 'select_account',
889
- xDomainId = '',
890
- xEnvironmentId = '',
891
- originCampaign = ''
892
- }) {
893
- this._closePopup();
894
- this.sessionStorageCache.delete(HAS_SESSION_CACHE_KEY);
895
- const url = this.loginUrl({
896
- state,
897
- acrValues,
898
- scope,
899
- redirectUri,
900
- loginHint,
901
- tag,
902
- teaser,
903
- maxAge,
904
- locale,
905
- oneStepLogin,
906
- prompt,
907
- xDomainId,
908
- xEnvironmentId,
909
- originCampaign
910
- });
911
-
912
- if (preferPopup) {
913
- this.popup =
914
- popup.open(this.window, url, 'Schibsted account', { width: 360, height: 570 });
915
- if (this.popup) {
916
- return this.popup;
917
- }
918
- }
919
- this.window.location.href = url;
920
- return null;
921
- }
922
-
923
- /**
924
- * @async
925
- * @summary Retrieve the sp_id (Varnish ID)
926
- * @description This function calls {@link Identity#hasSession} internally and thus has the side
927
- * effect that it might perform an auto-login on the user
928
- * @return {Promise<string|null>} - The sp_id string or null (if the server didn't return it)
929
- */
930
- async getSpId() {
931
- try {
932
- const user = await this.hasSession();
933
- return user.sp_id || null;
934
- } catch (_) {
935
- return null;
936
- }
937
- }
938
-
939
- /**
940
- * @summary Logs the user out from the Identity platform
941
- * @param {string} redirectUri - Where to redirect the browser after logging out of Schibsted
942
- * account
943
- * @return {void}
944
- */
945
- logout(redirectUri = this.redirectUri) {
946
- this.sessionStorageCache.delete(HAS_SESSION_CACHE_KEY);
947
- this._maybeClearVarnishCookie();
948
- this.emit('logout');
949
- this.window.location.href = this.logoutUrl(redirectUri);
950
- }
951
-
952
- /**
953
- * Generates the link to the new login page that'll be used in the popup or redirect flow
954
- * @param {LoginOptions} options
955
- * @param {string} options.state
956
- * @param {string} [options.acrValues]
957
- * @param {string} [options.scope=openid]
958
- * @param {string} [options.redirectUri]
959
- * @param {string} [options.loginHint]
960
- * @param {string} [options.tag]
961
- * @param {string} [options.teaser]
962
- * @param {number|string} [options.maxAge]
963
- * @param {string} [options.locale]
964
- * @param {boolean} [options.oneStepLogin=false]
965
- * @param {string} [options.prompt=select_account]
966
- * @param {string} [options.xDomainId]
967
- * @param {string} [options.xEnvironmentId]
968
- * @param {string} [options.originCampaign]
969
- * @return {string} - The url
970
- */
971
- loginUrl({
972
- state,
973
- acrValues = '',
974
- scope = 'openid',
975
- redirectUri = this.redirectUri,
976
- loginHint = '',
977
- tag = '',
978
- teaser = '',
979
- maxAge = '',
980
- locale = '',
981
- oneStepLogin = false,
982
- prompt = 'select_account',
983
- xDomainId = '',
984
- xEnvironmentId = '',
985
- originCampaign = ''
986
- }) {
987
- if (typeof arguments[0] !== 'object') {
988
- // backward compatibility
989
- state = arguments[0];
990
- acrValues = arguments[1];
991
- scope = arguments[2] || scope;
992
- redirectUri = arguments[3] || redirectUri;
993
- loginHint = arguments[4] || loginHint;
994
- tag = arguments[5] || tag;
995
- teaser = arguments[6] || teaser;
996
- maxAge = isNaN(arguments[7]) ? maxAge : arguments[7];
997
- }
998
- const isValidAcrValue = (acrValue) => isStrIn(acrValue, ['password', 'otp', 'sms', 'eid-dk', 'eid-no', 'eid-se', 'eid-fi', 'eid'], true);
999
- assert(!acrValues || isStrIn(acrValues, ['', 'otp-email'], true) || acrValues.split(' ').every(isValidAcrValue),
1000
- `The acrValues parameter is not acceptable: ${acrValues}`);
1001
- assert(isUrl(redirectUri),
1002
- `loginUrl(): redirectUri must be a valid url but is ${redirectUri}`);
1003
- assert(isNonEmptyString(state),
1004
- `the state parameter should be a non empty string but it is ${state}`);
1005
-
1006
- return this._oauthService.makeUrl('oauth/authorize', {
1007
- response_type: 'code',
1008
- redirect_uri: redirectUri,
1009
- scope,
1010
- state,
1011
- acr_values: acrValues,
1012
- login_hint: loginHint,
1013
- tag,
1014
- teaser,
1015
- max_age: maxAge,
1016
- locale,
1017
- one_step_login: oneStepLogin || '',
1018
- prompt: acrValues ? '' : prompt,
1019
- x_domain_id: xDomainId,
1020
- x_env_id: xEnvironmentId,
1021
- utm_campaign: originCampaign
1022
- });
1023
- }
1024
-
1025
- /**
1026
- * The url for logging the user out
1027
- * @param {string} [redirectUri=this.redirectUri]
1028
- * @return {string} url
1029
- */
1030
- logoutUrl(redirectUri = this.redirectUri) {
1031
- assert(isUrl(redirectUri), `logoutUrl(): redirectUri is invalid`);
1032
- const params = { redirect_uri: redirectUri };
1033
- return this._sessionService.makeUrl('logout', params);
1034
- }
1035
-
1036
- /**
1037
- * The account summary page url
1038
- * @param {string} [redirectUri=this.redirectUri]
1039
- * @return {string}
1040
- */
1041
- accountUrl(redirectUri = this.redirectUri) {
1042
- return this._spid.makeUrl('profile-pages', {
1043
- response_type: 'code',
1044
- redirect_uri: redirectUri
1045
- });
1046
- }
1047
-
1048
- /**
1049
- * The phone editing page url
1050
- * @param {string} [redirectUri=this.redirectUri]
1051
- * @return {string}
1052
- */
1053
- phonesUrl(redirectUri = this.redirectUri) {
1054
- return this._spid.makeUrl('profile-pages/about-you/phone', {
1055
- response_type: 'code',
1056
- redirect_uri: redirectUri
1057
- });
1058
- }
1059
-
1060
- /**
1061
- * Function responsible for loading and displaying simplified login widget. How often
1062
- * widget will be display is up to you. Preferred way would be to show it once per user,
1063
- * and store that info in localStorage. Widget will be display only if user is logged in to SSO.
1064
- *
1065
- * @async
1066
- * @param {SimplifiedLoginWidgetLoginOptions} loginParams - the same as `options` param for login function. Login will be called on user
1067
- * continue action. `state` might be string or async function.
1068
- * @param {SimplifiedLoginWidgetOptions} [options] - additional configuration of Simplified Login Widget
1069
- * @fires Identity#simplifiedLoginOpened
1070
- * @fires Identity#simplifiedLoginCancelled
1071
- * @return {Promise<boolean|SDKError>} - will resolve to true if widget will be display. Otherwise, will throw SDKError
1072
- */
1073
- async showSimplifiedLoginWidget(loginParams, options) {
1074
- // getUserContextData doesn't throw exception
1075
- const userData = await this.getUserContextData();
1076
-
1077
- const queryParams = { client_id: this.clientId };
1078
- if (options && options.encoding) {
1079
- queryParams.encoding = options.encoding;
1080
- }
1081
- const widgetUrl = this._bffService.makeUrl('simplified-login-widget', queryParams, false);
1082
-
1083
- const prepareLoginParams = async (loginPrams) => {
1084
- if (typeof loginPrams.state === 'function') {
1085
- loginPrams.state = await loginPrams.state();
1086
- }
1087
-
1088
- return loginPrams;
1089
- }
1090
-
1091
- return new Promise(
1092
- (resolve, reject) => {
1093
- if (!userData || !userData.display_text || !userData.identifier) {
1094
- return reject(new SDKError('Missing user data'));
1095
- }
1096
-
1097
- const initialParams = {
1098
- displayText: userData.display_text,
1099
- env: this.env,
1100
- clientName: userData.client_name,
1101
- clientId: this.clientId,
1102
- providerId: userData.provider_id,
1103
- windowWidth: () => window.innerWidth,
1104
- windowOnResize: (f) => {
1105
- window.onresize = f;
1106
- },
1107
- };
1108
-
1109
- if (options && options.locale) {
1110
- initialParams.locale = options.locale;
1111
- }
1112
-
1113
- const loginHandler = async () => {
1114
- this.login(Object.assign(await prepareLoginParams(loginParams), {loginHint: userData.identifier}));
1115
- };
1116
-
1117
- const loginNotYouHandler = async () => {
1118
- this.login(Object.assign(await prepareLoginParams(loginParams), {loginHint: userData.identifier, prompt: 'login'}));
1119
- };
1120
-
1121
- const initHandler = () => {
1122
- /**
1123
- * Emitted when the simplified login widget is displayed on the screen
1124
- * @event Identity#simplifiedLoginOpened
1125
- */
1126
- this.emit('simplifiedLoginOpened');
1127
- }
1128
-
1129
- const cancelLoginHandler = () => {
1130
- /**
1131
- * Emitted when the user closes the simplified login widget
1132
- * @event Identity#simplifiedLoginCancelled
1133
- */
1134
- this.emit('simplifiedLoginCancelled');
1135
- }
1136
-
1137
- if (window.openSimplifiedLoginWidget) {
1138
- window.openSimplifiedLoginWidget(initialParams, loginHandler, loginNotYouHandler, initHandler, cancelLoginHandler);
1139
- return resolve(true);
1140
- }
1141
-
1142
- const simplifiedLoginWidget = document.createElement("script");
1143
- simplifiedLoginWidget.type = "text/javascript";
1144
- simplifiedLoginWidget.src = widgetUrl;
1145
- simplifiedLoginWidget.onload = () => {
1146
- window.openSimplifiedLoginWidget(initialParams, loginHandler, loginNotYouHandler, initHandler, cancelLoginHandler);
1147
- resolve(true);
1148
- };
1149
- simplifiedLoginWidget.onerror = () => {
1150
- reject(new SDKError('Error when loading simplified login widget content'));
1151
- };
1152
- document.getElementsByTagName('body')[0].appendChild(simplifiedLoginWidget);
1153
- });
1154
- }
1155
- }
1156
-
1157
- export default Identity;