@schibsted/account-sdk-browser 4.8.7 → 5.0.0-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@schibsted/account-sdk-browser",
3
- "version": "4.8.7",
3
+ "version": "5.0.0-beta.2",
4
4
  "description": "Schibsted account SDK for browsers",
5
5
  "main": "index.js",
6
6
  "type": "module",
package/src/identity.d.ts CHANGED
@@ -13,26 +13,58 @@ export class Identity extends TinyEmitter {
13
13
  * @param {function} [options.log] - A function that receives debug log information. If not set,
14
14
  * no logging will be done
15
15
  * @param {object} [options.window] - window object
16
+ * @param {function} [options.callbackBeforeRedirect] - callback triggered before session refresh redirect happen
16
17
  * @throws {SDKError} - If any of options are invalid
17
18
  */
18
- constructor({ clientId, redirectUri, sessionDomain, env, log, window }: {
19
+ constructor({ clientId, redirectUri, sessionDomain, env, log, window, callbackBeforeRedirect }: {
19
20
  clientId: string;
20
21
  sessionDomain: string;
21
22
  redirectUri: string;
22
23
  env?: string;
23
24
  log?: Function;
24
25
  window?: any;
26
+ callbackBeforeRedirect?: Function;
25
27
  });
26
28
  _sessionInitiatedSent: boolean;
27
29
  window: any;
28
30
  clientId: string;
29
- cache: any;
31
+ sessionStorageCache: any;
32
+ localStorageCache: any;
30
33
  redirectUri: string;
31
34
  env: string;
32
35
  log: Function;
36
+ callbackBeforeRedirect: Function;
33
37
  _sessionDomain: string;
34
38
  _enableSessionCaching: boolean;
35
39
  _session: {};
40
+
41
+ /**
42
+ * Read tabId from session storage
43
+ * @returns {number}
44
+ * @private
45
+ */
46
+ private _getTabId;
47
+ /**
48
+ * Checks if getting session is blocked
49
+ * @private
50
+ *
51
+ * @returns {boolean|void}
52
+ */
53
+ private _isSessionCallBlocked;
54
+ /**
55
+ * Block calls to get session
56
+ * @private
57
+ *
58
+ * @returns {void}
59
+ */
60
+ private _blockSessionCall;
61
+ /**
62
+ * Unblocks calls to get session
63
+ * @private
64
+ *
65
+ * @returns {void}
66
+ */
67
+ private _unblockSessionCall;
36
68
  /**
37
69
  * Set SPiD server URL
38
70
  * @private
package/src/identity.js CHANGED
@@ -145,6 +145,13 @@ import version from './version.js';
145
145
  */
146
146
 
147
147
  const HAS_SESSION_CACHE_KEY = 'hasSession-cache';
148
+ const SESSION_CALL_BLOCKED_CACHE_KEY = 'sessionCallBlocked-cache';
149
+ const SESSION_CALL_BLOCKED_TTL = 1000 * 60 * 5;
150
+
151
+ const TAB_ID_KEY = 'tab-id-cache';
152
+ const TAB_ID = Math.floor(Math.random() * 100000)
153
+ const TAB_ID_TTL = 1000 * 60 * 60 * 24 * 30;
154
+
148
155
  const globalWindow = () => window;
149
156
 
150
157
  /**
@@ -160,9 +167,18 @@ export class Identity extends EventEmitter {
160
167
  * @param {function} [options.log] - A function that receives debug log information. If not set,
161
168
  * no logging will be done
162
169
  * @param {object} [options.window] - window object
170
+ * @param {function} [options.callbackBeforeRedirect] - callback triggered before session refresh redirect happen
163
171
  * @throws {SDKError} - If any of options are invalid
164
172
  */
165
- constructor({ clientId, redirectUri, sessionDomain, env = 'PRE', log, window = globalWindow() }) {
173
+ constructor({
174
+ clientId,
175
+ redirectUri,
176
+ sessionDomain,
177
+ env = 'PRE',
178
+ log,
179
+ window = globalWindow(),
180
+ callbackBeforeRedirect = ()=>{}
181
+ }) {
166
182
  super();
167
183
  assert(isNonEmptyString(clientId), 'clientId parameter is required');
168
184
  assert(isObject(window), 'The reference to window is missing');
@@ -173,10 +189,12 @@ export class Identity extends EventEmitter {
173
189
  this._sessionInitiatedSent = false;
174
190
  this.window = window;
175
191
  this.clientId = clientId;
176
- this.cache = new Cache(() => this.window && this.window.sessionStorage);
192
+ this.sessionStorageCache = new Cache(() => this.window && this.window.sessionStorage);
193
+ this.localStorageCache = new Cache(() => this.window && this.window.localStorage);
177
194
  this.redirectUri = redirectUri;
178
195
  this.env = env;
179
196
  this.log = log;
197
+ this.callbackBeforeRedirect = callbackBeforeRedirect;
180
198
  this._sessionDomain = sessionDomain;
181
199
 
182
200
  // Internal hack: set to false to always refresh from hassession
@@ -190,6 +208,61 @@ export class Identity extends EventEmitter {
190
208
  this._setBffServerUrl(env);
191
209
  this._setOauthServerUrl(env);
192
210
  this._setGlobalSessionServiceUrl(env);
211
+
212
+ this._unblockSessionCall();
213
+ }
214
+
215
+ /**
216
+ * Read tabId from session storage
217
+ * @returns {number}
218
+ * @private
219
+ */
220
+ _getTabId() {
221
+ if (this._enableSessionCaching) {
222
+ const tabId = this.sessionStorageCache.get(TAB_ID_KEY);
223
+ if (!tabId) {
224
+ this.sessionStorageCache.set(TAB_ID_KEY, TAB_ID, TAB_ID_TTL);
225
+ return TAB_ID;
226
+ }
227
+
228
+ return tabId;
229
+ }
230
+ }
231
+
232
+ /**
233
+ * Checks if getting session is blocked
234
+ * @private
235
+ *
236
+ * @returns {boolean|void}
237
+ */
238
+ _isSessionCallBlocked(){
239
+ return this.localStorageCache.get(SESSION_CALL_BLOCKED_CACHE_KEY);
240
+ }
241
+
242
+ /**
243
+ * Block calls to get session
244
+ * @private
245
+ *
246
+ * @returns {void}
247
+ */
248
+ _blockSessionCall(){
249
+ const SESSION_CALL_BLOCKED = true;
250
+
251
+ this.localStorageCache.set(
252
+ SESSION_CALL_BLOCKED_CACHE_KEY,
253
+ SESSION_CALL_BLOCKED,
254
+ SESSION_CALL_BLOCKED_TTL
255
+ );
256
+ }
257
+
258
+ /**
259
+ * Unblocks calls to get session
260
+ * @private
261
+ *
262
+ * @returns {void}
263
+ */
264
+ _unblockSessionCall(){
265
+ this.localStorageCache.delete(SESSION_CALL_BLOCKED_CACHE_KEY);
193
266
  }
194
267
 
195
268
  /**
@@ -480,9 +553,15 @@ export class Identity extends EventEmitter {
480
553
  * @return {Promise<HasSessionSuccessResponse|HasSessionFailureResponse>}
481
554
  */
482
555
  hasSession() {
556
+ const isSessionCallBlocked = this._isSessionCallBlocked()
557
+ if (isSessionCallBlocked) {
558
+ return this._session;
559
+ }
560
+
483
561
  if (this._hasSessionInProgress) {
484
562
  return this._hasSessionInProgress;
485
563
  }
564
+
486
565
  const _postProcess = (sessionData) => {
487
566
  if (sessionData.error) {
488
567
  throw new SDKError('HasSession failed', sessionData.error);
@@ -492,35 +571,60 @@ export class Identity extends EventEmitter {
492
571
  this._session = sessionData;
493
572
  return sessionData;
494
573
  };
574
+
575
+ const _checkRedirectionNeed = (sessionData={})=>{
576
+ const sessionDataKeys = Object.keys(sessionData);
577
+
578
+ return sessionDataKeys.length === 1 &&
579
+ sessionDataKeys[0] === 'redirectURL';
580
+ }
581
+
495
582
  const _getSession = async () => {
496
583
  if (this._enableSessionCaching) {
497
584
  // Try to resolve from cache (it has a TTL)
498
- let cachedSession = this.cache.get(HAS_SESSION_CACHE_KEY);
585
+ let cachedSession = this.sessionStorageCache.get(HAS_SESSION_CACHE_KEY);
499
586
  if (cachedSession) {
500
587
  return _postProcess(cachedSession);
501
588
  }
502
589
  }
503
590
  let sessionData = null;
504
591
  try {
505
- sessionData = await this._sessionService.get('/session');
592
+ sessionData = await this._sessionService.get('/v2/session', {tabId: this._getTabId()});
506
593
  } catch (err) {
507
594
  if (err && err.code === 400 && this._enableSessionCaching) {
508
595
  const expiresIn = 1000 * (err.expiresIn || 300);
509
- this.cache.set(HAS_SESSION_CACHE_KEY, { error: err }, expiresIn);
596
+ this.sessionStorageCache.set(HAS_SESSION_CACHE_KEY, { error: err }, expiresIn);
510
597
  }
511
598
  throw err;
512
599
  }
513
600
 
514
- if (sessionData && this._enableSessionCaching) {
515
- const expiresIn = 1000 * (sessionData.expiresIn || 300);
516
- this.cache.set(HAS_SESSION_CACHE_KEY, sessionData, expiresIn);
601
+ if (sessionData){
602
+ // for expiring session and safari browser do full page redirect to gain new session
603
+ if(_checkRedirectionNeed(sessionData)){
604
+ this._blockSessionCall();
605
+
606
+ await this.callbackBeforeRedirect();
607
+
608
+ return this._sessionService.makeUrl(sessionData.redirectURL, {tabId: this._getTabId()});
609
+ }
610
+
611
+ if (this._enableSessionCaching) {
612
+ const expiresIn = 1000 * (sessionData.expiresIn || 300);
613
+ this.sessionStorageCache.set(HAS_SESSION_CACHE_KEY, sessionData, expiresIn);
614
+ }
517
615
  }
616
+
518
617
  return _postProcess(sessionData);
519
618
  };
520
619
  this._hasSessionInProgress = _getSession()
521
620
  .then(
522
621
  sessionData => {
523
622
  this._hasSessionInProgress = false;
623
+
624
+ if (isUrl(sessionData)) {
625
+ return this.window.location.href = sessionData;
626
+ }
627
+
524
628
  return sessionData;
525
629
  },
526
630
  err => {
@@ -554,7 +658,7 @@ export class Identity extends EventEmitter {
554
658
  * @returns {void}
555
659
  */
556
660
  clearCachedUserSession() {
557
- this.cache.delete(HAS_SESSION_CACHE_KEY);
661
+ this.sessionStorageCache.delete(HAS_SESSION_CACHE_KEY);
558
662
  }
559
663
 
560
664
  /**
@@ -632,10 +736,10 @@ export class Identity extends EventEmitter {
632
736
  * meaning the same user's ID will differ between merchants.
633
737
  * Additionally, this identifier is bound to the external party provided as argument.
634
738
  *
635
- * @description This function calls {@link Identity#hasSession} internally and thus has the side
636
- * effect that it might perform an auto-login on the user
637
739
  * @param {string} externalParty
638
740
  * @param {string|null} optionalSuffix
741
+ * @description This function calls {@link Identity#hasSession} internally and thus has the side
742
+ * effect that it might perform an auto-login on the user
639
743
  * @throws {SDKError} If the `pairId` is missing in user session.
640
744
  * @throws {SDKError} If the `externalParty` is not defined
641
745
  * @return {Promise<string>} The merchant- and 3rd-party-specific `externalId`
@@ -765,7 +869,7 @@ export class Identity extends EventEmitter {
765
869
  prompt = 'select_account'
766
870
  }) {
767
871
  this._closePopup();
768
- this.cache.delete(HAS_SESSION_CACHE_KEY);
872
+ this.sessionStorageCache.delete(HAS_SESSION_CACHE_KEY);
769
873
  const url = this.loginUrl({
770
874
  state,
771
875
  acrValues,
@@ -814,7 +918,7 @@ export class Identity extends EventEmitter {
814
918
  * @return {void}
815
919
  */
816
920
  logout(redirectUri = this.redirectUri) {
817
- this.cache.delete(HAS_SESSION_CACHE_KEY);
921
+ this.sessionStorageCache.delete(HAS_SESSION_CACHE_KEY);
818
922
  this._maybeClearVarnishCookie();
819
923
  this.emit('logout');
820
924
  this.window.location.href = this.logoutUrl(redirectUri);
package/src/version.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // Automatically generated in 'npm version' by scripts/genversion.js
2
2
 
3
3
  'use strict'
4
- const version = '4.8.7';
4
+ const version = '5.0.0-beta.2';
5
5
  export default version;