@webex/plugin-authorization-browser-first-party 3.6.0-next.4 → 3.6.0-next.6
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/dist/authorization.js +95 -38
- package/dist/authorization.js.map +1 -1
- package/dist/index.js +12 -1
- package/dist/index.js.map +1 -1
- package/package.json +13 -13
- package/src/authorization.js +96 -36
- package/src/index.js +1 -1
- package/test/unit/spec/authorization.js +178 -100
package/dist/authorization.js
CHANGED
|
@@ -5,7 +5,7 @@ var _interopRequireDefault = require("@babel/runtime-corejs2/helpers/interopRequ
|
|
|
5
5
|
_Object$defineProperty(exports, "__esModule", {
|
|
6
6
|
value: true
|
|
7
7
|
});
|
|
8
|
-
exports.default = void 0;
|
|
8
|
+
exports.default = exports.Events = void 0;
|
|
9
9
|
var _apply = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/reflect/apply"));
|
|
10
10
|
var _promise = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/promise"));
|
|
11
11
|
var _assign = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/object/assign"));
|
|
@@ -33,6 +33,16 @@ var lodash = require('lodash');
|
|
|
33
33
|
var OAUTH2_CSRF_TOKEN = 'oauth2-csrf-token';
|
|
34
34
|
var OAUTH2_CODE_VERIFIER = 'oauth2-code-verifier';
|
|
35
35
|
|
|
36
|
+
/**
|
|
37
|
+
* Authorization plugin events
|
|
38
|
+
*/
|
|
39
|
+
var Events = exports.Events = {
|
|
40
|
+
/**
|
|
41
|
+
* QR code login events
|
|
42
|
+
*/
|
|
43
|
+
qRCodeLogin: 'qRCodeLogin'
|
|
44
|
+
};
|
|
45
|
+
|
|
36
46
|
/**
|
|
37
47
|
* Browser support for OAuth2. Automatically parses the URL query for an
|
|
38
48
|
* authorization code
|
|
@@ -76,14 +86,45 @@ var Authorization = _webexCore.WebexPlugin.extend((_dec = (0, _common.whileInFli
|
|
|
76
86
|
},
|
|
77
87
|
namespace: 'Credentials',
|
|
78
88
|
/**
|
|
79
|
-
*
|
|
89
|
+
* EventEmitter for authorization events
|
|
90
|
+
* @instance
|
|
91
|
+
* @memberof AuthorizationBrowserFirstParty
|
|
92
|
+
* @type {EventEmitter}
|
|
93
|
+
* @public
|
|
94
|
+
*/
|
|
95
|
+
eventEmitter: new _events.EventEmitter(),
|
|
96
|
+
/**
|
|
97
|
+
* Stores the timer ID for QR code polling
|
|
80
98
|
* @instance
|
|
81
99
|
* @memberof AuthorizationBrowserFirstParty
|
|
82
100
|
* @type {?number}
|
|
83
101
|
* @private
|
|
84
102
|
*/
|
|
85
|
-
|
|
86
|
-
|
|
103
|
+
pollingTimer: null,
|
|
104
|
+
/**
|
|
105
|
+
* Stores the expiration timer ID for QR code polling
|
|
106
|
+
* @instance
|
|
107
|
+
* @memberof AuthorizationBrowserFirstParty
|
|
108
|
+
* @type {?number}
|
|
109
|
+
* @private
|
|
110
|
+
*/
|
|
111
|
+
pollingExpirationTimer: null,
|
|
112
|
+
/**
|
|
113
|
+
* Monotonically increasing id to identify the current polling request
|
|
114
|
+
* @instance
|
|
115
|
+
* @memberof AuthorizationBrowserFirstParty
|
|
116
|
+
* @type {number}
|
|
117
|
+
* @private
|
|
118
|
+
*/
|
|
119
|
+
pollingId: 0,
|
|
120
|
+
/**
|
|
121
|
+
* Identifier for the current polling request
|
|
122
|
+
* @instance
|
|
123
|
+
* @memberof AuthorizationBrowserFirstParty
|
|
124
|
+
* @type {?number}
|
|
125
|
+
* @private
|
|
126
|
+
*/
|
|
127
|
+
currentPollingId: null,
|
|
87
128
|
/**
|
|
88
129
|
* Initializer
|
|
89
130
|
* @instance
|
|
@@ -249,8 +290,8 @@ var Authorization = _webexCore.WebexPlugin.extend((_dec = (0, _common.whileInFli
|
|
|
249
290
|
*/
|
|
250
291
|
initQRCodeLogin: function initQRCodeLogin() {
|
|
251
292
|
var _this3 = this;
|
|
252
|
-
if (this.
|
|
253
|
-
this.eventEmitter.emit(
|
|
293
|
+
if (this.pollingTimer) {
|
|
294
|
+
this.eventEmitter.emit(Events.qRCodeLogin, {
|
|
254
295
|
eventType: 'getUserCodeFailure',
|
|
255
296
|
data: {
|
|
256
297
|
message: 'There is already a polling request'
|
|
@@ -276,7 +317,7 @@ var Authorization = _webexCore.WebexPlugin.extend((_dec = (0, _common.whileInFli
|
|
|
276
317
|
user_code = _res$body.user_code,
|
|
277
318
|
verification_uri = _res$body.verification_uri,
|
|
278
319
|
verification_uri_complete = _res$body.verification_uri_complete;
|
|
279
|
-
_this3.eventEmitter.emit(
|
|
320
|
+
_this3.eventEmitter.emit(Events.qRCodeLogin, {
|
|
280
321
|
eventType: 'getUserCodeSuccess',
|
|
281
322
|
userData: {
|
|
282
323
|
userCode: user_code,
|
|
@@ -287,7 +328,7 @@ var Authorization = _webexCore.WebexPlugin.extend((_dec = (0, _common.whileInFli
|
|
|
287
328
|
// if device authorization success, then start to poll server to check whether the user has completed authorization
|
|
288
329
|
_this3._startQRCodePolling(res.body);
|
|
289
330
|
}).catch(function (res) {
|
|
290
|
-
_this3.eventEmitter.emit(
|
|
331
|
+
_this3.eventEmitter.emit(Events.qRCodeLogin, {
|
|
291
332
|
eventType: 'getUserCodeFailure',
|
|
292
333
|
data: res.body
|
|
293
334
|
});
|
|
@@ -301,10 +342,11 @@ var Authorization = _webexCore.WebexPlugin.extend((_dec = (0, _common.whileInFli
|
|
|
301
342
|
* @emits #qRCodeLogin
|
|
302
343
|
*/
|
|
303
344
|
_startQRCodePolling: function _startQRCodePolling() {
|
|
304
|
-
var
|
|
345
|
+
var _options$interval,
|
|
346
|
+
_this4 = this;
|
|
305
347
|
var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
306
348
|
if (!options.device_code) {
|
|
307
|
-
this.eventEmitter.emit(
|
|
349
|
+
this.eventEmitter.emit(Events.qRCodeLogin, {
|
|
308
350
|
eventType: 'authorizationFailure',
|
|
309
351
|
data: {
|
|
310
352
|
message: 'A deviceCode is required'
|
|
@@ -312,8 +354,8 @@ var Authorization = _webexCore.WebexPlugin.extend((_dec = (0, _common.whileInFli
|
|
|
312
354
|
});
|
|
313
355
|
return;
|
|
314
356
|
}
|
|
315
|
-
if (this.
|
|
316
|
-
this.eventEmitter.emit(
|
|
357
|
+
if (this.pollingTimer) {
|
|
358
|
+
this.eventEmitter.emit(Events.qRCodeLogin, {
|
|
317
359
|
eventType: 'authorizationFailure',
|
|
318
360
|
data: {
|
|
319
361
|
message: 'There is already a polling request'
|
|
@@ -322,15 +364,21 @@ var Authorization = _webexCore.WebexPlugin.extend((_dec = (0, _common.whileInFli
|
|
|
322
364
|
return;
|
|
323
365
|
}
|
|
324
366
|
var deviceCode = options.device_code,
|
|
325
|
-
_options$interval = options.interval,
|
|
326
|
-
interval = _options$interval === void 0 ? 2 : _options$interval,
|
|
327
367
|
_options$expires_in = options.expires_in,
|
|
328
368
|
expiresIn = _options$expires_in === void 0 ? 300 : _options$expires_in;
|
|
329
|
-
var
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
369
|
+
var interval = (_options$interval = options.interval) !== null && _options$interval !== void 0 ? _options$interval : 2;
|
|
370
|
+
this.pollingExpirationTimer = setTimeout(function () {
|
|
371
|
+
_this4.cancelQRCodePolling(false);
|
|
372
|
+
_this4.eventEmitter.emit(Events.qRCodeLogin, {
|
|
373
|
+
eventType: 'authorizationFailure',
|
|
374
|
+
data: {
|
|
375
|
+
message: 'Authorization timed out'
|
|
376
|
+
}
|
|
377
|
+
});
|
|
378
|
+
}, expiresIn * 1000);
|
|
379
|
+
var polling = function polling() {
|
|
380
|
+
_this4.pollingId += 1;
|
|
381
|
+
_this4.currentPollingId = _this4.pollingId;
|
|
334
382
|
_this4.webex.request({
|
|
335
383
|
method: 'POST',
|
|
336
384
|
service: 'oauth-helper',
|
|
@@ -346,40 +394,45 @@ var Authorization = _webexCore.WebexPlugin.extend((_dec = (0, _common.whileInFli
|
|
|
346
394
|
sendImmediately: true
|
|
347
395
|
}
|
|
348
396
|
}).then(function (res) {
|
|
349
|
-
if
|
|
350
|
-
_this4.
|
|
397
|
+
// if the pollingId has changed, it means that the polling request has been canceled
|
|
398
|
+
if (_this4.currentPollingId !== _this4.pollingId) return;
|
|
399
|
+
_this4.eventEmitter.emit(Events.qRCodeLogin, {
|
|
351
400
|
eventType: 'authorizationSuccess',
|
|
352
401
|
data: res.body
|
|
353
402
|
});
|
|
354
403
|
_this4.cancelQRCodePolling();
|
|
355
404
|
}).catch(function (res) {
|
|
356
|
-
if
|
|
357
|
-
if (
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
});
|
|
364
|
-
_this4.cancelQRCodePolling();
|
|
405
|
+
// if the pollingId has changed, it means that the polling request has been canceled
|
|
406
|
+
if (_this4.currentPollingId !== _this4.pollingId) return;
|
|
407
|
+
|
|
408
|
+
// When server sends 400 status code with message 'slow_down', it means that last request happened too soon.
|
|
409
|
+
// So, skip one interval and then poll again.
|
|
410
|
+
if (res.statusCode === 400 && res.body.message === 'slow_down') {
|
|
411
|
+
schedulePolling(interval * 2);
|
|
365
412
|
return;
|
|
366
413
|
}
|
|
414
|
+
|
|
367
415
|
// if the statusCode is 428 which means that the authorization request is still pending
|
|
368
416
|
// as the end user hasn't yet completed the user-interaction steps. So keep polling.
|
|
369
417
|
if (res.statusCode === 428) {
|
|
370
|
-
_this4.eventEmitter.emit(
|
|
418
|
+
_this4.eventEmitter.emit(Events.qRCodeLogin, {
|
|
371
419
|
eventType: 'authorizationPending',
|
|
372
420
|
data: res.body
|
|
373
421
|
});
|
|
422
|
+
schedulePolling(interval);
|
|
374
423
|
return;
|
|
375
424
|
}
|
|
376
425
|
_this4.cancelQRCodePolling();
|
|
377
|
-
_this4.eventEmitter.emit(
|
|
426
|
+
_this4.eventEmitter.emit(Events.qRCodeLogin, {
|
|
378
427
|
eventType: 'authorizationFailure',
|
|
379
428
|
data: res.body
|
|
380
429
|
});
|
|
381
430
|
});
|
|
382
|
-
}
|
|
431
|
+
};
|
|
432
|
+
var schedulePolling = function schedulePolling(interval) {
|
|
433
|
+
return _this4.pollingTimer = setTimeout(polling, interval * 1000);
|
|
434
|
+
};
|
|
435
|
+
schedulePolling(interval);
|
|
383
436
|
},
|
|
384
437
|
/**
|
|
385
438
|
* cancel polling request
|
|
@@ -388,13 +441,17 @@ var Authorization = _webexCore.WebexPlugin.extend((_dec = (0, _common.whileInFli
|
|
|
388
441
|
* @returns {void}
|
|
389
442
|
*/
|
|
390
443
|
cancelQRCodePolling: function cancelQRCodePolling() {
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
this.eventEmitter.emit(
|
|
444
|
+
var withCancelEvent = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
|
|
445
|
+
if (this.pollingTimer && withCancelEvent) {
|
|
446
|
+
this.eventEmitter.emit(Events.qRCodeLogin, {
|
|
394
447
|
eventType: 'pollingCanceled'
|
|
395
448
|
});
|
|
396
|
-
this.pollingRequest = null;
|
|
397
449
|
}
|
|
450
|
+
this.currentPollingId = null;
|
|
451
|
+
clearTimeout(this.pollingExpirationTimer);
|
|
452
|
+
this.pollingExpirationTimer = null;
|
|
453
|
+
clearTimeout(this.pollingTimer);
|
|
454
|
+
this.pollingTimer = null;
|
|
398
455
|
},
|
|
399
456
|
/**
|
|
400
457
|
* Extracts the orgId from the returned code from idbroker
|
|
@@ -504,7 +561,7 @@ var Authorization = _webexCore.WebexPlugin.extend((_dec = (0, _common.whileInFli
|
|
|
504
561
|
throw new Error("CSRF token ".concat(token, " does not match stored token ").concat(sessionToken));
|
|
505
562
|
}
|
|
506
563
|
},
|
|
507
|
-
version: "3.6.0-next.
|
|
564
|
+
version: "3.6.0-next.6"
|
|
508
565
|
}, ((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)));
|
|
509
566
|
var _default = exports.default = Authorization;
|
|
510
567
|
//# sourceMappingURL=authorization.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_querystring","_interopRequireDefault","require","_url","_events","_common","_webexCore","_lodash","_uuid","_encBase64url","_cryptoJs","_dec","_dec2","_obj","lodash","OAUTH2_CSRF_TOKEN","OAUTH2_CODE_VERIFIER","Authorization","WebexPlugin","extend","whileInFlight","derived","isAuthenticating","deps","fn","isAuthorizing","session","default","type","ready","namespace","pollingRequest","eventEmitter","EventEmitter","initialize","_this","_len","arguments","length","attrs","Array","_key","ret","_apply","prototype","location","url","parse","webex","getWindow","href","_checkForErrors","code","query","state","JSON","base64","decode","codeVerifier","sessionStorage","getItem","removeItem","emailhash","_verifySecurityToken","_cleanUrl","preauthCatalogParams","orgId","_extractOrgIdFromCode","process","nextTick","internal","services","collectPreauthCatalog","catch","_promise","resolve","then","requestAuthorizationCodeGrant","error","logger","warn","initiateLogin","options","undefined","cloneDeep","email","emailHash","CryptoJS","SHA256","toString","csrf_token","_generateSecurityToken","code_challenge","_generateCodeChallenge","code_challenge_method","initiateAuthorizationCodeGrant","info","credentials","buildLoginUrl","_assign","response_type","logout","noRedirect","buildLogoutUrl","_this2","reject","Error","form","grant_type","redirect_uri","config","self_contained_token","code_verifier","request","method","uri","tokenUrl","auth","user","client_id","pass","client_secret","sendImmediately","shouldRefreshAccessToken","res","set","supertoken","body","statusCode","ErrorConstructor","grantErrors","select","_res","initQRCodeLogin","_this3","emit","eventType","data","message","service","resource","scope","_res$body","user_code","verification_uri","verification_uri_complete","userData","userCode","verificationUri","verificationUriComplete","_startQRCodePolling","_this4","device_code","deviceCode","_options$interval","interval","_options$expires_in","expires_in","expiresIn","attempts","maxAttempts","setInterval","currentAttempts","cancelQRCodePolling","clearInterval","split","history","replaceState","_deleteProperty","isEmpty","omit","encode","_stringify","search","querystring","stringify","format","safeCharacterMap","base64url","_safe_map","times","random","join","codeChallenge","setItem","token","uuid","v4","sessionToken","concat","version","_applyDecoratedDescriptor2","_getOwnPropertyDescriptor","oneFlight","_default","exports"],"sources":["authorization.js"],"sourcesContent":["/*!\n * Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.\n */\n\n/* eslint camelcase: [0] */\n\nimport querystring from 'querystring';\nimport url from 'url';\nimport {EventEmitter} from 'events';\n\nimport {base64, oneFlight, whileInFlight} from '@webex/common';\nimport {grantErrors, WebexPlugin} from '@webex/webex-core';\nimport {cloneDeep, isEmpty, omit} from 'lodash';\nimport uuid from 'uuid';\nimport base64url from 'crypto-js/enc-base64url';\nimport CryptoJS from 'crypto-js';\n\n// Necessary to require lodash this way in order to stub\n// methods in the unit test\nconst lodash = require('lodash');\n\nconst OAUTH2_CSRF_TOKEN = 'oauth2-csrf-token';\nconst OAUTH2_CODE_VERIFIER = 'oauth2-code-verifier';\n\n/**\n * Browser support for OAuth2. Automatically parses the URL query for an\n * authorization code\n *\n * Use of this plugin for anything other than the Webex Web Client is strongly\n * discouraged and may be broken at any time\n * @class\n * @name AuthorizationBrowserFirstParty\n * @private\n */\nconst Authorization = WebexPlugin.extend({\n derived: {\n /**\n * Alias of {@link AuthorizationBrowserFirstParty#isAuthorizing}\n * @instance\n * @memberof AuthorizationBrowserFirstParty\n * @type {boolean}\n */\n isAuthenticating: {\n deps: ['isAuthorizing'],\n fn() {\n return this.isAuthorizing;\n },\n },\n },\n\n session: {\n /**\n * Indicates if an Authorization Code exchange is inflight\n * @instance\n * @memberof AuthorizationBrowserFirstParty\n * @type {boolean}\n */\n isAuthorizing: {\n default: false,\n type: 'boolean',\n },\n ready: {\n default: false,\n type: 'boolean',\n },\n },\n\n namespace: 'Credentials',\n\n\n /**\n * Stores the interval ID for QR code polling\n * @instance\n * @memberof AuthorizationBrowserFirstParty\n * @type {?number}\n * @private\n */\n pollingRequest: null,\n\n eventEmitter: new EventEmitter(),\n\n /**\n * Initializer\n * @instance\n * @memberof AuthorizationBrowserFirstParty\n * @private\n * @returns {Authorization}\n */\n // eslint-disable-next-line complexity\n initialize(...attrs) {\n const ret = Reflect.apply(WebexPlugin.prototype.initialize, this, attrs);\n const location = url.parse(this.webex.getWindow().location.href, true);\n\n this._checkForErrors(location);\n\n const {code} = location.query;\n\n if (!code) {\n this.ready = true;\n\n return ret;\n }\n\n if (location.query.state) {\n location.query.state = JSON.parse(base64.decode(location.query.state));\n } else {\n location.query.state = {};\n }\n\n const codeVerifier = this.webex.getWindow().sessionStorage.getItem(OAUTH2_CODE_VERIFIER);\n\n this.webex.getWindow().sessionStorage.removeItem(OAUTH2_CODE_VERIFIER);\n\n const {emailhash} = location.query.state;\n\n this._verifySecurityToken(location.query);\n this._cleanUrl(location);\n\n let preauthCatalogParams;\n\n const orgId = this._extractOrgIdFromCode(code);\n\n if (emailhash) {\n preauthCatalogParams = {emailhash};\n } else if (orgId) {\n preauthCatalogParams = {orgId};\n }\n\n // Wait until nextTick in case `credentials` hasn't initialized yet\n process.nextTick(() => {\n this.webex.internal.services\n .collectPreauthCatalog(preauthCatalogParams)\n .catch(() => Promise.resolve())\n .then(() => this.requestAuthorizationCodeGrant({code, codeVerifier}))\n .catch((error) => {\n this.logger.warn('authorization: failed initial authorization code grant request', error);\n })\n .then(() => {\n this.ready = true;\n });\n });\n\n return ret;\n },\n\n /**\n * Kicks off an oauth flow\n * @instance\n * @memberof AuthorizationBrowserFirstParty\n * @param {Object} options\n * @returns {Promise}\n */\n initiateLogin(options = {}) {\n options = cloneDeep(options);\n if (options.email) {\n options.emailHash = CryptoJS.SHA256(options.email).toString();\n }\n delete options.email;\n options.state = options.state || {};\n options.state.csrf_token = this._generateSecurityToken();\n // catalog uses emailhash and redirectCI uses emailHash\n options.state.emailhash = options.emailHash;\n\n options.code_challenge = this._generateCodeChallenge();\n options.code_challenge_method = 'S256';\n\n return this.initiateAuthorizationCodeGrant(options);\n },\n\n @whileInFlight('isAuthorizing')\n /**\n * Kicks off the Implicit Code grant flow. Typically called via\n * {@link AuthorizationBrowserFirstParty#initiateLogin}\n * @instance\n * @memberof AuthorizationBrowserFirstParty\n * @param {Object} options\n * @returns {Promise}\n */\n initiateAuthorizationCodeGrant(options) {\n this.logger.info('authorization: initiating authorization code grant flow');\n this.webex.getWindow().location = this.webex.credentials.buildLoginUrl(\n Object.assign({response_type: 'code'}, options)\n );\n\n return Promise.resolve();\n },\n\n /**\n * Called by {@link WebexCore#logout()}. Redirects to the logout page\n * @instance\n * @memberof AuthorizationBrowserFirstParty\n * @param {Object} options\n * @param {boolean} options.noRedirect if true, does not redirect\n * @returns {Promise}\n */\n logout(options = {}) {\n if (!options.noRedirect) {\n this.webex.getWindow().location = this.webex.credentials.buildLogoutUrl(options);\n }\n },\n\n @whileInFlight('isAuthorizing')\n @oneFlight\n /**\n * Exchanges an authorization code for an access token\n * @instance\n * @memberof AuthorizationBrowserFirstParty\n * @param {Object} options\n * @param {Object} options.code\n * @returns {Promise}\n */\n requestAuthorizationCodeGrant(options = {}) {\n this.logger.info('credentials: requesting authorization code grant');\n\n if (!options.code) {\n return Promise.reject(new Error('`options.code` is required'));\n }\n\n const form = {\n grant_type: 'authorization_code',\n redirect_uri: this.config.redirect_uri,\n code: options.code,\n self_contained_token: true,\n };\n\n if (options.codeVerifier) {\n form.code_verifier = options.codeVerifier;\n }\n\n return this.webex\n .request({\n method: 'POST',\n uri: this.config.tokenUrl,\n form,\n auth: {\n user: this.config.client_id,\n pass: this.config.client_secret,\n sendImmediately: true,\n },\n shouldRefreshAccessToken: false,\n })\n .then((res) => {\n this.webex.credentials.set({supertoken: res.body});\n })\n .catch((res) => {\n if (res.statusCode !== 400) {\n return Promise.reject(res);\n }\n\n const ErrorConstructor = grantErrors.select(res.body.error);\n\n return Promise.reject(new ErrorConstructor(res._res || res));\n });\n },\n\n /**\n * Get an OAuth Login URL for QRCode. Generate QR code based on the returned URL.\n * @instance\n * @memberof AuthorizationBrowserFirstParty\n * @emits #qRCodeLogin\n */\n initQRCodeLogin() {\n if (this.pollingRequest) {\n this.eventEmitter.emit('qRCodeLogin', {\n eventType: 'getUserCodeFailure',\n data: {message: 'There is already a polling request'},\n });\n return;\n }\n\n this.webex\n .request({\n method: 'POST',\n service: 'oauth-helper',\n resource: '/actions/device/authorize',\n form: {\n client_id: this.config.client_id,\n scope: this.config.scope,\n },\n auth: {\n user: this.config.client_id,\n pass: this.config.client_secret,\n sendImmediately: true,\n },\n })\n .then((res) => {\n const {user_code, verification_uri, verification_uri_complete} = res.body;\n this.eventEmitter.emit('qRCodeLogin', {\n eventType: 'getUserCodeSuccess',\n userData: {\n userCode: user_code,\n verificationUri: verification_uri,\n verificationUriComplete: verification_uri_complete,\n }\n });\n // if device authorization success, then start to poll server to check whether the user has completed authorization\n this._startQRCodePolling(res.body);\n })\n .catch((res) => {\n this.eventEmitter.emit('qRCodeLogin', {\n eventType: 'getUserCodeFailure',\n data: res.body,\n });\n });\n },\n\n /**\n * Polling the server to check whether the user has completed authorization\n * @instance\n * @memberof AuthorizationBrowserFirstParty\n * @param {Object} options\n * @emits #qRCodeLogin\n */\n _startQRCodePolling(options = {}) {\n if (!options.device_code) {\n this.eventEmitter.emit('qRCodeLogin', {\n eventType: 'authorizationFailure',\n data: {message: 'A deviceCode is required'},\n });\n return;\n }\n\n if (this.pollingRequest) {\n this.eventEmitter.emit('qRCodeLogin', {\n eventType: 'authorizationFailure',\n data: {message: 'There is already a polling request'},\n });\n return;\n }\n\n const {device_code: deviceCode, interval = 2, expires_in: expiresIn = 300} = options;\n\n let attempts = 0;\n const maxAttempts = expiresIn / interval;\n\n this.pollingRequest = setInterval(() => {\n attempts += 1;\n\n const currentAttempts = attempts;\n this.webex\n .request({\n method: 'POST',\n service: 'oauth-helper',\n resource: '/actions/device/token',\n form: {\n grant_type: 'urn:ietf:params:oauth:grant-type:device_code',\n device_code: deviceCode,\n client_id: this.config.client_id,\n },\n auth: {\n user: this.config.client_id,\n pass: this.config.client_secret,\n sendImmediately: true,\n },\n })\n .then((res) => {\n if (this.pollingRequest === null) return;\n\n this.eventEmitter.emit('qRCodeLogin', {\n eventType: 'authorizationSuccess',\n data: res.body,\n });\n this.cancelQRCodePolling();\n })\n .catch((res) => {\n if (this.pollingRequest === null) return;\n\n if (currentAttempts >= maxAttempts) {\n this.eventEmitter.emit('qRCodeLogin', {\n eventType: 'authorizationFailure',\n data: {message: 'Authorization timed out'}\n });\n this.cancelQRCodePolling();\n return;\n }\n // if the statusCode is 428 which means that the authorization request is still pending\n // as the end user hasn't yet completed the user-interaction steps. So keep polling.\n if (res.statusCode === 428) {\n this.eventEmitter.emit('qRCodeLogin', {\n eventType: 'authorizationPending',\n data: res.body\n });\n return;\n }\n\n this.cancelQRCodePolling();\n\n this.eventEmitter.emit('qRCodeLogin', {\n eventType: 'authorizationFailure',\n data: res.body\n });\n });\n }, interval * 1000);\n },\n\n /**\n * cancel polling request\n * @instance\n * @memberof AuthorizationBrowserFirstParty\n * @returns {void}\n */\n cancelQRCodePolling() {\n if (this.pollingRequest) {\n clearInterval(this.pollingRequest);\n this.eventEmitter.emit('qRCodeLogin', {\n eventType: 'pollingCanceled',\n });\n this.pollingRequest = null;\n }\n },\n\n /**\n * Extracts the orgId from the returned code from idbroker\n * Description of how to parse the code can be found here:\n * https://wiki.cisco.com/display/IDENTITY/Federated+Token+Validation\n * @instance\n * @memberof AuthorizationBrowserFirstParty\n * @param {String} code\n * @private\n * @returns {String}\n */\n _extractOrgIdFromCode(code) {\n return code?.split('_')[2] || undefined;\n },\n\n /**\n * Checks if the result of the login redirect contains an error string\n * @instance\n * @memberof AuthorizationBrowserFirstParty\n * @param {Object} location\n * @private\n * @returns {Promise}\n */\n _checkForErrors(location) {\n const {query} = location;\n\n if (query && query.error) {\n const ErrorConstructor = grantErrors.select(query.error);\n\n throw new ErrorConstructor(query);\n }\n },\n\n /**\n * Removes no-longer needed values from the url (access token, csrf token, etc)\n * @instance\n * @memberof AuthorizationBrowserFirstParty\n * @param {Object} location\n * @private\n * @returns {Promise}\n */\n _cleanUrl(location) {\n location = cloneDeep(location);\n if (this.webex.getWindow().history && this.webex.getWindow().history.replaceState) {\n Reflect.deleteProperty(location.query, 'code');\n if (isEmpty(omit(location.query.state, 'csrf_token'))) {\n Reflect.deleteProperty(location.query, 'state');\n } else {\n location.query.state = base64.encode(\n JSON.stringify(omit(location.query.state, 'csrf_token'))\n );\n }\n location.search = querystring.stringify(location.query);\n Reflect.deleteProperty(location, 'query');\n this.webex.getWindow().history.replaceState({}, null, url.format(location));\n }\n },\n\n /**\n * Generates PKCE code verifier and code challenge and sets the the code verifier in sessionStorage\n * @instance\n * @memberof AuthorizationBrowserFirstParty\n * @private\n * @returns {string}\n */\n _generateCodeChallenge() {\n this.logger.info('authorization: generating PKCE code challenge');\n\n // eslint-disable-next-line no-underscore-dangle\n const safeCharacterMap = base64url._safe_map;\n\n const codeVerifier = lodash\n .times(128, () => safeCharacterMap[lodash.random(0, safeCharacterMap.length - 1)])\n .join('');\n\n const codeChallenge = CryptoJS.SHA256(codeVerifier).toString(base64url);\n\n this.webex.getWindow().sessionStorage.setItem(OAUTH2_CODE_VERIFIER, codeVerifier);\n\n return codeChallenge;\n },\n\n /**\n * Generates a CSRF token and sticks in in sessionStorage\n * @instance\n * @memberof AuthorizationBrowserFirstParty\n * @private\n * @returns {Promise}\n */\n _generateSecurityToken() {\n this.logger.info('authorization: generating csrf token');\n\n const token = uuid.v4();\n\n this.webex.getWindow().sessionStorage.setItem('oauth2-csrf-token', token);\n\n return token;\n },\n\n /**\n * Checks if the CSRF token in sessionStorage is the same as the one returned\n * in the url.\n * @instance\n * @memberof AuthorizationBrowserFirstParty\n * @param {Object} query\n * @private\n * @returns {Promise}\n */\n _verifySecurityToken(query) {\n const sessionToken = this.webex.getWindow().sessionStorage.getItem(OAUTH2_CSRF_TOKEN);\n\n this.webex.getWindow().sessionStorage.removeItem(OAUTH2_CSRF_TOKEN);\n if (!sessionToken) {\n return;\n }\n\n if (!query.state) {\n throw new Error(`Expected CSRF token ${sessionToken}, but not found in redirect query`);\n }\n\n if (!query.state.csrf_token) {\n throw new Error(`Expected CSRF token ${sessionToken}, but not found in redirect query`);\n }\n\n const token = query.state.csrf_token;\n\n if (token !== sessionToken) {\n throw new Error(`CSRF token ${token} does not match stored token ${sessionToken}`);\n }\n },\n});\n\nexport default Authorization;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"names":["_querystring","_interopRequireDefault","require","_url","_events","_common","_webexCore","_lodash","_uuid","_encBase64url","_cryptoJs","_dec","_dec2","_obj","lodash","OAUTH2_CSRF_TOKEN","OAUTH2_CODE_VERIFIER","Events","exports","qRCodeLogin","Authorization","WebexPlugin","extend","whileInFlight","derived","isAuthenticating","deps","fn","isAuthorizing","session","default","type","ready","namespace","eventEmitter","EventEmitter","pollingTimer","pollingExpirationTimer","pollingId","currentPollingId","initialize","_this","_len","arguments","length","attrs","Array","_key","ret","_apply","prototype","location","url","parse","webex","getWindow","href","_checkForErrors","code","query","state","JSON","base64","decode","codeVerifier","sessionStorage","getItem","removeItem","emailhash","_verifySecurityToken","_cleanUrl","preauthCatalogParams","orgId","_extractOrgIdFromCode","process","nextTick","internal","services","collectPreauthCatalog","catch","_promise","resolve","then","requestAuthorizationCodeGrant","error","logger","warn","initiateLogin","options","undefined","cloneDeep","email","emailHash","CryptoJS","SHA256","toString","csrf_token","_generateSecurityToken","code_challenge","_generateCodeChallenge","code_challenge_method","initiateAuthorizationCodeGrant","info","credentials","buildLoginUrl","_assign","response_type","logout","noRedirect","buildLogoutUrl","_this2","reject","Error","form","grant_type","redirect_uri","config","self_contained_token","code_verifier","request","method","uri","tokenUrl","auth","user","client_id","pass","client_secret","sendImmediately","shouldRefreshAccessToken","res","set","supertoken","body","statusCode","ErrorConstructor","grantErrors","select","_res","initQRCodeLogin","_this3","emit","eventType","data","message","service","resource","scope","_res$body","user_code","verification_uri","verification_uri_complete","userData","userCode","verificationUri","verificationUriComplete","_startQRCodePolling","_options$interval","_this4","device_code","deviceCode","_options$expires_in","expires_in","expiresIn","interval","setTimeout","cancelQRCodePolling","polling","schedulePolling","withCancelEvent","clearTimeout","split","history","replaceState","_deleteProperty","isEmpty","omit","encode","_stringify","search","querystring","stringify","format","safeCharacterMap","base64url","_safe_map","times","random","join","codeChallenge","setItem","token","uuid","v4","sessionToken","concat","version","_applyDecoratedDescriptor2","_getOwnPropertyDescriptor","oneFlight","_default"],"sources":["authorization.js"],"sourcesContent":["/*!\n * Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.\n */\n\n/* eslint camelcase: [0] */\n\nimport querystring from 'querystring';\nimport url from 'url';\nimport {EventEmitter} from 'events';\n\nimport {base64, oneFlight, whileInFlight} from '@webex/common';\nimport {grantErrors, WebexPlugin} from '@webex/webex-core';\nimport {cloneDeep, isEmpty, omit} from 'lodash';\nimport uuid from 'uuid';\nimport base64url from 'crypto-js/enc-base64url';\nimport CryptoJS from 'crypto-js';\n\n// Necessary to require lodash this way in order to stub\n// methods in the unit test\nconst lodash = require('lodash');\n\nconst OAUTH2_CSRF_TOKEN = 'oauth2-csrf-token';\nconst OAUTH2_CODE_VERIFIER = 'oauth2-code-verifier';\n\n/**\n * Authorization plugin events\n */\nexport const Events = {\n /**\n * QR code login events\n */\n qRCodeLogin: 'qRCodeLogin',\n};\n\n/**\n * Browser support for OAuth2. Automatically parses the URL query for an\n * authorization code\n *\n * Use of this plugin for anything other than the Webex Web Client is strongly\n * discouraged and may be broken at any time\n * @class\n * @name AuthorizationBrowserFirstParty\n * @private\n */\nconst Authorization = WebexPlugin.extend({\n derived: {\n /**\n * Alias of {@link AuthorizationBrowserFirstParty#isAuthorizing}\n * @instance\n * @memberof AuthorizationBrowserFirstParty\n * @type {boolean}\n */\n isAuthenticating: {\n deps: ['isAuthorizing'],\n fn() {\n return this.isAuthorizing;\n },\n },\n },\n\n session: {\n /**\n * Indicates if an Authorization Code exchange is inflight\n * @instance\n * @memberof AuthorizationBrowserFirstParty\n * @type {boolean}\n */\n isAuthorizing: {\n default: false,\n type: 'boolean',\n },\n ready: {\n default: false,\n type: 'boolean',\n },\n },\n\n namespace: 'Credentials',\n\n /**\n * EventEmitter for authorization events\n * @instance\n * @memberof AuthorizationBrowserFirstParty\n * @type {EventEmitter}\n * @public\n */\n eventEmitter: new EventEmitter(),\n\n /**\n * Stores the timer ID for QR code polling\n * @instance\n * @memberof AuthorizationBrowserFirstParty\n * @type {?number}\n * @private\n */\n pollingTimer: null,\n /**\n * Stores the expiration timer ID for QR code polling\n * @instance\n * @memberof AuthorizationBrowserFirstParty\n * @type {?number}\n * @private\n */\n pollingExpirationTimer: null,\n\n /**\n * Monotonically increasing id to identify the current polling request\n * @instance\n * @memberof AuthorizationBrowserFirstParty\n * @type {number}\n * @private\n */\n pollingId: 0,\n\n /**\n * Identifier for the current polling request\n * @instance\n * @memberof AuthorizationBrowserFirstParty\n * @type {?number}\n * @private\n */\n currentPollingId: null,\n\n /**\n * Initializer\n * @instance\n * @memberof AuthorizationBrowserFirstParty\n * @private\n * @returns {Authorization}\n */\n // eslint-disable-next-line complexity\n initialize(...attrs) {\n const ret = Reflect.apply(WebexPlugin.prototype.initialize, this, attrs);\n const location = url.parse(this.webex.getWindow().location.href, true);\n\n this._checkForErrors(location);\n\n const {code} = location.query;\n\n if (!code) {\n this.ready = true;\n\n return ret;\n }\n\n if (location.query.state) {\n location.query.state = JSON.parse(base64.decode(location.query.state));\n } else {\n location.query.state = {};\n }\n\n const codeVerifier = this.webex.getWindow().sessionStorage.getItem(OAUTH2_CODE_VERIFIER);\n\n this.webex.getWindow().sessionStorage.removeItem(OAUTH2_CODE_VERIFIER);\n\n const {emailhash} = location.query.state;\n\n this._verifySecurityToken(location.query);\n this._cleanUrl(location);\n\n let preauthCatalogParams;\n\n const orgId = this._extractOrgIdFromCode(code);\n\n if (emailhash) {\n preauthCatalogParams = {emailhash};\n } else if (orgId) {\n preauthCatalogParams = {orgId};\n }\n\n // Wait until nextTick in case `credentials` hasn't initialized yet\n process.nextTick(() => {\n this.webex.internal.services\n .collectPreauthCatalog(preauthCatalogParams)\n .catch(() => Promise.resolve())\n .then(() => this.requestAuthorizationCodeGrant({code, codeVerifier}))\n .catch((error) => {\n this.logger.warn('authorization: failed initial authorization code grant request', error);\n })\n .then(() => {\n this.ready = true;\n });\n });\n\n return ret;\n },\n\n /**\n * Kicks off an oauth flow\n * @instance\n * @memberof AuthorizationBrowserFirstParty\n * @param {Object} options\n * @returns {Promise}\n */\n initiateLogin(options = {}) {\n options = cloneDeep(options);\n if (options.email) {\n options.emailHash = CryptoJS.SHA256(options.email).toString();\n }\n delete options.email;\n options.state = options.state || {};\n options.state.csrf_token = this._generateSecurityToken();\n // catalog uses emailhash and redirectCI uses emailHash\n options.state.emailhash = options.emailHash;\n\n options.code_challenge = this._generateCodeChallenge();\n options.code_challenge_method = 'S256';\n\n return this.initiateAuthorizationCodeGrant(options);\n },\n\n @whileInFlight('isAuthorizing')\n /**\n * Kicks off the Implicit Code grant flow. Typically called via\n * {@link AuthorizationBrowserFirstParty#initiateLogin}\n * @instance\n * @memberof AuthorizationBrowserFirstParty\n * @param {Object} options\n * @returns {Promise}\n */\n initiateAuthorizationCodeGrant(options) {\n this.logger.info('authorization: initiating authorization code grant flow');\n this.webex.getWindow().location = this.webex.credentials.buildLoginUrl(\n Object.assign({response_type: 'code'}, options)\n );\n\n return Promise.resolve();\n },\n\n /**\n * Called by {@link WebexCore#logout()}. Redirects to the logout page\n * @instance\n * @memberof AuthorizationBrowserFirstParty\n * @param {Object} options\n * @param {boolean} options.noRedirect if true, does not redirect\n * @returns {Promise}\n */\n logout(options = {}) {\n if (!options.noRedirect) {\n this.webex.getWindow().location = this.webex.credentials.buildLogoutUrl(options);\n }\n },\n\n @whileInFlight('isAuthorizing')\n @oneFlight\n /**\n * Exchanges an authorization code for an access token\n * @instance\n * @memberof AuthorizationBrowserFirstParty\n * @param {Object} options\n * @param {Object} options.code\n * @returns {Promise}\n */\n requestAuthorizationCodeGrant(options = {}) {\n this.logger.info('credentials: requesting authorization code grant');\n\n if (!options.code) {\n return Promise.reject(new Error('`options.code` is required'));\n }\n\n const form = {\n grant_type: 'authorization_code',\n redirect_uri: this.config.redirect_uri,\n code: options.code,\n self_contained_token: true,\n };\n\n if (options.codeVerifier) {\n form.code_verifier = options.codeVerifier;\n }\n\n return this.webex\n .request({\n method: 'POST',\n uri: this.config.tokenUrl,\n form,\n auth: {\n user: this.config.client_id,\n pass: this.config.client_secret,\n sendImmediately: true,\n },\n shouldRefreshAccessToken: false,\n })\n .then((res) => {\n this.webex.credentials.set({supertoken: res.body});\n })\n .catch((res) => {\n if (res.statusCode !== 400) {\n return Promise.reject(res);\n }\n\n const ErrorConstructor = grantErrors.select(res.body.error);\n\n return Promise.reject(new ErrorConstructor(res._res || res));\n });\n },\n\n /**\n * Get an OAuth Login URL for QRCode. Generate QR code based on the returned URL.\n * @instance\n * @memberof AuthorizationBrowserFirstParty\n * @emits #qRCodeLogin\n */\n initQRCodeLogin() {\n if (this.pollingTimer) {\n this.eventEmitter.emit(Events.qRCodeLogin, {\n eventType: 'getUserCodeFailure',\n data: {message: 'There is already a polling request'},\n });\n return;\n }\n\n this.webex\n .request({\n method: 'POST',\n service: 'oauth-helper',\n resource: '/actions/device/authorize',\n form: {\n client_id: this.config.client_id,\n scope: this.config.scope,\n },\n auth: {\n user: this.config.client_id,\n pass: this.config.client_secret,\n sendImmediately: true,\n },\n })\n .then((res) => {\n const {user_code, verification_uri, verification_uri_complete} = res.body;\n this.eventEmitter.emit(Events.qRCodeLogin, {\n eventType: 'getUserCodeSuccess',\n userData: {\n userCode: user_code,\n verificationUri: verification_uri,\n verificationUriComplete: verification_uri_complete,\n },\n });\n // if device authorization success, then start to poll server to check whether the user has completed authorization\n this._startQRCodePolling(res.body);\n })\n .catch((res) => {\n this.eventEmitter.emit(Events.qRCodeLogin, {\n eventType: 'getUserCodeFailure',\n data: res.body,\n });\n });\n },\n\n /**\n * Polling the server to check whether the user has completed authorization\n * @instance\n * @memberof AuthorizationBrowserFirstParty\n * @param {Object} options\n * @emits #qRCodeLogin\n */\n _startQRCodePolling(options = {}) {\n if (!options.device_code) {\n this.eventEmitter.emit(Events.qRCodeLogin, {\n eventType: 'authorizationFailure',\n data: {message: 'A deviceCode is required'},\n });\n return;\n }\n\n if (this.pollingTimer) {\n this.eventEmitter.emit(Events.qRCodeLogin, {\n eventType: 'authorizationFailure',\n data: {message: 'There is already a polling request'},\n });\n return;\n }\n\n const {device_code: deviceCode, expires_in: expiresIn = 300} = options;\n let interval = options.interval ?? 2;\n\n this.pollingExpirationTimer = setTimeout(() => {\n this.cancelQRCodePolling(false);\n this.eventEmitter.emit(Events.qRCodeLogin, {\n eventType: 'authorizationFailure',\n data: {message: 'Authorization timed out'},\n });\n }, expiresIn * 1000);\n\n const polling = () => {\n this.pollingId += 1;\n this.currentPollingId = this.pollingId;\n\n this.webex\n .request({\n method: 'POST',\n service: 'oauth-helper',\n resource: '/actions/device/token',\n form: {\n grant_type: 'urn:ietf:params:oauth:grant-type:device_code',\n device_code: deviceCode,\n client_id: this.config.client_id,\n },\n auth: {\n user: this.config.client_id,\n pass: this.config.client_secret,\n sendImmediately: true,\n },\n })\n .then((res) => {\n // if the pollingId has changed, it means that the polling request has been canceled\n if (this.currentPollingId !== this.pollingId) return;\n\n this.eventEmitter.emit(Events.qRCodeLogin, {\n eventType: 'authorizationSuccess',\n data: res.body,\n });\n this.cancelQRCodePolling();\n })\n .catch((res) => {\n // if the pollingId has changed, it means that the polling request has been canceled\n if (this.currentPollingId !== this.pollingId) return;\n\n // When server sends 400 status code with message 'slow_down', it means that last request happened too soon.\n // So, skip one interval and then poll again.\n if (res.statusCode === 400 && res.body.message === 'slow_down') {\n schedulePolling(interval * 2);\n return;\n }\n\n // if the statusCode is 428 which means that the authorization request is still pending\n // as the end user hasn't yet completed the user-interaction steps. So keep polling.\n if (res.statusCode === 428) {\n this.eventEmitter.emit(Events.qRCodeLogin, {\n eventType: 'authorizationPending',\n data: res.body,\n });\n schedulePolling(interval);\n return;\n }\n\n this.cancelQRCodePolling();\n\n this.eventEmitter.emit(Events.qRCodeLogin, {\n eventType: 'authorizationFailure',\n data: res.body,\n });\n });\n };\n\n const schedulePolling = (interval) =>\n (this.pollingTimer = setTimeout(polling, interval * 1000));\n\n schedulePolling(interval);\n },\n\n /**\n * cancel polling request\n * @instance\n * @memberof AuthorizationBrowserFirstParty\n * @returns {void}\n */\n cancelQRCodePolling(withCancelEvent = true) {\n if (this.pollingTimer && withCancelEvent) {\n this.eventEmitter.emit(Events.qRCodeLogin, {\n eventType: 'pollingCanceled',\n });\n }\n\n this.currentPollingId = null;\n\n clearTimeout(this.pollingExpirationTimer);\n this.pollingExpirationTimer = null;\n clearTimeout(this.pollingTimer);\n this.pollingTimer = null;\n },\n\n /**\n * Extracts the orgId from the returned code from idbroker\n * Description of how to parse the code can be found here:\n * https://wiki.cisco.com/display/IDENTITY/Federated+Token+Validation\n * @instance\n * @memberof AuthorizationBrowserFirstParty\n * @param {String} code\n * @private\n * @returns {String}\n */\n _extractOrgIdFromCode(code) {\n return code?.split('_')[2] || undefined;\n },\n\n /**\n * Checks if the result of the login redirect contains an error string\n * @instance\n * @memberof AuthorizationBrowserFirstParty\n * @param {Object} location\n * @private\n * @returns {Promise}\n */\n _checkForErrors(location) {\n const {query} = location;\n\n if (query && query.error) {\n const ErrorConstructor = grantErrors.select(query.error);\n\n throw new ErrorConstructor(query);\n }\n },\n\n /**\n * Removes no-longer needed values from the url (access token, csrf token, etc)\n * @instance\n * @memberof AuthorizationBrowserFirstParty\n * @param {Object} location\n * @private\n * @returns {Promise}\n */\n _cleanUrl(location) {\n location = cloneDeep(location);\n if (this.webex.getWindow().history && this.webex.getWindow().history.replaceState) {\n Reflect.deleteProperty(location.query, 'code');\n if (isEmpty(omit(location.query.state, 'csrf_token'))) {\n Reflect.deleteProperty(location.query, 'state');\n } else {\n location.query.state = base64.encode(\n JSON.stringify(omit(location.query.state, 'csrf_token'))\n );\n }\n location.search = querystring.stringify(location.query);\n Reflect.deleteProperty(location, 'query');\n this.webex.getWindow().history.replaceState({}, null, url.format(location));\n }\n },\n\n /**\n * Generates PKCE code verifier and code challenge and sets the the code verifier in sessionStorage\n * @instance\n * @memberof AuthorizationBrowserFirstParty\n * @private\n * @returns {string}\n */\n _generateCodeChallenge() {\n this.logger.info('authorization: generating PKCE code challenge');\n\n // eslint-disable-next-line no-underscore-dangle\n const safeCharacterMap = base64url._safe_map;\n\n const codeVerifier = lodash\n .times(128, () => safeCharacterMap[lodash.random(0, safeCharacterMap.length - 1)])\n .join('');\n\n const codeChallenge = CryptoJS.SHA256(codeVerifier).toString(base64url);\n\n this.webex.getWindow().sessionStorage.setItem(OAUTH2_CODE_VERIFIER, codeVerifier);\n\n return codeChallenge;\n },\n\n /**\n * Generates a CSRF token and sticks in in sessionStorage\n * @instance\n * @memberof AuthorizationBrowserFirstParty\n * @private\n * @returns {Promise}\n */\n _generateSecurityToken() {\n this.logger.info('authorization: generating csrf token');\n\n const token = uuid.v4();\n\n this.webex.getWindow().sessionStorage.setItem('oauth2-csrf-token', token);\n\n return token;\n },\n\n /**\n * Checks if the CSRF token in sessionStorage is the same as the one returned\n * in the url.\n * @instance\n * @memberof AuthorizationBrowserFirstParty\n * @param {Object} query\n * @private\n * @returns {Promise}\n */\n _verifySecurityToken(query) {\n const sessionToken = this.webex.getWindow().sessionStorage.getItem(OAUTH2_CSRF_TOKEN);\n\n this.webex.getWindow().sessionStorage.removeItem(OAUTH2_CSRF_TOKEN);\n if (!sessionToken) {\n return;\n }\n\n if (!query.state) {\n throw new Error(`Expected CSRF token ${sessionToken}, but not found in redirect query`);\n }\n\n if (!query.state.csrf_token) {\n throw new Error(`Expected CSRF token ${sessionToken}, but not found in redirect query`);\n }\n\n const token = query.state.csrf_token;\n\n if (token !== sessionToken) {\n throw new Error(`CSRF token ${token} does not match stored token ${sessionToken}`);\n }\n },\n});\n\nexport default Authorization;\n"],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -1,10 +1,19 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
+
var _typeof = require("@babel/runtime-corejs2/helpers/typeof");
|
|
4
|
+
var _WeakMap = require("@babel/runtime-corejs2/core-js/weak-map");
|
|
3
5
|
var _Object$defineProperty = require("@babel/runtime-corejs2/core-js/object/define-property");
|
|
6
|
+
var _Object$getOwnPropertyDescriptor = require("@babel/runtime-corejs2/core-js/object/get-own-property-descriptor");
|
|
4
7
|
var _interopRequireDefault = require("@babel/runtime-corejs2/helpers/interopRequireDefault");
|
|
5
8
|
_Object$defineProperty(exports, "__esModule", {
|
|
6
9
|
value: true
|
|
7
10
|
});
|
|
11
|
+
_Object$defineProperty(exports, "Events", {
|
|
12
|
+
enumerable: true,
|
|
13
|
+
get: function get() {
|
|
14
|
+
return _authorization.Events;
|
|
15
|
+
}
|
|
16
|
+
});
|
|
8
17
|
_Object$defineProperty(exports, "config", {
|
|
9
18
|
enumerable: true,
|
|
10
19
|
get: function get() {
|
|
@@ -18,8 +27,10 @@ _Object$defineProperty(exports, "default", {
|
|
|
18
27
|
}
|
|
19
28
|
});
|
|
20
29
|
var _webexCore = require("@webex/webex-core");
|
|
21
|
-
var _authorization =
|
|
30
|
+
var _authorization = _interopRequireWildcard(require("./authorization"));
|
|
22
31
|
var _config = _interopRequireDefault(require("./config"));
|
|
32
|
+
function _getRequireWildcardCache(e) { if ("function" != typeof _WeakMap) return null; var r = new _WeakMap(), t = new _WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); }
|
|
33
|
+
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof(e) && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = _Object$defineProperty && _Object$getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? _Object$getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? _Object$defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
23
34
|
/*!
|
|
24
35
|
* Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.
|
|
25
36
|
*/
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_webexCore","require","_authorization","
|
|
1
|
+
{"version":3,"names":["_webexCore","require","_authorization","_interopRequireWildcard","_config","_interopRequireDefault","_getRequireWildcardCache","e","_WeakMap","r","t","__esModule","_typeof","default","has","get","n","__proto__","a","_Object$defineProperty","_Object$getOwnPropertyDescriptor","u","Object","prototype","hasOwnProperty","call","i","set","proxies","registerPlugin","Authorization","config"],"sources":["index.js"],"sourcesContent":["/*!\n * Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.\n */\n\nimport {registerPlugin} from '@webex/webex-core';\n\nimport Authorization from './authorization';\nimport config from './config';\n\nconst proxies = ['isAuthorizing', 'isAuthenticating'];\n\nregisterPlugin('authorization', Authorization, {\n config,\n proxies,\n});\n\nexport {default, Events} from './authorization';\nexport {default as config} from './config';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAIA,IAAAA,UAAA,GAAAC,OAAA;AAEA,IAAAC,cAAA,GAAAC,uBAAA,CAAAF,OAAA;AACA,IAAAG,OAAA,GAAAC,sBAAA,CAAAJ,OAAA;AAA8B,SAAAK,yBAAAC,CAAA,6BAAAC,QAAA,mBAAAC,CAAA,OAAAD,QAAA,IAAAE,CAAA,OAAAF,QAAA,YAAAF,wBAAA,YAAAA,yBAAAC,CAAA,WAAAA,CAAA,GAAAG,CAAA,GAAAD,CAAA,KAAAF,CAAA;AAAA,SAAAJ,wBAAAI,CAAA,EAAAE,CAAA,SAAAA,CAAA,IAAAF,CAAA,IAAAA,CAAA,CAAAI,UAAA,SAAAJ,CAAA,eAAAA,CAAA,gBAAAK,OAAA,CAAAL,CAAA,0BAAAA,CAAA,WAAAM,OAAA,EAAAN,CAAA,QAAAG,CAAA,GAAAJ,wBAAA,CAAAG,CAAA,OAAAC,CAAA,IAAAA,CAAA,CAAAI,GAAA,CAAAP,CAAA,UAAAG,CAAA,CAAAK,GAAA,CAAAR,CAAA,OAAAS,CAAA,KAAAC,SAAA,UAAAC,CAAA,GAAAC,sBAAA,IAAAC,gCAAA,WAAAC,CAAA,IAAAd,CAAA,oBAAAc,CAAA,IAAAC,MAAA,CAAAC,SAAA,CAAAC,cAAA,CAAAC,IAAA,CAAAlB,CAAA,EAAAc,CAAA,SAAAK,CAAA,GAAAR,CAAA,GAAAE,gCAAA,CAAAb,CAAA,EAAAc,CAAA,UAAAK,CAAA,KAAAA,CAAA,CAAAX,GAAA,IAAAW,CAAA,CAAAC,GAAA,IAAAR,sBAAA,CAAAH,CAAA,EAAAK,CAAA,EAAAK,CAAA,IAAAV,CAAA,CAAAK,CAAA,IAAAd,CAAA,CAAAc,CAAA,YAAAL,CAAA,CAAAH,OAAA,GAAAN,CAAA,EAAAG,CAAA,IAAAA,CAAA,CAAAiB,GAAA,CAAApB,CAAA,EAAAS,CAAA,GAAAA,CAAA;AAP9B;AACA;AACA;;AAOA,IAAMY,OAAO,GAAG,CAAC,eAAe,EAAE,kBAAkB,CAAC;AAErD,IAAAC,yBAAc,EAAC,eAAe,EAAEC,sBAAa,EAAE;EAC7CC,MAAM,EAANA,eAAM;EACNH,OAAO,EAAPA;AACF,CAAC,CAAC"}
|
package/package.json
CHANGED
|
@@ -26,23 +26,23 @@
|
|
|
26
26
|
"@webex/eslint-config-legacy": "0.0.0",
|
|
27
27
|
"@webex/jest-config-legacy": "0.0.0",
|
|
28
28
|
"@webex/legacy-tools": "0.0.0",
|
|
29
|
-
"@webex/test-helper-chai": "3.6.0-next.
|
|
30
|
-
"@webex/test-helper-mocha": "3.6.0-next.
|
|
31
|
-
"@webex/test-helper-mock-webex": "3.6.0-next.
|
|
32
|
-
"@webex/test-helper-test-users": "3.6.0-next.
|
|
29
|
+
"@webex/test-helper-chai": "3.6.0-next.4",
|
|
30
|
+
"@webex/test-helper-mocha": "3.6.0-next.4",
|
|
31
|
+
"@webex/test-helper-mock-webex": "3.6.0-next.4",
|
|
32
|
+
"@webex/test-helper-test-users": "3.6.0-next.4",
|
|
33
33
|
"eslint": "^8.24.0",
|
|
34
34
|
"prettier": "^2.7.1",
|
|
35
35
|
"sinon": "^9.2.4"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@webex/common": "3.6.0-next.
|
|
39
|
-
"@webex/storage-adapter-local-storage": "3.6.0-next.
|
|
40
|
-
"@webex/test-helper-automation": "3.6.0-next.
|
|
41
|
-
"@webex/test-helper-chai": "3.6.0-next.
|
|
42
|
-
"@webex/test-helper-mocha": "3.6.0-next.
|
|
43
|
-
"@webex/test-helper-mock-webex": "3.6.0-next.
|
|
44
|
-
"@webex/test-helper-test-users": "3.6.0-next.
|
|
45
|
-
"@webex/webex-core": "3.6.0-next.
|
|
38
|
+
"@webex/common": "3.6.0-next.4",
|
|
39
|
+
"@webex/storage-adapter-local-storage": "3.6.0-next.4",
|
|
40
|
+
"@webex/test-helper-automation": "3.6.0-next.4",
|
|
41
|
+
"@webex/test-helper-chai": "3.6.0-next.4",
|
|
42
|
+
"@webex/test-helper-mocha": "3.6.0-next.4",
|
|
43
|
+
"@webex/test-helper-mock-webex": "3.6.0-next.4",
|
|
44
|
+
"@webex/test-helper-test-users": "3.6.0-next.4",
|
|
45
|
+
"@webex/webex-core": "3.6.0-next.4",
|
|
46
46
|
"crypto-js": "^4.1.1",
|
|
47
47
|
"lodash": "^4.17.21",
|
|
48
48
|
"uuid": "^3.3.2"
|
|
@@ -56,5 +56,5 @@
|
|
|
56
56
|
"test:style": "eslint ./src/**/*.*",
|
|
57
57
|
"test:unit": "webex-legacy-tools test --unit --runner jest"
|
|
58
58
|
},
|
|
59
|
-
"version": "3.6.0-next.
|
|
59
|
+
"version": "3.6.0-next.6"
|
|
60
60
|
}
|
package/src/authorization.js
CHANGED
|
@@ -22,6 +22,16 @@ const lodash = require('lodash');
|
|
|
22
22
|
const OAUTH2_CSRF_TOKEN = 'oauth2-csrf-token';
|
|
23
23
|
const OAUTH2_CODE_VERIFIER = 'oauth2-code-verifier';
|
|
24
24
|
|
|
25
|
+
/**
|
|
26
|
+
* Authorization plugin events
|
|
27
|
+
*/
|
|
28
|
+
export const Events = {
|
|
29
|
+
/**
|
|
30
|
+
* QR code login events
|
|
31
|
+
*/
|
|
32
|
+
qRCodeLogin: 'qRCodeLogin',
|
|
33
|
+
};
|
|
34
|
+
|
|
25
35
|
/**
|
|
26
36
|
* Browser support for OAuth2. Automatically parses the URL query for an
|
|
27
37
|
* authorization code
|
|
@@ -67,17 +77,49 @@ const Authorization = WebexPlugin.extend({
|
|
|
67
77
|
|
|
68
78
|
namespace: 'Credentials',
|
|
69
79
|
|
|
80
|
+
/**
|
|
81
|
+
* EventEmitter for authorization events
|
|
82
|
+
* @instance
|
|
83
|
+
* @memberof AuthorizationBrowserFirstParty
|
|
84
|
+
* @type {EventEmitter}
|
|
85
|
+
* @public
|
|
86
|
+
*/
|
|
87
|
+
eventEmitter: new EventEmitter(),
|
|
70
88
|
|
|
71
89
|
/**
|
|
72
|
-
* Stores the
|
|
90
|
+
* Stores the timer ID for QR code polling
|
|
73
91
|
* @instance
|
|
74
92
|
* @memberof AuthorizationBrowserFirstParty
|
|
75
93
|
* @type {?number}
|
|
76
94
|
* @private
|
|
77
95
|
*/
|
|
78
|
-
|
|
96
|
+
pollingTimer: null,
|
|
97
|
+
/**
|
|
98
|
+
* Stores the expiration timer ID for QR code polling
|
|
99
|
+
* @instance
|
|
100
|
+
* @memberof AuthorizationBrowserFirstParty
|
|
101
|
+
* @type {?number}
|
|
102
|
+
* @private
|
|
103
|
+
*/
|
|
104
|
+
pollingExpirationTimer: null,
|
|
79
105
|
|
|
80
|
-
|
|
106
|
+
/**
|
|
107
|
+
* Monotonically increasing id to identify the current polling request
|
|
108
|
+
* @instance
|
|
109
|
+
* @memberof AuthorizationBrowserFirstParty
|
|
110
|
+
* @type {number}
|
|
111
|
+
* @private
|
|
112
|
+
*/
|
|
113
|
+
pollingId: 0,
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Identifier for the current polling request
|
|
117
|
+
* @instance
|
|
118
|
+
* @memberof AuthorizationBrowserFirstParty
|
|
119
|
+
* @type {?number}
|
|
120
|
+
* @private
|
|
121
|
+
*/
|
|
122
|
+
currentPollingId: null,
|
|
81
123
|
|
|
82
124
|
/**
|
|
83
125
|
* Initializer
|
|
@@ -260,8 +302,8 @@ const Authorization = WebexPlugin.extend({
|
|
|
260
302
|
* @emits #qRCodeLogin
|
|
261
303
|
*/
|
|
262
304
|
initQRCodeLogin() {
|
|
263
|
-
if (this.
|
|
264
|
-
this.eventEmitter.emit(
|
|
305
|
+
if (this.pollingTimer) {
|
|
306
|
+
this.eventEmitter.emit(Events.qRCodeLogin, {
|
|
265
307
|
eventType: 'getUserCodeFailure',
|
|
266
308
|
data: {message: 'There is already a polling request'},
|
|
267
309
|
});
|
|
@@ -285,19 +327,19 @@ const Authorization = WebexPlugin.extend({
|
|
|
285
327
|
})
|
|
286
328
|
.then((res) => {
|
|
287
329
|
const {user_code, verification_uri, verification_uri_complete} = res.body;
|
|
288
|
-
this.eventEmitter.emit(
|
|
330
|
+
this.eventEmitter.emit(Events.qRCodeLogin, {
|
|
289
331
|
eventType: 'getUserCodeSuccess',
|
|
290
332
|
userData: {
|
|
291
333
|
userCode: user_code,
|
|
292
334
|
verificationUri: verification_uri,
|
|
293
335
|
verificationUriComplete: verification_uri_complete,
|
|
294
|
-
}
|
|
336
|
+
},
|
|
295
337
|
});
|
|
296
338
|
// if device authorization success, then start to poll server to check whether the user has completed authorization
|
|
297
339
|
this._startQRCodePolling(res.body);
|
|
298
340
|
})
|
|
299
341
|
.catch((res) => {
|
|
300
|
-
this.eventEmitter.emit(
|
|
342
|
+
this.eventEmitter.emit(Events.qRCodeLogin, {
|
|
301
343
|
eventType: 'getUserCodeFailure',
|
|
302
344
|
data: res.body,
|
|
303
345
|
});
|
|
@@ -313,30 +355,36 @@ const Authorization = WebexPlugin.extend({
|
|
|
313
355
|
*/
|
|
314
356
|
_startQRCodePolling(options = {}) {
|
|
315
357
|
if (!options.device_code) {
|
|
316
|
-
this.eventEmitter.emit(
|
|
358
|
+
this.eventEmitter.emit(Events.qRCodeLogin, {
|
|
317
359
|
eventType: 'authorizationFailure',
|
|
318
360
|
data: {message: 'A deviceCode is required'},
|
|
319
361
|
});
|
|
320
362
|
return;
|
|
321
363
|
}
|
|
322
364
|
|
|
323
|
-
if (this.
|
|
324
|
-
this.eventEmitter.emit(
|
|
365
|
+
if (this.pollingTimer) {
|
|
366
|
+
this.eventEmitter.emit(Events.qRCodeLogin, {
|
|
325
367
|
eventType: 'authorizationFailure',
|
|
326
368
|
data: {message: 'There is already a polling request'},
|
|
327
369
|
});
|
|
328
370
|
return;
|
|
329
371
|
}
|
|
330
372
|
|
|
331
|
-
const {device_code: deviceCode,
|
|
373
|
+
const {device_code: deviceCode, expires_in: expiresIn = 300} = options;
|
|
374
|
+
let interval = options.interval ?? 2;
|
|
332
375
|
|
|
333
|
-
|
|
334
|
-
|
|
376
|
+
this.pollingExpirationTimer = setTimeout(() => {
|
|
377
|
+
this.cancelQRCodePolling(false);
|
|
378
|
+
this.eventEmitter.emit(Events.qRCodeLogin, {
|
|
379
|
+
eventType: 'authorizationFailure',
|
|
380
|
+
data: {message: 'Authorization timed out'},
|
|
381
|
+
});
|
|
382
|
+
}, expiresIn * 1000);
|
|
335
383
|
|
|
336
|
-
|
|
337
|
-
|
|
384
|
+
const polling = () => {
|
|
385
|
+
this.pollingId += 1;
|
|
386
|
+
this.currentPollingId = this.pollingId;
|
|
338
387
|
|
|
339
|
-
const currentAttempts = attempts;
|
|
340
388
|
this.webex
|
|
341
389
|
.request({
|
|
342
390
|
method: 'POST',
|
|
@@ -354,43 +402,50 @@ const Authorization = WebexPlugin.extend({
|
|
|
354
402
|
},
|
|
355
403
|
})
|
|
356
404
|
.then((res) => {
|
|
357
|
-
if
|
|
405
|
+
// if the pollingId has changed, it means that the polling request has been canceled
|
|
406
|
+
if (this.currentPollingId !== this.pollingId) return;
|
|
358
407
|
|
|
359
|
-
this.eventEmitter.emit(
|
|
408
|
+
this.eventEmitter.emit(Events.qRCodeLogin, {
|
|
360
409
|
eventType: 'authorizationSuccess',
|
|
361
410
|
data: res.body,
|
|
362
411
|
});
|
|
363
412
|
this.cancelQRCodePolling();
|
|
364
413
|
})
|
|
365
414
|
.catch((res) => {
|
|
366
|
-
if
|
|
415
|
+
// if the pollingId has changed, it means that the polling request has been canceled
|
|
416
|
+
if (this.currentPollingId !== this.pollingId) return;
|
|
367
417
|
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
});
|
|
373
|
-
this.cancelQRCodePolling();
|
|
418
|
+
// When server sends 400 status code with message 'slow_down', it means that last request happened too soon.
|
|
419
|
+
// So, skip one interval and then poll again.
|
|
420
|
+
if (res.statusCode === 400 && res.body.message === 'slow_down') {
|
|
421
|
+
schedulePolling(interval * 2);
|
|
374
422
|
return;
|
|
375
423
|
}
|
|
424
|
+
|
|
376
425
|
// if the statusCode is 428 which means that the authorization request is still pending
|
|
377
426
|
// as the end user hasn't yet completed the user-interaction steps. So keep polling.
|
|
378
427
|
if (res.statusCode === 428) {
|
|
379
|
-
this.eventEmitter.emit(
|
|
428
|
+
this.eventEmitter.emit(Events.qRCodeLogin, {
|
|
380
429
|
eventType: 'authorizationPending',
|
|
381
|
-
data: res.body
|
|
430
|
+
data: res.body,
|
|
382
431
|
});
|
|
432
|
+
schedulePolling(interval);
|
|
383
433
|
return;
|
|
384
434
|
}
|
|
385
435
|
|
|
386
436
|
this.cancelQRCodePolling();
|
|
387
437
|
|
|
388
|
-
this.eventEmitter.emit(
|
|
438
|
+
this.eventEmitter.emit(Events.qRCodeLogin, {
|
|
389
439
|
eventType: 'authorizationFailure',
|
|
390
|
-
data: res.body
|
|
440
|
+
data: res.body,
|
|
391
441
|
});
|
|
392
442
|
});
|
|
393
|
-
}
|
|
443
|
+
};
|
|
444
|
+
|
|
445
|
+
const schedulePolling = (interval) =>
|
|
446
|
+
(this.pollingTimer = setTimeout(polling, interval * 1000));
|
|
447
|
+
|
|
448
|
+
schedulePolling(interval);
|
|
394
449
|
},
|
|
395
450
|
|
|
396
451
|
/**
|
|
@@ -399,14 +454,19 @@ const Authorization = WebexPlugin.extend({
|
|
|
399
454
|
* @memberof AuthorizationBrowserFirstParty
|
|
400
455
|
* @returns {void}
|
|
401
456
|
*/
|
|
402
|
-
cancelQRCodePolling() {
|
|
403
|
-
if (this.
|
|
404
|
-
|
|
405
|
-
this.eventEmitter.emit('qRCodeLogin', {
|
|
457
|
+
cancelQRCodePolling(withCancelEvent = true) {
|
|
458
|
+
if (this.pollingTimer && withCancelEvent) {
|
|
459
|
+
this.eventEmitter.emit(Events.qRCodeLogin, {
|
|
406
460
|
eventType: 'pollingCanceled',
|
|
407
461
|
});
|
|
408
|
-
this.pollingRequest = null;
|
|
409
462
|
}
|
|
463
|
+
|
|
464
|
+
this.currentPollingId = null;
|
|
465
|
+
|
|
466
|
+
clearTimeout(this.pollingExpirationTimer);
|
|
467
|
+
this.pollingExpirationTimer = null;
|
|
468
|
+
clearTimeout(this.pollingTimer);
|
|
469
|
+
this.pollingTimer = null;
|
|
410
470
|
},
|
|
411
471
|
|
|
412
472
|
/**
|
package/src/index.js
CHANGED
|
@@ -18,7 +18,6 @@ import Authorization from '@webex/plugin-authorization-browser-first-party';
|
|
|
18
18
|
// Necessary to require lodash this way in order to stub the method
|
|
19
19
|
const lodash = require('lodash');
|
|
20
20
|
|
|
21
|
-
|
|
22
21
|
describe('plugin-authorization-browser-first-party', () => {
|
|
23
22
|
describe('Authorization', () => {
|
|
24
23
|
function makeWebex(
|
|
@@ -187,14 +186,16 @@ describe('plugin-authorization-browser-first-party', () => {
|
|
|
187
186
|
const webex = makeWebex(
|
|
188
187
|
`http://example.com/?code=${code}&state=${base64.encode(
|
|
189
188
|
JSON.stringify({emailhash: 'someemailhash'})
|
|
190
|
-
)}
|
|
189
|
+
)}`
|
|
191
190
|
);
|
|
192
191
|
|
|
193
192
|
const requestAuthorizationCodeGrantStub = sinon.stub(
|
|
194
193
|
Authorization.prototype,
|
|
195
194
|
'requestAuthorizationCodeGrant'
|
|
196
195
|
);
|
|
197
|
-
const collectPreauthCatalogStub = sinon
|
|
196
|
+
const collectPreauthCatalogStub = sinon
|
|
197
|
+
.stub(Services.prototype, 'collectPreauthCatalog')
|
|
198
|
+
.resolves();
|
|
198
199
|
|
|
199
200
|
await webex.authorization.when('change:ready');
|
|
200
201
|
|
|
@@ -206,9 +207,7 @@ describe('plugin-authorization-browser-first-party', () => {
|
|
|
206
207
|
|
|
207
208
|
it('collects the preauth catalog no emailhash is present in the state', async () => {
|
|
208
209
|
const code = 'authcode_clusterid_theOrgId';
|
|
209
|
-
const webex = makeWebex(
|
|
210
|
-
`http://example.com/?code=${code}`
|
|
211
|
-
);
|
|
210
|
+
const webex = makeWebex(`http://example.com/?code=${code}`);
|
|
212
211
|
|
|
213
212
|
const requestAuthorizationCodeGrantStub = sinon.stub(
|
|
214
213
|
Authorization.prototype,
|
|
@@ -271,12 +270,13 @@ describe('plugin-authorization-browser-first-party', () => {
|
|
|
271
270
|
it('throws a grant error', () => {
|
|
272
271
|
let err = null;
|
|
273
272
|
try {
|
|
274
|
-
makeWebex(
|
|
275
|
-
|
|
276
|
-
|
|
273
|
+
makeWebex(
|
|
274
|
+
'http://127.0.0.1:8000/?error=invalid_scope&error_description=The%20requested%20scope%20is%20invalid.'
|
|
275
|
+
);
|
|
276
|
+
} catch (e) {
|
|
277
277
|
err = e;
|
|
278
278
|
}
|
|
279
|
-
expect(err?.message).toBe('Cannot convert object to primitive value')
|
|
279
|
+
expect(err?.message).toBe('Cannot convert object to primitive value');
|
|
280
280
|
});
|
|
281
281
|
});
|
|
282
282
|
|
|
@@ -446,14 +446,14 @@ describe('plugin-authorization-browser-first-party', () => {
|
|
|
446
446
|
describe('#initQRCodeLogin()', () => {
|
|
447
447
|
it('should prevent concurrent request if there is already a polling request', async () => {
|
|
448
448
|
const webex = makeWebex('http://example.com');
|
|
449
|
-
|
|
450
|
-
webex.authorization.
|
|
449
|
+
|
|
450
|
+
webex.authorization.pollingTimer = 1;
|
|
451
451
|
const emitSpy = sinon.spy(webex.authorization.eventEmitter, 'emit');
|
|
452
452
|
webex.authorization.initQRCodeLogin();
|
|
453
|
-
|
|
453
|
+
|
|
454
454
|
assert.calledOnce(emitSpy);
|
|
455
|
-
assert.equal(emitSpy.getCall(0).args[1].eventType, 'getUserCodeFailure');
|
|
456
|
-
webex.authorization.
|
|
455
|
+
assert.equal(emitSpy.getCall(0).args[1].eventType, 'getUserCodeFailure');
|
|
456
|
+
webex.authorization.pollingTimer = null;
|
|
457
457
|
});
|
|
458
458
|
|
|
459
459
|
it('should send correct request parameters to the API', async () => {
|
|
@@ -461,19 +461,19 @@ describe('plugin-authorization-browser-first-party', () => {
|
|
|
461
461
|
const testClientId = 'test-client-id';
|
|
462
462
|
const testScope = 'test-scope';
|
|
463
463
|
const sampleData = {
|
|
464
|
-
device_code:
|
|
464
|
+
device_code: 'test123',
|
|
465
465
|
expires_in: 300,
|
|
466
|
-
user_code:
|
|
467
|
-
verification_uri:
|
|
468
|
-
verification_uri_complete:
|
|
469
|
-
interval: 2
|
|
466
|
+
user_code: '421175',
|
|
467
|
+
verification_uri: 'http://example.com',
|
|
468
|
+
verification_uri_complete: 'http://example.com',
|
|
469
|
+
interval: 2,
|
|
470
470
|
};
|
|
471
471
|
|
|
472
472
|
const webex = makeWebex('http://example.com', undefined, undefined, {
|
|
473
473
|
credentials: {
|
|
474
474
|
client_id: testClientId,
|
|
475
475
|
scope: testScope,
|
|
476
|
-
}
|
|
476
|
+
},
|
|
477
477
|
});
|
|
478
478
|
webex.request.onFirstCall().resolves({statusCode: 200, body: sampleData});
|
|
479
479
|
sinon.spy(webex.authorization, '_startQRCodePolling');
|
|
@@ -481,11 +481,11 @@ describe('plugin-authorization-browser-first-party', () => {
|
|
|
481
481
|
|
|
482
482
|
webex.authorization.initQRCodeLogin();
|
|
483
483
|
clock.tick(2000);
|
|
484
|
-
await clock.runAllAsync()
|
|
484
|
+
await clock.runAllAsync();
|
|
485
485
|
|
|
486
486
|
assert.calledTwice(webex.request);
|
|
487
487
|
assert.calledOnce(webex.authorization._startQRCodePolling);
|
|
488
|
-
assert.equal(emitSpy.getCall(0).args[1].eventType, 'getUserCodeSuccess');
|
|
488
|
+
assert.equal(emitSpy.getCall(0).args[1].eventType, 'getUserCodeSuccess');
|
|
489
489
|
|
|
490
490
|
const request = webex.request.getCall(0);
|
|
491
491
|
|
|
@@ -498,18 +498,18 @@ describe('plugin-authorization-browser-first-party', () => {
|
|
|
498
498
|
const clock = sinon.useFakeTimers();
|
|
499
499
|
const webex = makeWebex('http://example.com');
|
|
500
500
|
const sampleData = {
|
|
501
|
-
device_code:
|
|
501
|
+
device_code: 'test123',
|
|
502
502
|
expires_in: 300,
|
|
503
|
-
user_code:
|
|
504
|
-
verification_uri:
|
|
505
|
-
verification_uri_complete:
|
|
506
|
-
interval: 2
|
|
503
|
+
user_code: '421175',
|
|
504
|
+
verification_uri: 'http://example.com',
|
|
505
|
+
verification_uri_complete: 'http://example.com',
|
|
506
|
+
interval: 2,
|
|
507
507
|
};
|
|
508
508
|
webex.request.resolves().resolves({statusCode: 200, body: sampleData});
|
|
509
509
|
|
|
510
510
|
webex.authorization.initQRCodeLogin();
|
|
511
511
|
clock.tick(2000);
|
|
512
|
-
await clock.runAllAsync()
|
|
512
|
+
await clock.runAllAsync();
|
|
513
513
|
|
|
514
514
|
const request = webex.request.getCall(0);
|
|
515
515
|
assert.equal(request.args[0].method, 'POST');
|
|
@@ -517,7 +517,7 @@ describe('plugin-authorization-browser-first-party', () => {
|
|
|
517
517
|
assert.equal(request.args[0].resource, '/actions/device/authorize');
|
|
518
518
|
clock.restore();
|
|
519
519
|
});
|
|
520
|
-
|
|
520
|
+
|
|
521
521
|
it('should emit getUserCodeFailure event', async () => {
|
|
522
522
|
const clock = sinon.useFakeTimers();
|
|
523
523
|
const webex = makeWebex('http://example.com');
|
|
@@ -526,7 +526,7 @@ describe('plugin-authorization-browser-first-party', () => {
|
|
|
526
526
|
|
|
527
527
|
webex.authorization.initQRCodeLogin();
|
|
528
528
|
|
|
529
|
-
await clock.runAllAsync()
|
|
529
|
+
await clock.runAllAsync();
|
|
530
530
|
|
|
531
531
|
assert.calledOnce(emitSpy);
|
|
532
532
|
assert.equal(emitSpy.getCall(0).args[1].eventType, 'getUserCodeFailure');
|
|
@@ -537,15 +537,15 @@ describe('plugin-authorization-browser-first-party', () => {
|
|
|
537
537
|
describe('#_startQRCodePolling()', () => {
|
|
538
538
|
it('requires a deviceCode', () => {
|
|
539
539
|
const webex = makeWebex('http://example.com');
|
|
540
|
-
|
|
540
|
+
|
|
541
541
|
const emitSpy = sinon.spy(webex.authorization.eventEmitter, 'emit');
|
|
542
542
|
|
|
543
543
|
webex.authorization._startQRCodePolling({});
|
|
544
544
|
|
|
545
545
|
assert.calledOnce(emitSpy);
|
|
546
|
-
assert.equal(emitSpy.getCall(0).args[1].eventType, 'authorizationFailure');
|
|
546
|
+
assert.equal(emitSpy.getCall(0).args[1].eventType, 'authorizationFailure');
|
|
547
547
|
});
|
|
548
|
-
|
|
548
|
+
|
|
549
549
|
it('should send correct request parameters to the API', async () => {
|
|
550
550
|
const clock = sinon.useFakeTimers();
|
|
551
551
|
const testClientId = 'test-client-id';
|
|
@@ -560,7 +560,7 @@ describe('plugin-authorization-browser-first-party', () => {
|
|
|
560
560
|
const webex = makeWebex('http://example.com', undefined, undefined, {
|
|
561
561
|
credentials: {
|
|
562
562
|
client_id: testClientId,
|
|
563
|
-
}
|
|
563
|
+
},
|
|
564
564
|
});
|
|
565
565
|
|
|
566
566
|
webex.request.onFirstCall().resolves({statusCode: 200, body: {access_token: 'token'}});
|
|
@@ -569,7 +569,7 @@ describe('plugin-authorization-browser-first-party', () => {
|
|
|
569
569
|
|
|
570
570
|
webex.authorization._startQRCodePolling(options);
|
|
571
571
|
clock.tick(2000);
|
|
572
|
-
await clock.runAllAsync()
|
|
572
|
+
await clock.runAllAsync();
|
|
573
573
|
|
|
574
574
|
assert.calledOnce(webex.request);
|
|
575
575
|
|
|
@@ -577,7 +577,10 @@ describe('plugin-authorization-browser-first-party', () => {
|
|
|
577
577
|
|
|
578
578
|
assert.equal(request.args[0].form.client_id, testClientId);
|
|
579
579
|
assert.equal(request.args[0].form.device_code, testDeviceCode);
|
|
580
|
-
assert.equal(
|
|
580
|
+
assert.equal(
|
|
581
|
+
request.args[0].form.grant_type,
|
|
582
|
+
'urn:ietf:params:oauth:grant-type:device_code'
|
|
583
|
+
);
|
|
581
584
|
|
|
582
585
|
assert.calledOnce(webex.authorization.cancelQRCodePolling);
|
|
583
586
|
assert.calledTwice(emitSpy);
|
|
@@ -593,23 +596,26 @@ describe('plugin-authorization-browser-first-party', () => {
|
|
|
593
596
|
const options = {
|
|
594
597
|
device_code: 'test-device-code',
|
|
595
598
|
interval: 2,
|
|
596
|
-
expires_in: 300
|
|
599
|
+
expires_in: 300,
|
|
597
600
|
};
|
|
598
|
-
|
|
599
|
-
webex.request
|
|
601
|
+
|
|
602
|
+
webex.request
|
|
603
|
+
.onFirstCall()
|
|
604
|
+
.rejects({statusCode: 428, body: {message: 'authorization_pending'}});
|
|
600
605
|
webex.request.onSecondCall().resolves({statusCode: 200, body: {access_token: 'token'}});
|
|
601
606
|
sinon.spy(webex.authorization, 'cancelQRCodePolling');
|
|
602
607
|
const emitSpy = sinon.spy(webex.authorization.eventEmitter, 'emit');
|
|
603
|
-
|
|
608
|
+
|
|
604
609
|
webex.authorization._startQRCodePolling(options);
|
|
605
|
-
clock.
|
|
606
|
-
await clock.runAllAsync()
|
|
607
|
-
|
|
610
|
+
await clock.tickAsync(4000);
|
|
611
|
+
//await clock.runAllAsync()
|
|
612
|
+
|
|
608
613
|
assert.calledTwice(webex.request);
|
|
609
614
|
assert.calledOnce(webex.authorization.cancelQRCodePolling);
|
|
610
|
-
assert.
|
|
611
|
-
assert.equal(emitSpy.getCall(0).args[1].eventType, '
|
|
612
|
-
assert.equal(emitSpy.getCall(1).args[1].eventType, '
|
|
615
|
+
assert.calledThrice(emitSpy);
|
|
616
|
+
assert.equal(emitSpy.getCall(0).args[1].eventType, 'authorizationPending');
|
|
617
|
+
assert.equal(emitSpy.getCall(1).args[1].eventType, 'authorizationSuccess');
|
|
618
|
+
assert.equal(emitSpy.getCall(2).args[1].eventType, 'pollingCanceled');
|
|
613
619
|
clock.restore();
|
|
614
620
|
});
|
|
615
621
|
|
|
@@ -619,23 +625,21 @@ describe('plugin-authorization-browser-first-party', () => {
|
|
|
619
625
|
const options = {
|
|
620
626
|
device_code: 'test-device-code',
|
|
621
627
|
interval: 5,
|
|
622
|
-
expires_in:
|
|
628
|
+
expires_in: 9,
|
|
623
629
|
};
|
|
624
|
-
|
|
630
|
+
|
|
625
631
|
webex.request.rejects({statusCode: 428, body: {message: 'authorizationPending'}});
|
|
626
632
|
sinon.spy(webex.authorization, 'cancelQRCodePolling');
|
|
627
633
|
const emitSpy = sinon.spy(webex.authorization.eventEmitter, 'emit');
|
|
628
634
|
|
|
629
635
|
webex.authorization._startQRCodePolling(options);
|
|
630
|
-
clock.
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
assert.calledTwice(webex.request);
|
|
636
|
+
await clock.tickAsync(10_000);
|
|
637
|
+
|
|
638
|
+
assert.calledOnce(webex.request);
|
|
634
639
|
assert.calledOnce(webex.authorization.cancelQRCodePolling);
|
|
635
|
-
assert.
|
|
636
|
-
assert.equal(emitSpy.getCall(0).args[1].eventType, 'authorizationPending');
|
|
640
|
+
assert.calledTwice(emitSpy);
|
|
641
|
+
assert.equal(emitSpy.getCall(0).args[1].eventType, 'authorizationPending');
|
|
637
642
|
assert.equal(emitSpy.getCall(1).args[1].eventType, 'authorizationFailure');
|
|
638
|
-
assert.equal(emitSpy.getCall(2).args[1].eventType, 'pollingCanceled');
|
|
639
643
|
clock.restore();
|
|
640
644
|
});
|
|
641
645
|
|
|
@@ -644,54 +648,129 @@ describe('plugin-authorization-browser-first-party', () => {
|
|
|
644
648
|
const options = {
|
|
645
649
|
device_code: 'test-device-code',
|
|
646
650
|
interval: 2,
|
|
647
|
-
expires_in: 300
|
|
651
|
+
expires_in: 300,
|
|
648
652
|
};
|
|
649
|
-
|
|
650
|
-
webex.authorization.
|
|
653
|
+
|
|
654
|
+
webex.authorization.pollingTimer = 1;
|
|
651
655
|
|
|
652
656
|
const emitSpy = sinon.spy(webex.authorization.eventEmitter, 'emit');
|
|
653
657
|
webex.authorization._startQRCodePolling(options);
|
|
654
658
|
|
|
655
659
|
assert.calledOnce(emitSpy);
|
|
656
|
-
assert.equal(emitSpy.getCall(0).args[1].eventType, 'authorizationFailure');
|
|
657
|
-
webex.authorization.
|
|
660
|
+
assert.equal(emitSpy.getCall(0).args[1].eventType, 'authorizationFailure');
|
|
661
|
+
webex.authorization.pollingTimer = null;
|
|
662
|
+
});
|
|
663
|
+
|
|
664
|
+
it('should skip a interval when server ask for slow_down', async () => {
|
|
665
|
+
const clock = sinon.useFakeTimers();
|
|
666
|
+
const webex = makeWebex('http://example.com');
|
|
667
|
+
const options = {
|
|
668
|
+
device_code: 'test-device-code',
|
|
669
|
+
interval: 2,
|
|
670
|
+
expires_in: 300,
|
|
671
|
+
};
|
|
672
|
+
|
|
673
|
+
webex.request.onFirstCall().rejects({statusCode: 400, body: {message: 'slow_down'}});
|
|
674
|
+
webex.request.onSecondCall().resolves({statusCode: 200, body: {access_token: 'token'}});
|
|
675
|
+
sinon.spy(webex.authorization, 'cancelQRCodePolling');
|
|
676
|
+
const emitSpy = sinon.spy(webex.authorization.eventEmitter, 'emit');
|
|
677
|
+
|
|
678
|
+
webex.authorization._startQRCodePolling(options);
|
|
679
|
+
await clock.tickAsync(4000);
|
|
680
|
+
|
|
681
|
+
// Request only once because of slow_down
|
|
682
|
+
assert.calledOnce(webex.request);
|
|
683
|
+
|
|
684
|
+
// Wait for next interval
|
|
685
|
+
await clock.tickAsync(2000);
|
|
686
|
+
|
|
687
|
+
assert.calledTwice(webex.request);
|
|
688
|
+
assert.calledOnce(webex.authorization.cancelQRCodePolling);
|
|
689
|
+
assert.calledTwice(emitSpy);
|
|
690
|
+
assert.equal(emitSpy.getCall(0).args[1].eventType, 'authorizationSuccess');
|
|
691
|
+
assert.equal(emitSpy.getCall(1).args[1].eventType, 'pollingCanceled');
|
|
692
|
+
clock.restore();
|
|
693
|
+
});
|
|
694
|
+
|
|
695
|
+
it('should ignore the response from the previous polling', async () => {
|
|
696
|
+
const clock = sinon.useFakeTimers();
|
|
697
|
+
const webex = makeWebex('http://example.com');
|
|
698
|
+
const options = {
|
|
699
|
+
device_code: 'test-device-code',
|
|
700
|
+
interval: 2,
|
|
701
|
+
expires_in: 300,
|
|
702
|
+
};
|
|
703
|
+
|
|
704
|
+
webex.request.onFirstCall().callsFake(() => {
|
|
705
|
+
return new Promise((resolve) => {
|
|
706
|
+
setTimeout(() => {
|
|
707
|
+
resolve({statusCode: 200, body: {access_token: 'token'}});
|
|
708
|
+
}, 1000);
|
|
709
|
+
});
|
|
710
|
+
});
|
|
711
|
+
|
|
712
|
+
webex.request
|
|
713
|
+
.onSecondCall()
|
|
714
|
+
.rejects({statusCode: 428, body: {message: 'authorizationPending'}});
|
|
715
|
+
sinon.spy(webex.authorization, 'cancelQRCodePolling');
|
|
716
|
+
const emitSpy = sinon.spy(webex.authorization.eventEmitter, 'emit');
|
|
717
|
+
|
|
718
|
+
webex.authorization._startQRCodePolling(options);
|
|
719
|
+
await clock.tickAsync(2500);
|
|
720
|
+
|
|
721
|
+
webex.authorization.cancelQRCodePolling();
|
|
722
|
+
|
|
723
|
+
// Start new polling
|
|
724
|
+
|
|
725
|
+
webex.authorization._startQRCodePolling(options);
|
|
726
|
+
|
|
727
|
+
// Wait for next interval
|
|
728
|
+
await clock.tickAsync(3000);
|
|
729
|
+
|
|
730
|
+
assert.calledTwice(webex.request);
|
|
731
|
+
assert.calledOnce(webex.authorization.cancelQRCodePolling);
|
|
732
|
+
assert.calledTwice(emitSpy);
|
|
733
|
+
// authorizationSuccess event should not be emitted
|
|
734
|
+
assert.equal(emitSpy.getCall(0).args[1].eventType, 'pollingCanceled');
|
|
735
|
+
assert.equal(emitSpy.getCall(1).args[1].eventType, 'authorizationPending');
|
|
736
|
+
clock.restore();
|
|
658
737
|
});
|
|
659
738
|
});
|
|
660
739
|
|
|
661
740
|
describe('#cancelQRCodePolling()', () => {
|
|
662
741
|
it('should stop polling after cancellation', async () => {
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
742
|
+
const clock = sinon.useFakeTimers();
|
|
743
|
+
const webex = makeWebex('http://example.com');
|
|
744
|
+
const options = {
|
|
745
|
+
device_code: 'test-device-code',
|
|
746
|
+
interval: 2,
|
|
747
|
+
expires_in: 300,
|
|
748
|
+
};
|
|
749
|
+
|
|
750
|
+
webex.request.rejects({statusCode: 428, body: {message: 'authorizationPending'}});
|
|
751
|
+
const emitSpy = sinon.spy(webex.authorization.eventEmitter, 'emit');
|
|
752
|
+
|
|
753
|
+
webex.authorization._startQRCodePolling(options);
|
|
754
|
+
// First poll
|
|
755
|
+
clock.tick(2000);
|
|
756
|
+
assert.calledOnce(webex.request);
|
|
757
|
+
|
|
758
|
+
webex.authorization.cancelQRCodePolling();
|
|
759
|
+
// Wait for next interval
|
|
760
|
+
clock.tick(2000);
|
|
761
|
+
|
|
762
|
+
const eventArgs = emitSpy.getCall(0).args;
|
|
763
|
+
|
|
764
|
+
// Verify no additional requests were made
|
|
765
|
+
assert.calledOnce(webex.request);
|
|
766
|
+
assert.calledOnce(emitSpy);
|
|
767
|
+
assert.equal(eventArgs[1].eventType, 'pollingCanceled');
|
|
768
|
+
clock.restore();
|
|
769
|
+
});
|
|
691
770
|
it('should clear interval and reset polling request', () => {
|
|
692
771
|
const clock = sinon.useFakeTimers();
|
|
693
772
|
const webex = makeWebex('http://example.com');
|
|
694
|
-
|
|
773
|
+
|
|
695
774
|
const options = {
|
|
696
775
|
device_code: 'test_device_code',
|
|
697
776
|
interval: 2,
|
|
@@ -699,22 +778,21 @@ describe('plugin-authorization-browser-first-party', () => {
|
|
|
699
778
|
};
|
|
700
779
|
|
|
701
780
|
webex.authorization._startQRCodePolling(options);
|
|
702
|
-
assert.isDefined(webex.authorization.
|
|
703
|
-
|
|
781
|
+
assert.isDefined(webex.authorization.pollingTimer);
|
|
782
|
+
|
|
704
783
|
webex.authorization.cancelQRCodePolling();
|
|
705
|
-
assert.isNull(webex.authorization.
|
|
706
|
-
|
|
784
|
+
assert.isNull(webex.authorization.pollingTimer);
|
|
785
|
+
|
|
707
786
|
clock.restore();
|
|
708
787
|
});
|
|
709
|
-
|
|
788
|
+
|
|
710
789
|
it('should handle cancellation when no polling is in progress', () => {
|
|
711
790
|
const webex = makeWebex('http://example.com');
|
|
712
|
-
assert.isNull(webex.authorization.
|
|
713
|
-
|
|
791
|
+
assert.isNull(webex.authorization.pollingTimer);
|
|
792
|
+
|
|
714
793
|
webex.authorization.cancelQRCodePolling();
|
|
715
|
-
assert.isNull(webex.authorization.
|
|
794
|
+
assert.isNull(webex.authorization.pollingTimer);
|
|
716
795
|
});
|
|
717
|
-
|
|
718
796
|
});
|
|
719
797
|
|
|
720
798
|
describe('#_generateCodeChallenge', () => {
|
|
@@ -836,7 +914,7 @@ describe('plugin-authorization-browser-first-party', () => {
|
|
|
836
914
|
const orgId = webex.authorization._extractOrgIdFromCode(code);
|
|
837
915
|
|
|
838
916
|
assert.isUndefined(orgId);
|
|
839
|
-
})
|
|
917
|
+
});
|
|
840
918
|
});
|
|
841
919
|
});
|
|
842
920
|
});
|