@webex/plugin-authorization-browser 3.0.0-beta.14 → 3.0.0-beta.15

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.
@@ -396,7 +396,7 @@ var Authorization = _webexCore.WebexPlugin.extend((_dec = (0, _common.whileInFli
396
396
  throw new Error("CSRF token ".concat(token, " does not match stored token ").concat(sessionToken));
397
397
  }
398
398
  },
399
- version: "3.0.0-beta.14"
399
+ version: "3.0.0-beta.15"
400
400
  }, ((0, _applyDecoratedDescriptor2.default)(_obj, "initiateImplicitGrant", [_dec], (0, _getOwnPropertyDescriptor.default)(_obj, "initiateImplicitGrant"), _obj), (0, _applyDecoratedDescriptor2.default)(_obj, "initiateAuthorizationCodeGrant", [_dec2], (0, _getOwnPropertyDescriptor.default)(_obj, "initiateAuthorizationCodeGrant"), _obj), (0, _applyDecoratedDescriptor2.default)(_obj, "requestAccessTokenFromJwt", [_common.oneFlight], (0, _getOwnPropertyDescriptor.default)(_obj, "requestAccessTokenFromJwt"), _obj)), _obj)));
401
401
 
402
402
  var _default = Authorization;
@@ -1 +1 @@
1
- {"version":3,"names":["OAUTH2_CSRF_TOKEN","EMPTY_OBJECT_STRING","base64","encode","Authorization","WebexPlugin","extend","whileInFlight","derived","isAuthenticating","deps","fn","isAuthorizing","session","default","type","ready","namespace","initialize","attrs","options","ret","prototype","parse","location","url","webex","getWindow","href","_checkForErrors","hash","includes","substr","querystring","state","JSON","decode","tokenData","_parseHash","_cleanUrl","process","nextTick","credentials","set","supertoken","initiateLogin","csrf_token","_generateSecurityToken","config","clientType","initiateAuthorizationCodeGrant","initiateImplicitGrant","logger","info","buildLoginUrl","response_type","resolve","requestAccessTokenFromJwt","jwt","hydraUri","internal","services","get","slice","env","HYDRA_SERVICE_URL","request","method","uri","headers","authorization","then","body","access_token","token","token_type","expires_in","expiresIn","initServiceCatalogs","logout","noRedirect","buildLogoutUrl","query","error","ErrorConstructor","grantErrors","select","history","replaceState","forEach","key","stringify","format","uuid","v4","sessionStorage","setItem","_verifySecurityToken","undefined","refresh_token_expires_in","sessionToken","getItem","removeItem","Error","oneFlight"],"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';\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';\n\nconst OAUTH2_CSRF_TOKEN = 'oauth2-csrf-token';\nconst EMPTY_OBJECT_STRING = base64.encode(JSON.stringify({}));\n\n/**\n * Browser support for OAuth2. Automatically parses the URL hash for an access\n * token\n * @class\n * @name AuthorizationBrowser\n */\nconst Authorization = WebexPlugin.extend({\n derived: {\n /**\n * Alias of {@link AuthorizationBrowser#isAuthorizing}\n * @instance\n * @memberof AuthorizationBrowser\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 AuthorizationBrowser\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 AuthorizationBrowser\n * @param {Object} attrs {@link AmpersandState}\n * @param {boolean} attrs.parse Controls whether or not the the url should get\n * parsed for an access token\n * @private\n * @returns {Authorization}\n */\n // eslint-disable-next-line complexity\n initialize(attrs, options) {\n const ret = Reflect.apply(WebexPlugin.prototype.initialize, this, [attrs, options]);\n\n // Reminder, we can't do parse based on config, because config is not\n // available until nextTick and we want to be able to throw errors found in\n // the url.\n if (attrs.parse === false) {\n this.ready = true;\n\n return ret;\n }\n const location = url.parse(this.webex.getWindow().location.href, true);\n\n this._checkForErrors(location);\n\n let {hash} = location;\n\n if (!hash) {\n this.ready = true;\n\n return ret;\n }\n if (hash.includes('#')) {\n hash = hash.substr(1);\n }\n location.hash = querystring.parse(hash);\n if (location.hash.state) {\n location.hash.state = JSON.parse(base64.decode(location.hash.state));\n }\n const tokenData = this._parseHash(location);\n\n if (!tokenData) {\n return ret;\n }\n this._cleanUrl(location);\n\n // Wait until nextTick in case `credentials` hasn't initialized yet\n process.nextTick(() => {\n this.webex.credentials.set({supertoken: tokenData});\n this.ready = true;\n });\n\n return ret;\n },\n\n /**\n * Kicks off an oauth flow\n * @instance\n * @memberof AuthorizationBrowser\n * @param {Object} options\n * @returns {Promise}\n */\n initiateLogin(options = {}) {\n options.state = options.state || {};\n options.state.csrf_token = this._generateSecurityToken();\n\n // If we're not explicitly a confidential client, assume we're a public\n // client\n if (this.config.clientType === 'confidential') {\n return this.initiateAuthorizationCodeGrant(options);\n }\n\n return this.initiateImplicitGrant(options);\n },\n\n @whileInFlight('isAuthorizing')\n /**\n * Kicks off the Authorization Code grant flow. Typically called via\n * {@link AuthorizationBrowser#initiateLogin}\n * @instance\n * @memberof AuthorizationBrowser\n * @param {Object} options\n * @returns {Promise}\n */\n initiateImplicitGrant(options) {\n this.logger.info('authorization: initiating implicit grant flow');\n this.webex.getWindow().location = this.webex.credentials.buildLoginUrl(Object.assign({response_type: 'token'}, options));\n\n return Promise.resolve();\n },\n\n @whileInFlight('isAuthorizing')\n /**\n * Kicks off the Implicit Code grant flow. Typically called via\n * {@link AuthorizationBrowser#initiateLogin}\n * @instance\n * @memberof AuthorizationBrowser\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 @oneFlight\n /**\n * Requests a Webex access token for a user already authenticated into\n * your product.\n *\n * Note: You'll need to supply a jwtRefreshCallback of the form\n * `Promise<jwt> = jwtRefreshCallback(webex)` for automatic token refresh to\n * work.\n *\n * @instance\n * @memberof AuthorizationBrowser\n * @param {Object} options\n * @param {Object} options.jwt This is a jwt generated by your backend that\n * identifies a user in your system\n * @returns {Promise}\n */\n requestAccessTokenFromJwt({jwt}) {\n let hydraUri = this.webex.internal.services.get('hydra', true);\n\n if (hydraUri && hydraUri.slice(-1) !== '/') {\n // add a `/` to hydra's uri from the services catalog so that\n // it matches the current env service format.\n hydraUri += '/';\n }\n\n hydraUri = hydraUri ||\n process.env.HYDRA_SERVICE_URL ||\n 'https://api.ciscospark.com/v1/';\n\n return this.webex.request({\n method: 'POST',\n uri: `${hydraUri}jwt/login`,\n headers: {\n authorization: jwt\n }\n })\n .then(({body}) => ({\n access_token: body.token,\n token_type: 'Bearer',\n expires_in: body.expiresIn\n }))\n .then((token) => {\n this.webex.credentials.set({\n supertoken: token\n });\n })\n .then(() => this.webex.internal.services.initServiceCatalogs());\n },\n\n /**\n * Called by {@link WebexCore#logout()}. Redirects to the logout page\n * @instance\n * @memberof AuthorizationBrowser\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 * Checks if the result of the login redirect contains an error string\n * @instance\n * @memberof AuthorizationBrowser\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 AuthorizationBrowser\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 [\n 'access_token',\n 'token_type',\n 'expires_in',\n 'refresh_token',\n 'refresh_token_expires_in'\n ].forEach((key) => Reflect.deleteProperty(location.hash, key));\n if (!isEmpty(location.hash.state)) {\n location.hash.state = base64.encode(JSON.stringify(omit(location.hash.state, 'csrf_token')));\n if (location.hash.state === EMPTY_OBJECT_STRING) {\n Reflect.deleteProperty(location.hash, 'state');\n }\n }\n else {\n Reflect.deleteProperty(location.hash, 'state');\n }\n location.hash = querystring.stringify(location.hash);\n this.webex.getWindow().history.replaceState({}, null, url.format(location));\n }\n },\n\n /**\n * Generates a CSRF token and sticks in in sessionStorage\n * @instance\n * @memberof AuthorizationBrowser\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 * Parses the url hash into an access token object\n * @instance\n * @memberof AuthorizationBrowser\n * @param {Object} location\n * @private\n * @returns {Object}\n */\n _parseHash(location) {\n const hash = cloneDeep(location.hash);\n\n if (hash) {\n this._verifySecurityToken(hash);\n }\n if (!hash.access_token) {\n this.ready = true;\n\n return undefined;\n }\n if (hash.expires_in) {\n hash.expires_in = parseInt(hash.expires_in, 10);\n }\n if (hash.refresh_token_expires_in) {\n hash.refresh_token_expires_in = parseInt(hash.refresh_token_expires_in, 10);\n }\n\n return hash;\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 AuthorizationBrowser\n * @param {Object} hash\n * @private\n * @returns {Promise}\n */\n _verifySecurityToken(hash) {\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 (!hash.state) {\n throw new Error(`Expected CSRF token ${sessionToken}, but not found in redirect hash`);\n }\n\n if (!hash.state.csrf_token) {\n throw new Error(`Expected CSRF token ${sessionToken}, but not found in redirect hash`);\n }\n\n const token = hash.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":["OAUTH2_CSRF_TOKEN","EMPTY_OBJECT_STRING","base64","encode","Authorization","WebexPlugin","extend","whileInFlight","derived","isAuthenticating","deps","fn","isAuthorizing","session","default","type","ready","namespace","initialize","attrs","options","ret","prototype","parse","location","url","webex","getWindow","href","_checkForErrors","hash","includes","substr","querystring","state","JSON","decode","tokenData","_parseHash","_cleanUrl","process","nextTick","credentials","set","supertoken","initiateLogin","csrf_token","_generateSecurityToken","config","clientType","initiateAuthorizationCodeGrant","initiateImplicitGrant","logger","info","buildLoginUrl","response_type","resolve","requestAccessTokenFromJwt","jwt","hydraUri","internal","services","get","slice","env","HYDRA_SERVICE_URL","request","method","uri","headers","authorization","then","body","access_token","token","token_type","expires_in","expiresIn","initServiceCatalogs","logout","noRedirect","buildLogoutUrl","query","error","ErrorConstructor","grantErrors","select","history","replaceState","forEach","key","stringify","format","uuid","v4","sessionStorage","setItem","_verifySecurityToken","undefined","refresh_token_expires_in","sessionToken","getItem","removeItem","Error","oneFlight"],"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';\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';\n\nconst OAUTH2_CSRF_TOKEN = 'oauth2-csrf-token';\nconst EMPTY_OBJECT_STRING = base64.encode(JSON.stringify({}));\n\n/**\n * Browser support for OAuth2. Automatically parses the URL hash for an access\n * token\n * @class\n * @name AuthorizationBrowser\n */\nconst Authorization = WebexPlugin.extend({\n derived: {\n /**\n * Alias of {@link AuthorizationBrowser#isAuthorizing}\n * @instance\n * @memberof AuthorizationBrowser\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 AuthorizationBrowser\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 AuthorizationBrowser\n * @param {Object} attrs {@link AmpersandState}\n * @param {boolean} attrs.parse Controls whether or not the the url should get\n * parsed for an access token\n * @private\n * @returns {Authorization}\n */\n // eslint-disable-next-line complexity\n initialize(attrs, options) {\n const ret = Reflect.apply(WebexPlugin.prototype.initialize, this, [attrs, options]);\n\n // Reminder, we can't do parse based on config, because config is not\n // available until nextTick and we want to be able to throw errors found in\n // the url.\n if (attrs.parse === false) {\n this.ready = true;\n\n return ret;\n }\n const location = url.parse(this.webex.getWindow().location.href, true);\n\n this._checkForErrors(location);\n\n let {hash} = location;\n\n if (!hash) {\n this.ready = true;\n\n return ret;\n }\n if (hash.includes('#')) {\n hash = hash.substr(1);\n }\n location.hash = querystring.parse(hash);\n if (location.hash.state) {\n location.hash.state = JSON.parse(base64.decode(location.hash.state));\n }\n const tokenData = this._parseHash(location);\n\n if (!tokenData) {\n return ret;\n }\n this._cleanUrl(location);\n\n // Wait until nextTick in case `credentials` hasn't initialized yet\n process.nextTick(() => {\n this.webex.credentials.set({supertoken: tokenData});\n this.ready = true;\n });\n\n return ret;\n },\n\n /**\n * Kicks off an oauth flow\n * @instance\n * @memberof AuthorizationBrowser\n * @param {Object} options\n * @returns {Promise}\n */\n initiateLogin(options = {}) {\n options.state = options.state || {};\n options.state.csrf_token = this._generateSecurityToken();\n\n // If we're not explicitly a confidential client, assume we're a public\n // client\n if (this.config.clientType === 'confidential') {\n return this.initiateAuthorizationCodeGrant(options);\n }\n\n return this.initiateImplicitGrant(options);\n },\n\n @whileInFlight('isAuthorizing')\n /**\n * Kicks off the Authorization Code grant flow. Typically called via\n * {@link AuthorizationBrowser#initiateLogin}\n * @instance\n * @memberof AuthorizationBrowser\n * @param {Object} options\n * @returns {Promise}\n */\n initiateImplicitGrant(options) {\n this.logger.info('authorization: initiating implicit grant flow');\n this.webex.getWindow().location = this.webex.credentials.buildLoginUrl(\n Object.assign({response_type: 'token'}, options)\n );\n\n return Promise.resolve();\n },\n\n @whileInFlight('isAuthorizing')\n /**\n * Kicks off the Implicit Code grant flow. Typically called via\n * {@link AuthorizationBrowser#initiateLogin}\n * @instance\n * @memberof AuthorizationBrowser\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 @oneFlight\n /**\n * Requests a Webex access token for a user already authenticated into\n * your product.\n *\n * Note: You'll need to supply a jwtRefreshCallback of the form\n * `Promise<jwt> = jwtRefreshCallback(webex)` for automatic token refresh to\n * work.\n *\n * @instance\n * @memberof AuthorizationBrowser\n * @param {Object} options\n * @param {Object} options.jwt This is a jwt generated by your backend that\n * identifies a user in your system\n * @returns {Promise}\n */\n requestAccessTokenFromJwt({jwt}) {\n let hydraUri = this.webex.internal.services.get('hydra', true);\n\n if (hydraUri && hydraUri.slice(-1) !== '/') {\n // add a `/` to hydra's uri from the services catalog so that\n // it matches the current env service format.\n hydraUri += '/';\n }\n\n hydraUri = hydraUri || process.env.HYDRA_SERVICE_URL || 'https://api.ciscospark.com/v1/';\n\n return this.webex\n .request({\n method: 'POST',\n uri: `${hydraUri}jwt/login`,\n headers: {\n authorization: jwt,\n },\n })\n .then(({body}) => ({\n access_token: body.token,\n token_type: 'Bearer',\n expires_in: body.expiresIn,\n }))\n .then((token) => {\n this.webex.credentials.set({\n supertoken: token,\n });\n })\n .then(() => this.webex.internal.services.initServiceCatalogs());\n },\n\n /**\n * Called by {@link WebexCore#logout()}. Redirects to the logout page\n * @instance\n * @memberof AuthorizationBrowser\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 * Checks if the result of the login redirect contains an error string\n * @instance\n * @memberof AuthorizationBrowser\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 AuthorizationBrowser\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 [\n 'access_token',\n 'token_type',\n 'expires_in',\n 'refresh_token',\n 'refresh_token_expires_in',\n ].forEach((key) => Reflect.deleteProperty(location.hash, key));\n if (!isEmpty(location.hash.state)) {\n location.hash.state = base64.encode(\n JSON.stringify(omit(location.hash.state, 'csrf_token'))\n );\n if (location.hash.state === EMPTY_OBJECT_STRING) {\n Reflect.deleteProperty(location.hash, 'state');\n }\n } else {\n Reflect.deleteProperty(location.hash, 'state');\n }\n location.hash = querystring.stringify(location.hash);\n this.webex.getWindow().history.replaceState({}, null, url.format(location));\n }\n },\n\n /**\n * Generates a CSRF token and sticks in in sessionStorage\n * @instance\n * @memberof AuthorizationBrowser\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 * Parses the url hash into an access token object\n * @instance\n * @memberof AuthorizationBrowser\n * @param {Object} location\n * @private\n * @returns {Object}\n */\n _parseHash(location) {\n const hash = cloneDeep(location.hash);\n\n if (hash) {\n this._verifySecurityToken(hash);\n }\n if (!hash.access_token) {\n this.ready = true;\n\n return undefined;\n }\n if (hash.expires_in) {\n hash.expires_in = parseInt(hash.expires_in, 10);\n }\n if (hash.refresh_token_expires_in) {\n hash.refresh_token_expires_in = parseInt(hash.refresh_token_expires_in, 10);\n }\n\n return hash;\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 AuthorizationBrowser\n * @param {Object} hash\n * @private\n * @returns {Promise}\n */\n _verifySecurityToken(hash) {\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 (!hash.state) {\n throw new Error(`Expected CSRF token ${sessionToken}, but not found in redirect hash`);\n }\n\n if (!hash.state.csrf_token) {\n throw new Error(`Expected CSRF token ${sessionToken}, but not found in redirect hash`);\n }\n\n const token = hash.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 +1 @@
1
- {"version":3,"names":["credentials","clientType"],"sources":["config.js"],"sourcesContent":["/*!\n * Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.\n */\n\nexport default {\n credentials: {\n /**\n * Controls whether {@link Authorization#initiateLogin()} requests a token\n * or an auth code. Anything other than 'confidential' will be treated as\n * 'public'\n * @private\n * @type {string}\n */\n clientType: 'public'\n }\n};\n"],"mappings":";;;;;;;;;;AAAA;AACA;AACA;eAEe;EACbA,WAAW,EAAE;IACX;AACJ;AACA;AACA;AACA;AACA;AACA;IACIC,UAAU,EAAE;EARD;AADA,C"}
1
+ {"version":3,"names":["credentials","clientType"],"sources":["config.js"],"sourcesContent":["/*!\n * Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.\n */\n\nexport default {\n credentials: {\n /**\n * Controls whether {@link Authorization#initiateLogin()} requests a token\n * or an auth code. Anything other than 'confidential' will be treated as\n * 'public'\n * @private\n * @type {string}\n */\n clientType: 'public',\n },\n};\n"],"mappings":";;;;;;;;;;AAAA;AACA;AACA;eAEe;EACbA,WAAW,EAAE;IACX;AACJ;AACA;AACA;AACA;AACA;AACA;IACIC,UAAU,EAAE;EARD;AADA,C"}
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"names":["proxies","registerPlugin","Authorization","config"],"sources":["index.js"],"sourcesContent":["/*!\n * Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.\n */\n\nimport '@webex/internal-plugin-device';\nimport {registerPlugin} from '@webex/webex-core';\n\nimport Authorization from './authorization';\nimport config from './config';\n\nconst proxies = [\n 'isAuthorizing',\n 'isAuthenticating'\n];\n\nregisterPlugin('authorization', Authorization, {\n config,\n proxies\n});\n\nexport {default} from './authorization';\nexport {default as config} from './config';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAIA;;AACA;;AAEA;;AACA;;AARA;AACA;AACA;AAQA,IAAMA,OAAO,GAAG,CACd,eADc,EAEd,kBAFc,CAAhB;AAKA,IAAAC,yBAAA,EAAe,eAAf,EAAgCC,sBAAhC,EAA+C;EAC7CC,MAAM,EAANA,eAD6C;EAE7CH,OAAO,EAAPA;AAF6C,CAA/C"}
1
+ {"version":3,"names":["proxies","registerPlugin","Authorization","config"],"sources":["index.js"],"sourcesContent":["/*!\n * Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.\n */\n\nimport '@webex/internal-plugin-device';\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} from './authorization';\nexport {default as config} from './config';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAIA;;AACA;;AAEA;;AACA;;AARA;AACA;AACA;AAQA,IAAMA,OAAO,GAAG,CAAC,eAAD,EAAkB,kBAAlB,CAAhB;AAEA,IAAAC,yBAAA,EAAe,eAAf,EAAgCC,sBAAhC,EAA+C;EAC7CC,MAAM,EAANA,eAD6C;EAE7CH,OAAO,EAAPA;AAF6C,CAA/C"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webex/plugin-authorization-browser",
3
- "version": "3.0.0-beta.14",
3
+ "version": "3.0.0-beta.15",
4
4
  "description": "",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",
@@ -20,22 +20,22 @@
20
20
  ]
21
21
  },
22
22
  "devDependencies": {
23
- "@webex/plugin-authorization-browser": "3.0.0-beta.14",
24
- "@webex/test-helper-appid": "3.0.0-beta.14",
25
- "@webex/test-helper-automation": "3.0.0-beta.14",
26
- "@webex/test-helper-chai": "3.0.0-beta.14",
27
- "@webex/test-helper-mocha": "3.0.0-beta.14",
28
- "@webex/test-helper-mock-webex": "3.0.0-beta.14",
29
- "@webex/test-helper-test-users": "3.0.0-beta.14",
23
+ "@webex/plugin-authorization-browser": "3.0.0-beta.15",
24
+ "@webex/test-helper-appid": "3.0.0-beta.15",
25
+ "@webex/test-helper-automation": "3.0.0-beta.15",
26
+ "@webex/test-helper-chai": "3.0.0-beta.15",
27
+ "@webex/test-helper-mocha": "3.0.0-beta.15",
28
+ "@webex/test-helper-mock-webex": "3.0.0-beta.15",
29
+ "@webex/test-helper-test-users": "3.0.0-beta.15",
30
30
  "sinon": "^9.2.4"
31
31
  },
32
32
  "dependencies": {
33
- "@webex/common": "3.0.0-beta.14",
34
- "@webex/internal-plugin-device": "3.0.0-beta.14",
35
- "@webex/plugin-authorization-node": "3.0.0-beta.14",
36
- "@webex/storage-adapter-local-storage": "3.0.0-beta.14",
37
- "@webex/storage-adapter-spec": "3.0.0-beta.14",
38
- "@webex/webex-core": "3.0.0-beta.14",
33
+ "@webex/common": "3.0.0-beta.15",
34
+ "@webex/internal-plugin-device": "3.0.0-beta.15",
35
+ "@webex/plugin-authorization-node": "3.0.0-beta.15",
36
+ "@webex/storage-adapter-local-storage": "3.0.0-beta.15",
37
+ "@webex/storage-adapter-spec": "3.0.0-beta.15",
38
+ "@webex/webex-core": "3.0.0-beta.15",
39
39
  "lodash": "^4.17.21",
40
40
  "uuid": "^3.3.2"
41
41
  }
@@ -33,8 +33,8 @@ const Authorization = WebexPlugin.extend({
33
33
  deps: ['isAuthorizing'],
34
34
  fn() {
35
35
  return this.isAuthorizing;
36
- }
37
- }
36
+ },
37
+ },
38
38
  },
39
39
 
40
40
  session: {
@@ -46,12 +46,12 @@ const Authorization = WebexPlugin.extend({
46
46
  */
47
47
  isAuthorizing: {
48
48
  default: false,
49
- type: 'boolean'
49
+ type: 'boolean',
50
50
  },
51
51
  ready: {
52
52
  default: false,
53
- type: 'boolean'
54
- }
53
+ type: 'boolean',
54
+ },
55
55
  },
56
56
 
57
57
  namespace: 'Credentials',
@@ -143,7 +143,9 @@ const Authorization = WebexPlugin.extend({
143
143
  */
144
144
  initiateImplicitGrant(options) {
145
145
  this.logger.info('authorization: initiating implicit grant flow');
146
- this.webex.getWindow().location = this.webex.credentials.buildLoginUrl(Object.assign({response_type: 'token'}, options));
146
+ this.webex.getWindow().location = this.webex.credentials.buildLoginUrl(
147
+ Object.assign({response_type: 'token'}, options)
148
+ );
147
149
 
148
150
  return Promise.resolve();
149
151
  },
@@ -159,7 +161,9 @@ const Authorization = WebexPlugin.extend({
159
161
  */
160
162
  initiateAuthorizationCodeGrant(options) {
161
163
  this.logger.info('authorization: initiating authorization code grant flow');
162
- this.webex.getWindow().location = this.webex.credentials.buildLoginUrl(Object.assign({response_type: 'code'}, options));
164
+ this.webex.getWindow().location = this.webex.credentials.buildLoginUrl(
165
+ Object.assign({response_type: 'code'}, options)
166
+ );
163
167
 
164
168
  return Promise.resolve();
165
169
  },
@@ -189,25 +193,24 @@ const Authorization = WebexPlugin.extend({
189
193
  hydraUri += '/';
190
194
  }
191
195
 
192
- hydraUri = hydraUri ||
193
- process.env.HYDRA_SERVICE_URL ||
194
- 'https://api.ciscospark.com/v1/';
196
+ hydraUri = hydraUri || process.env.HYDRA_SERVICE_URL || 'https://api.ciscospark.com/v1/';
195
197
 
196
- return this.webex.request({
197
- method: 'POST',
198
- uri: `${hydraUri}jwt/login`,
199
- headers: {
200
- authorization: jwt
201
- }
202
- })
198
+ return this.webex
199
+ .request({
200
+ method: 'POST',
201
+ uri: `${hydraUri}jwt/login`,
202
+ headers: {
203
+ authorization: jwt,
204
+ },
205
+ })
203
206
  .then(({body}) => ({
204
207
  access_token: body.token,
205
208
  token_type: 'Bearer',
206
- expires_in: body.expiresIn
209
+ expires_in: body.expiresIn,
207
210
  }))
208
211
  .then((token) => {
209
212
  this.webex.credentials.set({
210
- supertoken: token
213
+ supertoken: token,
211
214
  });
212
215
  })
213
216
  .then(() => this.webex.internal.services.initServiceCatalogs());
@@ -261,15 +264,16 @@ const Authorization = WebexPlugin.extend({
261
264
  'token_type',
262
265
  'expires_in',
263
266
  'refresh_token',
264
- 'refresh_token_expires_in'
267
+ 'refresh_token_expires_in',
265
268
  ].forEach((key) => Reflect.deleteProperty(location.hash, key));
266
269
  if (!isEmpty(location.hash.state)) {
267
- location.hash.state = base64.encode(JSON.stringify(omit(location.hash.state, 'csrf_token')));
270
+ location.hash.state = base64.encode(
271
+ JSON.stringify(omit(location.hash.state, 'csrf_token'))
272
+ );
268
273
  if (location.hash.state === EMPTY_OBJECT_STRING) {
269
274
  Reflect.deleteProperty(location.hash, 'state');
270
275
  }
271
- }
272
- else {
276
+ } else {
273
277
  Reflect.deleteProperty(location.hash, 'state');
274
278
  }
275
279
  location.hash = querystring.stringify(location.hash);
@@ -353,7 +357,7 @@ const Authorization = WebexPlugin.extend({
353
357
  if (token !== sessionToken) {
354
358
  throw new Error(`CSRF token ${token} does not match stored token ${sessionToken}`);
355
359
  }
356
- }
360
+ },
357
361
  });
358
362
 
359
363
  export default Authorization;
package/src/config.js CHANGED
@@ -11,6 +11,6 @@ export default {
11
11
  * @private
12
12
  * @type {string}
13
13
  */
14
- clientType: 'public'
15
- }
14
+ clientType: 'public',
15
+ },
16
16
  };
package/src/index.js CHANGED
@@ -8,14 +8,11 @@ import {registerPlugin} from '@webex/webex-core';
8
8
  import Authorization from './authorization';
9
9
  import config from './config';
10
10
 
11
- const proxies = [
12
- 'isAuthorizing',
13
- 'isAuthenticating'
14
- ];
11
+ const proxies = ['isAuthorizing', 'isAuthenticating'];
15
12
 
16
13
  registerPlugin('authorization', Authorization, {
17
14
  config,
18
- proxies
15
+ proxies,
19
16
  });
20
17
 
21
18
  export {default} from './authorization';
@@ -10,35 +10,37 @@ import WebexCore from '@webex/webex-core';
10
10
 
11
11
  import pkg from '../../../package';
12
12
 
13
- const webex = window.webex = new WebexCore({
13
+ const webex = (window.webex = new WebexCore({
14
14
  config: {
15
15
  credentials: {
16
16
  refreshCallback(webex, token) {
17
- return webex.request({
18
- method: 'POST',
19
- uri: '/refresh',
20
- body: {
21
- // eslint-disable-next-line camelcase
22
- refresh_token: token.refresh_token
23
- }
24
- })
17
+ return webex
18
+ .request({
19
+ method: 'POST',
20
+ uri: '/refresh',
21
+ body: {
22
+ // eslint-disable-next-line camelcase
23
+ refresh_token: token.refresh_token,
24
+ },
25
+ })
25
26
  .then((res) => res.body);
26
- }
27
+ },
27
28
  },
28
29
  storage: {
29
- boundedAdapter: new StorageAdapterLocalStorage('webex')
30
- }
31
- }
32
- });
30
+ boundedAdapter: new StorageAdapterLocalStorage('webex'),
31
+ },
32
+ },
33
+ }));
33
34
 
34
35
  webex.once('ready', () => {
35
36
  if (webex.canAuthorize) {
36
37
  document.getElementById('access-token').innerHTML = webex.credentials.supertoken.access_token;
37
38
  document.getElementById('refresh-token').innerHTML = webex.credentials.supertoken.refresh_token;
38
39
 
39
- webex.request({
40
- uri: 'https://locus-a.wbx2.com/locus/api/v1/ping'
41
- })
40
+ webex
41
+ .request({
42
+ uri: 'https://locus-a.wbx2.com/locus/api/v1/ping',
43
+ })
42
44
  .then(() => {
43
45
  document.getElementById('ping-complete').innerHTML = 'success';
44
46
  });
@@ -50,24 +52,23 @@ document.body.classList.add('ready');
50
52
 
51
53
  document.getElementById('initiate-implicit-grant').addEventListener('click', () => {
52
54
  webex.authorization.initiateLogin({
53
- state: {name: pkg.name}
55
+ state: {name: pkg.name},
54
56
  });
55
57
  });
56
58
 
57
59
  document.getElementById('initiate-authorization-code-grant').addEventListener('click', () => {
58
60
  webex.config.credentials.clientType = 'confidential';
59
61
  webex.authorization.initiateLogin({
60
- state: {name: pkg.name}
62
+ state: {name: pkg.name},
61
63
  });
62
64
  });
63
65
 
64
66
  document.getElementById('token-refresh').addEventListener('click', () => {
65
67
  document.getElementById('access-token').innerHTML = '';
66
- webex.refresh({force: true})
67
- .then(() => {
68
- document.getElementById('access-token').innerHTML = webex.credentials.supertoken.access_token;
69
- document.getElementById('refresh-token').innerHTML = webex.credentials.supertoken.refresh_token;
70
- });
68
+ webex.refresh({force: true}).then(() => {
69
+ document.getElementById('access-token').innerHTML = webex.credentials.supertoken.access_token;
70
+ document.getElementById('refresh-token').innerHTML = webex.credentials.supertoken.refresh_token;
71
+ });
71
72
  });
72
73
 
73
74
  document.getElementById('logout').addEventListener('click', () => {
@@ -1,22 +1,27 @@
1
1
  <!DOCTYPE html>
2
2
  <html>
3
- <head>
4
- <title>Authorization Automation Test</title>
5
- </head>
6
- <body class="authorization-automation-test">
7
- <button title="Login with Implicit Grant" id="initiate-implicit-grant">Login with Implicit Grant</button>
8
- <button title="Login with Authorization Code Grant" id="initiate-authorization-code-grant">Login with Authorization Code Grant</button>
9
- <button title="Refresh Access Token" id="token-refresh">Refresh Access Token</button>
3
+ <head>
4
+ <title>Authorization Automation Test</title>
5
+ </head>
6
+ <body class="authorization-automation-test">
7
+ <button title="Login with Implicit Grant" id="initiate-implicit-grant">
8
+ Login with Implicit Grant
9
+ </button>
10
+ <button title="Login with Authorization Code Grant" id="initiate-authorization-code-grant">
11
+ Login with Authorization Code Grant
12
+ </button>
13
+ <button title="Refresh Access Token" id="token-refresh">Refresh Access Token</button>
10
14
 
11
- <h1>Access Token</h1>
12
- <div id="access-token"></div>
13
- <h1>Refresh Token</h1>
14
- <div id="refresh-token"></div>
15
+ <h1>Access Token</h1>
16
+ <div id="access-token"></div>
17
+ <h1>Refresh Token</h1>
18
+ <div id="refresh-token"></div>
15
19
 
16
- <h1>Pinging WDM</h1>
17
- <div id="ping-complete"></div>
20
+ <h1>Pinging WDM</h1>
21
+ <div id="ping-complete"></div>
18
22
 
19
- <button title="Logout" id="logout">Logout</button>
23
+ <button title="Logout" id="logout">Logout</button>
20
24
 
21
- <script src="app.js"></script>
22
- </body>
25
+ <script src="app.js"></script>
26
+ </body>
27
+ </html>
@@ -18,98 +18,106 @@ describe('plugin-authorization-browser', function () {
18
18
  describe.skip('Authorization Code Grant', () => {
19
19
  let browser, user;
20
20
 
21
- before(() => testUsers.create({count: 1})
22
- .then((users) => {
21
+ before(() =>
22
+ testUsers.create({count: 1}).then((users) => {
23
23
  user = users[0];
24
- }));
24
+ })
25
+ );
25
26
 
26
- before(() => createBrowser(pkg)
27
- .then((b) => {
27
+ before(() =>
28
+ createBrowser(pkg).then((b) => {
28
29
  browser = b;
29
- }));
30
+ })
31
+ );
30
32
 
31
33
  after(() => browser && browser.printLogs());
32
34
 
33
- after(() => browser && browser.quit()
34
- .catch((reason) => {
35
- console.warn(reason);
36
- }));
37
-
38
- it('authorizes a user', () => browser
39
- .get(`${redirectUri}/${pkg.name}`)
40
- .waitForElementByClassName('ready')
41
- .title()
35
+ after(
36
+ () =>
37
+ browser &&
38
+ browser.quit().catch((reason) => {
39
+ console.warn(reason);
40
+ })
41
+ );
42
+
43
+ it('authorizes a user', () =>
44
+ browser
45
+ .get(`${redirectUri}/${pkg.name}`)
46
+ .waitForElementByClassName('ready')
47
+ .title()
42
48
  .should.eventually.become('Authorization Automation Test')
43
- .waitForElementByCssSelector('[title="Login with Authorization Code Grant"]')
49
+ .waitForElementByCssSelector('[title="Login with Authorization Code Grant"]')
44
50
  .click()
45
- .login(user)
46
- .waitForElementByClassName('authorization-automation-test')
47
- .waitForElementById('refresh-token')
51
+ .login(user)
52
+ .waitForElementByClassName('authorization-automation-test')
53
+ .waitForElementById('refresh-token')
48
54
  .text()
49
- .should.eventually.not.be.empty
50
- .waitForElementByCssSelector('#ping-complete:not(:empty)')
55
+ .should.eventually.not.be.empty.waitForElementByCssSelector('#ping-complete:not(:empty)')
51
56
  .text()
52
- .should.eventually.become('success'));
57
+ .should.eventually.become('success'));
53
58
 
54
- it('is still logged in after reloading the page', () => browser
55
- .waitForElementById('access-token')
56
- .text()
57
- .should.eventually.not.be.empty
58
- .get(`${redirectUri}/${pkg.name}`)
59
- .sleep(500)
60
- .waitForElementById('access-token')
59
+ it('is still logged in after reloading the page', () =>
60
+ browser
61
+ .waitForElementById('access-token')
61
62
  .text()
62
- .should.eventually.not.be.empty);
63
+ .should.eventually.not.be.empty.get(`${redirectUri}/${pkg.name}`)
64
+ .sleep(500)
65
+ .waitForElementById('access-token')
66
+ .text().should.eventually.not.be.empty);
63
67
 
64
- it('refreshes the user\'s access token', () => {
68
+ it("refreshes the user's access token", () => {
65
69
  let accessToken = '';
66
70
 
67
- return browser
68
- .waitForElementByCssSelector('#access-token:not(:empty)')
71
+ return (
72
+ browser
73
+ .waitForElementByCssSelector('#access-token:not(:empty)')
69
74
  .text()
70
- .then((text) => {
71
- accessToken = text;
72
- assert.isString(accessToken);
73
- assert.isAbove(accessToken.length, 0);
74
-
75
- return browser;
76
- })
77
- .waitForElementByCssSelector('[title="Refresh Access Token"]')
75
+ .then((text) => {
76
+ accessToken = text;
77
+ assert.isString(accessToken);
78
+ assert.isAbove(accessToken.length, 0);
79
+
80
+ return browser;
81
+ })
82
+ .waitForElementByCssSelector('[title="Refresh Access Token"]')
78
83
  .click()
79
- // Not thrilled by a sleep, but we just need to give the button click
80
- // enough time to clear the #access-token box
81
- .sleep(500)
82
- .waitForElementByCssSelector('#access-token:not(:empty)')
84
+ // Not thrilled by a sleep, but we just need to give the button click
85
+ // enough time to clear the #access-token box
86
+ .sleep(500)
87
+ .waitForElementByCssSelector('#access-token:not(:empty)')
83
88
  .text()
84
- .then((text) => {
85
- assert.isString(text);
86
- assert.isAbove(text.length, 0);
87
- assert.notEqual(text, accessToken);
88
-
89
- return browser;
90
- });
89
+ .then((text) => {
90
+ assert.isString(text);
91
+ assert.isAbove(text.length, 0);
92
+ assert.notEqual(text, accessToken);
93
+
94
+ return browser;
95
+ })
96
+ );
91
97
  });
92
98
 
93
- it('logs out a user', () => browser
94
- .title()
99
+ it('logs out a user', () =>
100
+ browser
101
+ .title()
95
102
  .should.eventually.become('Authorization Automation Test')
96
- .waitForElementByCssSelector('[title="Logout"]')
103
+ .waitForElementByCssSelector('[title="Logout"]')
97
104
  .click()
98
- // We need to revoke three tokens before the window.location assignment.
99
- // So far, I haven't found any ques to wait for, so sleep seems to be
100
- // the only option.
101
- .sleep(3000)
102
- .title()
105
+ // We need to revoke three tokens before the window.location assignment.
106
+ // So far, I haven't found any ques to wait for, so sleep seems to be
107
+ // the only option.
108
+ .sleep(3000)
109
+ .title()
103
110
  .should.eventually.become('Redirect Dispatcher')
104
- .get(`${redirectUri}/${pkg.name}`)
105
- .title()
111
+ .get(`${redirectUri}/${pkg.name}`)
112
+ .title()
106
113
  .should.eventually.become('Authorization Automation Test')
107
- .waitForElementById('access-token')
114
+ .waitForElementById('access-token')
108
115
  .text()
109
- .should.eventually.be.empty
110
- .waitForElementByCssSelector('[title="Login with Authorization Code Grant"]')
116
+ .should.eventually.be.empty.waitForElementByCssSelector(
117
+ '[title="Login with Authorization Code Grant"]'
118
+ )
111
119
  .click()
112
- .waitForElementById('IDToken1'));
120
+ .waitForElementById('IDToken1'));
113
121
  });
114
122
  });
115
123
  });