@webex/plugin-authorization-browser-first-party 1.150.0 → 1.151.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/authorization.js
CHANGED
|
@@ -132,7 +132,7 @@ var Authorization = _webexCore.WebexPlugin.extend((_dec = (0, _common.whileInFli
|
|
|
132
132
|
|
|
133
133
|
var codeVerifier = this.webex.getWindow().sessionStorage.getItem(OAUTH2_CODE_VERIFIER);
|
|
134
134
|
this.webex.getWindow().sessionStorage.removeItem(OAUTH2_CODE_VERIFIER);
|
|
135
|
-
var
|
|
135
|
+
var emailhash = location.query.state.emailhash;
|
|
136
136
|
|
|
137
137
|
this._verifySecurityToken(location.query);
|
|
138
138
|
|
|
@@ -141,7 +141,7 @@ var Authorization = _webexCore.WebexPlugin.extend((_dec = (0, _common.whileInFli
|
|
|
141
141
|
|
|
142
142
|
process.nextTick(function () {
|
|
143
143
|
_this.webex.internal.services.collectPreauthCatalog({
|
|
144
|
-
|
|
144
|
+
emailhash: emailhash
|
|
145
145
|
}).catch(function () {
|
|
146
146
|
return _promise.default.resolve();
|
|
147
147
|
}).then(function () {
|
|
@@ -165,9 +165,17 @@ var Authorization = _webexCore.WebexPlugin.extend((_dec = (0, _common.whileInFli
|
|
|
165
165
|
*/
|
|
166
166
|
initiateLogin: function initiateLogin() {
|
|
167
167
|
var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
168
|
+
options = (0, _cloneDeep2.default)(options);
|
|
169
|
+
|
|
170
|
+
if (options.email) {
|
|
171
|
+
options.emailHash = _cryptoJs.default.SHA256(options.email).toString();
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
delete options.email;
|
|
168
175
|
options.state = options.state || {};
|
|
169
|
-
options.state.csrf_token = this._generateSecurityToken();
|
|
170
|
-
|
|
176
|
+
options.state.csrf_token = this._generateSecurityToken(); // catalog uses emailhash and redirectCI uses emailHash
|
|
177
|
+
|
|
178
|
+
options.state.emailhash = options.emailHash;
|
|
171
179
|
options.code_challenge = this._generateCodeChallenge();
|
|
172
180
|
options.code_challenge_method = 'S256';
|
|
173
181
|
return this.initiateAuthorizationCodeGrant(options);
|
|
@@ -371,7 +379,7 @@ var Authorization = _webexCore.WebexPlugin.extend((_dec = (0, _common.whileInFli
|
|
|
371
379
|
throw new Error("CSRF token ".concat(token, " does not match stored token ").concat(sessionToken));
|
|
372
380
|
}
|
|
373
381
|
},
|
|
374
|
-
version: "1.
|
|
382
|
+
version: "1.151.2"
|
|
375
383
|
}, ((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)));
|
|
376
384
|
|
|
377
385
|
var _default = Authorization;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["authorization.js"],"names":["lodash","require","OAUTH2_CSRF_TOKEN","OAUTH2_CODE_VERIFIER","Authorization","WebexPlugin","extend","derived","isAuthenticating","deps","fn","isAuthorizing","session","default","type","ready","namespace","initialize","attrs","ret","prototype","location","url","parse","webex","getWindow","href","_checkForErrors","code","query","state","JSON","base64","decode","codeVerifier","sessionStorage","getItem","removeItem","email","_verifySecurityToken","_cleanUrl","process","nextTick","internal","services","collectPreauthCatalog","catch","resolve","then","requestAuthorizationCodeGrant","initiateLogin","options","csrf_token","_generateSecurityToken","code_challenge","_generateCodeChallenge","code_challenge_method","initiateAuthorizationCodeGrant","logger","info","credentials","buildLoginUrl","response_type","logout","noRedirect","buildLogoutUrl","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","error","_res","history","replaceState","encode","search","querystring","stringify","format","safeCharacterMap","base64url","_safe_map","times","random","length","join","codeChallenge","CryptoJS","SHA256","toString","setItem","token","uuid","v4","sessionToken","oneFlight"],"mappings":"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","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';\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 * 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 }\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\n const {email} = location.query.state;\n\n this._verifySecurityToken(location.query);\n this._cleanUrl(location);\n\n // Wait until nextTick in case `credentials` hasn't initialized yet\n process.nextTick(() => {\n this.webex.internal.services.collectPreauthCatalog({email})\n .catch(() => Promise.resolve())\n .then(() => this.requestAuthorizationCodeGrant({code, codeVerifier}))\n .then(() => {\n this.ready = true;\n });\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.state = options.state || {};\n options.state.csrf_token = this._generateSecurityToken();\n options.state.email = options.email;\n\n options.code_challenge = this._generateCodeChallenge();\n options.code_challenge_method = 'S256';\n\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(Object.assign({response_type: 'code'}, options));\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\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.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 * 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 }\n else {\n location.query.state = base64.encode(JSON.stringify(omit(location.query.state, 'csrf_token')));\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.times(\n 128,\n () => 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(\n OAUTH2_CODE_VERIFIER, codeVerifier\n );\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"]}
|
|
1
|
+
{"version":3,"sources":["authorization.js"],"names":["lodash","require","OAUTH2_CSRF_TOKEN","OAUTH2_CODE_VERIFIER","Authorization","WebexPlugin","extend","derived","isAuthenticating","deps","fn","isAuthorizing","session","default","type","ready","namespace","initialize","attrs","ret","prototype","location","url","parse","webex","getWindow","href","_checkForErrors","code","query","state","JSON","base64","decode","codeVerifier","sessionStorage","getItem","removeItem","emailhash","_verifySecurityToken","_cleanUrl","process","nextTick","internal","services","collectPreauthCatalog","catch","resolve","then","requestAuthorizationCodeGrant","initiateLogin","options","email","emailHash","CryptoJS","SHA256","toString","csrf_token","_generateSecurityToken","code_challenge","_generateCodeChallenge","code_challenge_method","initiateAuthorizationCodeGrant","logger","info","credentials","buildLoginUrl","response_type","logout","noRedirect","buildLogoutUrl","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","error","_res","history","replaceState","encode","search","querystring","stringify","format","safeCharacterMap","base64url","_safe_map","times","random","length","join","codeChallenge","setItem","token","uuid","v4","sessionToken","oneFlight"],"mappings":"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","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';\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 * 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 }\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\n const {emailhash} = location.query.state;\n\n this._verifySecurityToken(location.query);\n this._cleanUrl(location);\n\n // Wait until nextTick in case `credentials` hasn't initialized yet\n process.nextTick(() => {\n this.webex.internal.services.collectPreauthCatalog({emailhash})\n .catch(() => Promise.resolve())\n .then(() => this.requestAuthorizationCodeGrant({code, codeVerifier}))\n .then(() => {\n this.ready = true;\n });\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\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(Object.assign({response_type: 'code'}, options));\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\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.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 * 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 }\n else {\n location.query.state = base64.encode(JSON.stringify(omit(location.query.state, 'csrf_token')));\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.times(\n 128,\n () => 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(\n OAUTH2_CODE_VERIFIER, codeVerifier\n );\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"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webex/plugin-authorization-browser-first-party",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.151.2",
|
|
4
4
|
"description": "",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Ian W. Remmel <iremmel@cisco.com>",
|
|
@@ -17,9 +17,9 @@
|
|
|
17
17
|
},
|
|
18
18
|
"dependencies": {
|
|
19
19
|
"@babel/runtime-corejs2": "^7.14.8",
|
|
20
|
-
"@webex/webex-core": "1.
|
|
20
|
+
"@webex/webex-core": "1.151.2",
|
|
21
21
|
"lodash": "^4.17.21",
|
|
22
|
-
"@webex/common": "1.
|
|
22
|
+
"@webex/common": "1.151.2",
|
|
23
23
|
"uuid": "^3.3.2",
|
|
24
24
|
"crypto-js": "^4.1.1",
|
|
25
25
|
"envify": "^4.1.0"
|
package/src/authorization.js
CHANGED
|
@@ -100,14 +100,14 @@ const Authorization = WebexPlugin.extend({
|
|
|
100
100
|
this.webex.getWindow().sessionStorage.removeItem(OAUTH2_CODE_VERIFIER);
|
|
101
101
|
|
|
102
102
|
|
|
103
|
-
const {
|
|
103
|
+
const {emailhash} = location.query.state;
|
|
104
104
|
|
|
105
105
|
this._verifySecurityToken(location.query);
|
|
106
106
|
this._cleanUrl(location);
|
|
107
107
|
|
|
108
108
|
// Wait until nextTick in case `credentials` hasn't initialized yet
|
|
109
109
|
process.nextTick(() => {
|
|
110
|
-
this.webex.internal.services.collectPreauthCatalog({
|
|
110
|
+
this.webex.internal.services.collectPreauthCatalog({emailhash})
|
|
111
111
|
.catch(() => Promise.resolve())
|
|
112
112
|
.then(() => this.requestAuthorizationCodeGrant({code, codeVerifier}))
|
|
113
113
|
.then(() => {
|
|
@@ -127,9 +127,15 @@ const Authorization = WebexPlugin.extend({
|
|
|
127
127
|
* @returns {Promise}
|
|
128
128
|
*/
|
|
129
129
|
initiateLogin(options = {}) {
|
|
130
|
+
options = cloneDeep(options);
|
|
131
|
+
if (options.email) {
|
|
132
|
+
options.emailHash = CryptoJS.SHA256(options.email).toString();
|
|
133
|
+
}
|
|
134
|
+
delete options.email;
|
|
130
135
|
options.state = options.state || {};
|
|
131
136
|
options.state.csrf_token = this._generateSecurityToken();
|
|
132
|
-
|
|
137
|
+
// catalog uses emailhash and redirectCI uses emailHash
|
|
138
|
+
options.state.emailhash = options.emailHash;
|
|
133
139
|
|
|
134
140
|
options.code_challenge = this._generateCodeChallenge();
|
|
135
141
|
options.code_challenge_method = 'S256';
|
|
@@ -259,6 +259,27 @@ browserOnly(describe)('plugin-authorization-browser-first-party', () => {
|
|
|
259
259
|
});
|
|
260
260
|
});
|
|
261
261
|
|
|
262
|
+
it('adds emailHash', () => {
|
|
263
|
+
const webex = makeWebex(undefined, undefined, {
|
|
264
|
+
credentials: {
|
|
265
|
+
clientType: 'confidential'
|
|
266
|
+
}
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
const expectedEmailHash = '73062d872926c2a556f17b36f50e328ddf9bff9d403939bd14b6c3b7f5a33fc2';
|
|
270
|
+
|
|
271
|
+
sinon.spy(webex.authorization, 'initiateAuthorizationCodeGrant');
|
|
272
|
+
|
|
273
|
+
return webex.authorization.initiateLogin({email: 'test@email.com'})
|
|
274
|
+
.then(() => {
|
|
275
|
+
assert.called(webex.authorization.initiateAuthorizationCodeGrant);
|
|
276
|
+
const grantOptions = webex.authorization.initiateAuthorizationCodeGrant.getCall(0).args[0];
|
|
277
|
+
|
|
278
|
+
assert.equal(grantOptions.emailHash, expectedEmailHash);
|
|
279
|
+
assert.isUndefined(grantOptions.email);
|
|
280
|
+
});
|
|
281
|
+
});
|
|
282
|
+
|
|
262
283
|
it('sets #isAuthorizing', () => {
|
|
263
284
|
const webex = makeWebex(undefined, undefined, {
|
|
264
285
|
credentials: {
|