@webex/plugin-authorization-browser-first-party 3.12.0-next.5 → 3.12.0-next.50
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 +38 -7
- package/dist/authorization.js +177 -21
- package/dist/authorization.js.map +1 -1
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/package.json +13 -13
- package/src/authorization.js +185 -29
- package/src/index.js +1 -1
- package/test/unit/spec/authorization.js +516 -82
package/README.md
CHANGED
|
@@ -178,13 +178,44 @@ webex.authorization.initQRCodeLogin();
|
|
|
178
178
|
|
|
179
179
|
### Properties
|
|
180
180
|
|
|
181
|
-
| Property
|
|
182
|
-
|
|
|
183
|
-
| `
|
|
184
|
-
| `
|
|
185
|
-
| `
|
|
186
|
-
| `
|
|
187
|
-
| `
|
|
181
|
+
| Property | Type | Description |
|
|
182
|
+
| -------------------------------------- | ---------------- | --------------------------------------------------------- |
|
|
183
|
+
| `initialAuthorizationCodeGrantOutcome` | string | Retained outcome of the automatic initialization exchange |
|
|
184
|
+
| `isAuthorizing` | boolean | True while a grant request is in flight |
|
|
185
|
+
| `isAuthenticating` | boolean | Alias of `isAuthorizing` |
|
|
186
|
+
| `ready` | boolean | Set true after initial redirect/code processing completes |
|
|
187
|
+
| `eventEmitter` | EventEmitter | Emits QR/Device login lifecycle events |
|
|
188
|
+
| `Events` | enum-like object | Accessible names for event types |
|
|
189
|
+
|
|
190
|
+
#### Initial authorization-code grant outcome
|
|
191
|
+
|
|
192
|
+
```javascript
|
|
193
|
+
import {InitialAuthorizationCodeGrantOutcomes} from '@webex/plugin-authorization-browser-first-party';
|
|
194
|
+
|
|
195
|
+
const didInitialExchangeSucceed =
|
|
196
|
+
webex.authorization.initialAuthorizationCodeGrantOutcome ===
|
|
197
|
+
InitialAuthorizationCodeGrantOutcomes.success;
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
`initialAuthorizationCodeGrantOutcome` describes only the automatic
|
|
201
|
+
`requestAuthorizationCodeGrant()` call made while this authorization plugin
|
|
202
|
+
instance initializes. Read it after `ready`:
|
|
203
|
+
|
|
204
|
+
- `not_attempted`: initialization did not invoke the exchange.
|
|
205
|
+
- `success`: the initialization exchange fulfilled.
|
|
206
|
+
- `failure`: the initialization exchange threw or rejected.
|
|
207
|
+
|
|
208
|
+
The value is a historical result retained for the lifetime of the SDK instance
|
|
209
|
+
and is not reset by logout. It does not represent current authorization state
|
|
210
|
+
or credentials hydrated from storage. It also does not track guest or device
|
|
211
|
+
authentication, token refreshes, or authorization-code exchanges requested
|
|
212
|
+
later on the same SDK instance.
|
|
213
|
+
|
|
214
|
+
OAuth redirect errors and CSRF validation failures occur before the exchange,
|
|
215
|
+
so the value remains `not_attempted`; these errors can throw before `ready`
|
|
216
|
+
becomes `true`. A non-redirecting logout does not cancel an initialization
|
|
217
|
+
exchange already in flight. If that exchange later settles, it can still update
|
|
218
|
+
credentials and this retained outcome.
|
|
188
219
|
|
|
189
220
|
## Security Considerations
|
|
190
221
|
|
package/dist/authorization.js
CHANGED
|
@@ -5,19 +5,20 @@ var _interopRequireDefault = require("@babel/runtime-corejs2/helpers/interopRequ
|
|
|
5
5
|
_Object$defineProperty(exports, "__esModule", {
|
|
6
6
|
value: true
|
|
7
7
|
});
|
|
8
|
-
exports.default = exports.Events = void 0;
|
|
8
|
+
exports.default = exports.InitialAuthorizationCodeGrantOutcomes = exports.Events = void 0;
|
|
9
|
+
var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/objectWithoutProperties"));
|
|
9
10
|
var _apply = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/reflect/apply"));
|
|
10
11
|
var _promise = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/promise"));
|
|
11
12
|
var _assign = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/object/assign"));
|
|
12
13
|
var _entries = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/object/entries"));
|
|
13
14
|
var _deleteProperty = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/reflect/delete-property"));
|
|
14
|
-
var
|
|
15
|
+
var _from = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/array/from"));
|
|
15
16
|
var _getOwnPropertyDescriptor = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/object/get-own-property-descriptor"));
|
|
16
17
|
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/slicedToArray"));
|
|
17
18
|
var _typeof2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/typeof"));
|
|
18
19
|
var _applyDecoratedDescriptor2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/applyDecoratedDescriptor"));
|
|
19
20
|
var _querystring = _interopRequireDefault(require("querystring"));
|
|
20
|
-
var
|
|
21
|
+
var _url2 = _interopRequireDefault(require("url"));
|
|
21
22
|
var _events = require("events");
|
|
22
23
|
var _common = require("@webex/common");
|
|
23
24
|
var _webexCore = require("@webex/webex-core");
|
|
@@ -25,6 +26,7 @@ var _lodash = require("lodash");
|
|
|
25
26
|
var _uuid = _interopRequireDefault(require("uuid"));
|
|
26
27
|
var _encBase64url = _interopRequireDefault(require("crypto-js/enc-base64url"));
|
|
27
28
|
var _cryptoJs = _interopRequireDefault(require("crypto-js"));
|
|
29
|
+
var _excluded = ["csrf_token"];
|
|
28
30
|
var _dec, _dec2, _obj; // @ts-nocheck
|
|
29
31
|
/* eslint-disable */
|
|
30
32
|
/*!
|
|
@@ -35,9 +37,6 @@ var _dec, _dec2, _obj; // @ts-nocheck
|
|
|
35
37
|
* TS checking disabled: file uses legacy decorator syntax inside an object literal
|
|
36
38
|
* transformed by Babel. Safe to ignore for now.
|
|
37
39
|
*/
|
|
38
|
-
// Necessary to require lodash this way in order to stub
|
|
39
|
-
// methods in the unit test
|
|
40
|
-
var lodash = require('lodash');
|
|
41
40
|
var OAUTH2_CSRF_TOKEN = 'oauth2-csrf-token';
|
|
42
41
|
var OAUTH2_CODE_VERIFIER = 'oauth2-code-verifier';
|
|
43
42
|
|
|
@@ -52,6 +51,18 @@ var Events = exports.Events = {
|
|
|
52
51
|
qRCodeLogin: 'qRCodeLogin'
|
|
53
52
|
};
|
|
54
53
|
|
|
54
|
+
/**
|
|
55
|
+
* Terminal outcomes for the automatic authorization-code exchange performed
|
|
56
|
+
* during authorization plugin initialization.
|
|
57
|
+
*
|
|
58
|
+
* @enum {string}
|
|
59
|
+
*/
|
|
60
|
+
var InitialAuthorizationCodeGrantOutcomes = exports.InitialAuthorizationCodeGrantOutcomes = {
|
|
61
|
+
failure: 'failure',
|
|
62
|
+
notAttempted: 'not_attempted',
|
|
63
|
+
success: 'success'
|
|
64
|
+
};
|
|
65
|
+
|
|
55
66
|
/**
|
|
56
67
|
* Browser support for OAuth2 for first-party (Webex Web Client) usage.
|
|
57
68
|
*
|
|
@@ -82,6 +93,37 @@ var Events = exports.Events = {
|
|
|
82
93
|
*/
|
|
83
94
|
var Authorization = _webexCore.WebexPlugin.extend((_dec = (0, _common.whileInFlight)('isAuthorizing'), _dec2 = (0, _common.whileInFlight)('isAuthorizing'), _obj = {
|
|
84
95
|
derived: {
|
|
96
|
+
/**
|
|
97
|
+
* Retains the terminal outcome of the automatic authorization-code exchange
|
|
98
|
+
* performed during this authorization plugin instance's initialization.
|
|
99
|
+
*
|
|
100
|
+
* This historical value does not represent current authorization state,
|
|
101
|
+
* credentials hydrated from storage, guest authentication, or
|
|
102
|
+
* authorization-code exchanges requested later on the same SDK instance. It
|
|
103
|
+
* is not reset by logout. OAuth redirect errors and CSRF validation failures
|
|
104
|
+
* occur before the exchange, so the value remains not_attempted; these errors
|
|
105
|
+
* can throw before ready becomes true.
|
|
106
|
+
*
|
|
107
|
+
* Calling logout({noRedirect: true}) does not cancel an initialization
|
|
108
|
+
* exchange already in flight. If that exchange later settles, it can still
|
|
109
|
+
* update credentials and this retained outcome.
|
|
110
|
+
*
|
|
111
|
+
* Interpret only after authorization readiness:
|
|
112
|
+
* - not_attempted: initialization did not invoke requestAuthorizationCodeGrant()
|
|
113
|
+
* - success: the initialization exchange fulfilled
|
|
114
|
+
* - failure: the initialization exchange threw or rejected
|
|
115
|
+
*
|
|
116
|
+
* @instance
|
|
117
|
+
* @memberof AuthorizationBrowserFirstParty
|
|
118
|
+
* @readonly
|
|
119
|
+
* @type {string}
|
|
120
|
+
*/
|
|
121
|
+
initialAuthorizationCodeGrantOutcome: {
|
|
122
|
+
deps: ['_initialAuthorizationCodeGrantOutcome'],
|
|
123
|
+
fn: function fn() {
|
|
124
|
+
return this._initialAuthorizationCodeGrantOutcome;
|
|
125
|
+
}
|
|
126
|
+
},
|
|
85
127
|
/**
|
|
86
128
|
* Alias of {@link AuthorizationBrowserFirstParty#isAuthorizing}
|
|
87
129
|
* @instance
|
|
@@ -106,6 +148,14 @@ var Authorization = _webexCore.WebexPlugin.extend((_dec = (0, _common.whileInFli
|
|
|
106
148
|
default: false,
|
|
107
149
|
type: 'boolean'
|
|
108
150
|
},
|
|
151
|
+
/**
|
|
152
|
+
* Internal backing state for the initial authorization-code grant outcome.
|
|
153
|
+
* @private
|
|
154
|
+
*/
|
|
155
|
+
_initialAuthorizationCodeGrantOutcome: {
|
|
156
|
+
default: InitialAuthorizationCodeGrantOutcomes.notAttempted,
|
|
157
|
+
type: 'string'
|
|
158
|
+
},
|
|
109
159
|
/**
|
|
110
160
|
* Indicates that the plugin has finished any automatic startup
|
|
111
161
|
* processing (e.g., exchanging a returned authorization code)
|
|
@@ -194,7 +244,7 @@ var Authorization = _webexCore.WebexPlugin.extend((_dec = (0, _common.whileInFli
|
|
|
194
244
|
attrs[_key] = arguments[_key];
|
|
195
245
|
}
|
|
196
246
|
var ret = (0, _apply.default)(_webexCore.WebexPlugin.prototype.initialize, this, attrs);
|
|
197
|
-
var location =
|
|
247
|
+
var location = _url2.default.parse(this.webex.getWindow().location.href, true);
|
|
198
248
|
|
|
199
249
|
// Check if redirect includes error
|
|
200
250
|
this._checkForErrors(location);
|
|
@@ -208,7 +258,7 @@ var Authorization = _webexCore.WebexPlugin.extend((_dec = (0, _common.whileInFli
|
|
|
208
258
|
|
|
209
259
|
// Decode and parse state object (if present)
|
|
210
260
|
if (location.query.state) {
|
|
211
|
-
location.query.state =
|
|
261
|
+
location.query.state = (0, _common.decodeState)(location.query.state);
|
|
212
262
|
} else {
|
|
213
263
|
location.query.state = {};
|
|
214
264
|
}
|
|
@@ -247,7 +297,10 @@ var Authorization = _webexCore.WebexPlugin.extend((_dec = (0, _common.whileInFli
|
|
|
247
297
|
code: code,
|
|
248
298
|
codeVerifier: codeVerifier
|
|
249
299
|
});
|
|
300
|
+
}).then(function () {
|
|
301
|
+
_this._initialAuthorizationCodeGrantOutcome = InitialAuthorizationCodeGrantOutcomes.success;
|
|
250
302
|
}).catch(function (error) {
|
|
303
|
+
_this._initialAuthorizationCodeGrantOutcome = InitialAuthorizationCodeGrantOutcomes.failure;
|
|
251
304
|
_this.logger.warn('authorization: failed initial authorization code grant request', error);
|
|
252
305
|
}).then(function () {
|
|
253
306
|
// Mark plugin ready regardless of success/failure of token exchange
|
|
@@ -347,6 +400,96 @@ var Authorization = _webexCore.WebexPlugin.extend((_dec = (0, _common.whileInFli
|
|
|
347
400
|
}
|
|
348
401
|
return _promise.default.resolve();
|
|
349
402
|
},
|
|
403
|
+
/**
|
|
404
|
+
* Initiates third-party (social provider) login. Generates a CSRF token,
|
|
405
|
+
* embeds it in `options.state.csrf_token`, and delegates to
|
|
406
|
+
* `initiateThirdPartyLoginRedirect` for navigation.
|
|
407
|
+
*
|
|
408
|
+
* @instance
|
|
409
|
+
* @memberof AuthorizationBrowserFirstParty
|
|
410
|
+
* @param {Object} options
|
|
411
|
+
* @param {string} options.oauth2provider
|
|
412
|
+
* @param {string} options.returnURL
|
|
413
|
+
* @param {Object} [options.state] - Caller-supplied state object. Merged
|
|
414
|
+
* with the generated `csrf_token`.
|
|
415
|
+
* @returns {Promise<void>}
|
|
416
|
+
*/
|
|
417
|
+
initiateThirdPartyLogin: function initiateThirdPartyLogin() {
|
|
418
|
+
var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
419
|
+
options = (0, _lodash.cloneDeep)(options);
|
|
420
|
+
if (options.state !== undefined && !(0, _lodash.isObject)(options.state)) {
|
|
421
|
+
throw new Error('if specified, `options.state` must be an object');
|
|
422
|
+
}
|
|
423
|
+
options.state = options.state || {};
|
|
424
|
+
options.state.csrf_token = this._generateSecurityToken();
|
|
425
|
+
return this.initiateThirdPartyLoginRedirect(options);
|
|
426
|
+
},
|
|
427
|
+
/**
|
|
428
|
+
* Performs the navigation step of the third-party login flow. Builds the
|
|
429
|
+
* IdBroker URL via `Credentials#buildThirdPartyLoginUrl` and assigns it
|
|
430
|
+
* to `getWindow().location`.
|
|
431
|
+
*
|
|
432
|
+
* Mirrors `initiateAuthorizationCodeGrant` for the `/authorize` flow.
|
|
433
|
+
* Consumers may override this method for custom navigation handling
|
|
434
|
+
* (e.g. postMessage in iframed contexts).
|
|
435
|
+
*
|
|
436
|
+
* @instance
|
|
437
|
+
* @memberof AuthorizationBrowserFirstParty
|
|
438
|
+
* @param {Object} options
|
|
439
|
+
* @param {string} options.oauth2provider
|
|
440
|
+
* @param {string} options.returnURL
|
|
441
|
+
* @returns {Promise<void>}
|
|
442
|
+
*/
|
|
443
|
+
initiateThirdPartyLoginRedirect: function initiateThirdPartyLoginRedirect() {
|
|
444
|
+
var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
445
|
+
this.logger.info('authorization: initiating third-party login redirect');
|
|
446
|
+
try {
|
|
447
|
+
var _url = this.webex.credentials.buildThirdPartyLoginUrl(options);
|
|
448
|
+
this.webex.getWindow().location = _url;
|
|
449
|
+
} catch (err) {
|
|
450
|
+
return _promise.default.reject(err);
|
|
451
|
+
}
|
|
452
|
+
return _promise.default.resolve();
|
|
453
|
+
},
|
|
454
|
+
/**
|
|
455
|
+
* Handles the third-party (social provider) login callback. Reads the
|
|
456
|
+
* current `window.location`, decodes `state`, validates the CSRF token
|
|
457
|
+
* (`state.csrf_token`), scrubs sensitive parameters from the URL via
|
|
458
|
+
* `_cleanUrl`, and returns the parsed payload.
|
|
459
|
+
*
|
|
460
|
+
* Mirrors `initialize()` in always operating on the live
|
|
461
|
+
* `window.location`
|
|
462
|
+
*
|
|
463
|
+
* `idToken` is single-use: it is parsed out of the URL exactly once and
|
|
464
|
+
* the calling client is expected to exchange it (or discard it)
|
|
465
|
+
* immediately. The returned `state` has `csrf_token` removed.
|
|
466
|
+
*
|
|
467
|
+
* @instance
|
|
468
|
+
* @memberof AuthorizationBrowserFirstParty
|
|
469
|
+
* @returns {{idToken: string|undefined, email: string|undefined,
|
|
470
|
+
* error: string|undefined, state: Object}}
|
|
471
|
+
*/
|
|
472
|
+
handleThirdPartyCallback: function handleThirdPartyCallback() {
|
|
473
|
+
var location = _url2.default.parse(this.webex.getWindow().location.href, true);
|
|
474
|
+
location.query.state = (0, _common.decodeState)(location.query.state || 'e30');
|
|
475
|
+
this._verifySecurityToken(location.query, {
|
|
476
|
+
requireMatch: true
|
|
477
|
+
});
|
|
478
|
+
this._cleanUrl(location);
|
|
479
|
+
var _location$query = location.query,
|
|
480
|
+
idToken = _location$query.id_token,
|
|
481
|
+
email = _location$query.email,
|
|
482
|
+
error = _location$query.error,
|
|
483
|
+
_location$query$state = _location$query.state,
|
|
484
|
+
csrf_token = _location$query$state.csrf_token,
|
|
485
|
+
state = (0, _objectWithoutProperties2.default)(_location$query$state, _excluded);
|
|
486
|
+
return {
|
|
487
|
+
idToken: idToken,
|
|
488
|
+
email: email,
|
|
489
|
+
error: error,
|
|
490
|
+
state: state
|
|
491
|
+
};
|
|
492
|
+
},
|
|
350
493
|
/**
|
|
351
494
|
* Called by {@link WebexCore#logout()}.
|
|
352
495
|
* Constructs logout URL and (unless suppressed) navigates away to ensure
|
|
@@ -696,8 +839,9 @@ var Authorization = _webexCore.WebexPlugin.extend((_dec = (0, _common.whileInFli
|
|
|
696
839
|
* - HTTP referrer headers to third-party content
|
|
697
840
|
*
|
|
698
841
|
* Approach:
|
|
699
|
-
* - Remove 'code'
|
|
700
|
-
*
|
|
842
|
+
* - Remove 'code' (OAuth code-grant), 'id_token', and 'email'
|
|
843
|
+
* (third-party callback).
|
|
844
|
+
* - Remove 'state' entirely if it only contained csrf_token.
|
|
701
845
|
* - Else, re-encode remaining state fields (minus csrf_token).
|
|
702
846
|
* - Replace current history entry (no page reload).
|
|
703
847
|
*
|
|
@@ -711,14 +855,16 @@ var Authorization = _webexCore.WebexPlugin.extend((_dec = (0, _common.whileInFli
|
|
|
711
855
|
location = (0, _lodash.cloneDeep)(location);
|
|
712
856
|
if (this.webex.getWindow().history && this.webex.getWindow().history.replaceState) {
|
|
713
857
|
(0, _deleteProperty.default)(location.query, 'code');
|
|
858
|
+
(0, _deleteProperty.default)(location.query, 'id_token');
|
|
859
|
+
(0, _deleteProperty.default)(location.query, 'email');
|
|
714
860
|
if ((0, _lodash.isEmpty)((0, _lodash.omit)(location.query.state, 'csrf_token'))) {
|
|
715
861
|
(0, _deleteProperty.default)(location.query, 'state');
|
|
716
862
|
} else {
|
|
717
|
-
location.query.state =
|
|
863
|
+
location.query.state = (0, _common.encodeState)((0, _lodash.omit)(location.query.state, 'csrf_token'));
|
|
718
864
|
}
|
|
719
865
|
location.search = _querystring.default.stringify(location.query);
|
|
720
866
|
(0, _deleteProperty.default)(location, 'query');
|
|
721
|
-
this.webex.getWindow().history.replaceState({}, null,
|
|
867
|
+
this.webex.getWindow().history.replaceState({}, null, _url2.default.format(location));
|
|
722
868
|
}
|
|
723
869
|
},
|
|
724
870
|
/**
|
|
@@ -727,7 +873,8 @@ var Authorization = _webexCore.WebexPlugin.extend((_dec = (0, _common.whileInFli
|
|
|
727
873
|
* during authorization code exchange; removes it once consumed.
|
|
728
874
|
*
|
|
729
875
|
* Implementation details:
|
|
730
|
-
* - Creates a 128 character string using
|
|
876
|
+
* - Creates a 128 character string using a cryptographically secure random
|
|
877
|
+
* source and the base64url safe alphabet.
|
|
731
878
|
* - Computes SHA256 hash, encodes to base64url (no padding).
|
|
732
879
|
*
|
|
733
880
|
* @instance
|
|
@@ -740,8 +887,10 @@ var Authorization = _webexCore.WebexPlugin.extend((_dec = (0, _common.whileInFli
|
|
|
740
887
|
|
|
741
888
|
// eslint-disable-next-line no-underscore-dangle
|
|
742
889
|
var safeCharacterMap = _encBase64url.default._safe_map;
|
|
743
|
-
var
|
|
744
|
-
|
|
890
|
+
var randomValues = new Uint8Array(128);
|
|
891
|
+
this.webex.getWindow().crypto.getRandomValues(randomValues);
|
|
892
|
+
var codeVerifier = (0, _from.default)(randomValues, function (randomValue) {
|
|
893
|
+
return safeCharacterMap[randomValue & safeCharacterMap.length - 1];
|
|
745
894
|
}).join('');
|
|
746
895
|
var codeChallenge = _cryptoJs.default.SHA256(codeVerifier).toString(_encBase64url.default);
|
|
747
896
|
this.webex.getWindow().sessionStorage.setItem(OAUTH2_CODE_VERIFIER, codeVerifier);
|
|
@@ -773,24 +922,31 @@ var Authorization = _webexCore.WebexPlugin.extend((_dec = (0, _common.whileInFli
|
|
|
773
922
|
* - Ensure state + state.csrf_token exist.
|
|
774
923
|
* - Compare values; throw descriptive errors on mismatch / absence.
|
|
775
924
|
*
|
|
776
|
-
* If no stored token (e.g., user navigated directly), silently returns
|
|
925
|
+
* If no stored token (e.g., user navigated directly), silently returns
|
|
926
|
+
* unless `options.requireMatch` is `true`, in which case absence of a
|
|
927
|
+
* stored token is treated as a CSRF failure.
|
|
777
928
|
*
|
|
778
929
|
* @instance
|
|
779
930
|
* @memberof AuthorizationBrowserFirstParty
|
|
780
931
|
* @param {Object} query - Parsed query (location.query)
|
|
932
|
+
* @param {Object} [options]
|
|
933
|
+
* @param {boolean} [options.requireMatch=false] - When true, throws if
|
|
934
|
+
* no stored sessionToken is present.
|
|
781
935
|
* @private
|
|
782
936
|
* @returns {void}
|
|
783
937
|
*/
|
|
784
938
|
_verifySecurityToken: function _verifySecurityToken(query) {
|
|
939
|
+
var _query$state;
|
|
940
|
+
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
785
941
|
var sessionToken = this.webex.getWindow().sessionStorage.getItem(OAUTH2_CSRF_TOKEN);
|
|
786
942
|
this.webex.getWindow().sessionStorage.removeItem(OAUTH2_CSRF_TOKEN);
|
|
787
943
|
if (!sessionToken) {
|
|
944
|
+
if (options.requireMatch) {
|
|
945
|
+
throw new Error('CSRF token missing from session storage');
|
|
946
|
+
}
|
|
788
947
|
return;
|
|
789
948
|
}
|
|
790
|
-
if (!query.state) {
|
|
791
|
-
throw new Error("Expected CSRF token ".concat(sessionToken, ", but not found in redirect query"));
|
|
792
|
-
}
|
|
793
|
-
if (!query.state.csrf_token) {
|
|
949
|
+
if (!((_query$state = query.state) !== null && _query$state !== void 0 && _query$state.csrf_token)) {
|
|
794
950
|
throw new Error("Expected CSRF token ".concat(sessionToken, ", but not found in redirect query"));
|
|
795
951
|
}
|
|
796
952
|
var token = query.state.csrf_token;
|
|
@@ -798,7 +954,7 @@ var Authorization = _webexCore.WebexPlugin.extend((_dec = (0, _common.whileInFli
|
|
|
798
954
|
throw new Error("CSRF token ".concat(token, " does not match stored token ").concat(sessionToken));
|
|
799
955
|
}
|
|
800
956
|
},
|
|
801
|
-
version: "3.12.0-next.
|
|
957
|
+
version: "3.12.0-next.50"
|
|
802
958
|
}, (0, _applyDecoratedDescriptor2.default)(_obj, "initiateAuthorizationCodeGrant", [_dec], (0, _getOwnPropertyDescriptor.default)(_obj, "initiateAuthorizationCodeGrant"), _obj), (0, _applyDecoratedDescriptor2.default)(_obj, "requestAuthorizationCodeGrant", [_dec2, _common.oneFlight], (0, _getOwnPropertyDescriptor.default)(_obj, "requestAuthorizationCodeGrant"), _obj), _obj));
|
|
803
959
|
var _default = exports.default = Authorization;
|
|
804
960
|
//# sourceMappingURL=authorization.js.map
|