@webex/plugin-authorization-browser-first-party 3.12.0-next.39 → 3.12.0-next.40
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +38 -7
- package/dist/authorization.js +56 -2
- package/dist/authorization.js.map +1 -1
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/authorization.js +63 -1
- package/src/index.js +1 -1
- package/test/unit/spec/authorization.js +85 -1
package/README.md
CHANGED
|
@@ -178,13 +178,44 @@ webex.authorization.initQRCodeLogin();
|
|
|
178
178
|
|
|
179
179
|
### Properties
|
|
180
180
|
|
|
181
|
-
| Property
|
|
182
|
-
|
|
|
183
|
-
| `
|
|
184
|
-
| `
|
|
185
|
-
| `
|
|
186
|
-
| `
|
|
187
|
-
| `
|
|
181
|
+
| Property | Type | Description |
|
|
182
|
+
| -------------------------------------- | ---------------- | --------------------------------------------------------- |
|
|
183
|
+
| `initialAuthorizationCodeGrantOutcome` | string | Retained outcome of the automatic initialization exchange |
|
|
184
|
+
| `isAuthorizing` | boolean | True while a grant request is in flight |
|
|
185
|
+
| `isAuthenticating` | boolean | Alias of `isAuthorizing` |
|
|
186
|
+
| `ready` | boolean | Set true after initial redirect/code processing completes |
|
|
187
|
+
| `eventEmitter` | EventEmitter | Emits QR/Device login lifecycle events |
|
|
188
|
+
| `Events` | enum-like object | Accessible names for event types |
|
|
189
|
+
|
|
190
|
+
#### Initial authorization-code grant outcome
|
|
191
|
+
|
|
192
|
+
```javascript
|
|
193
|
+
import {InitialAuthorizationCodeGrantOutcomes} from '@webex/plugin-authorization-browser-first-party';
|
|
194
|
+
|
|
195
|
+
const didInitialExchangeSucceed =
|
|
196
|
+
webex.authorization.initialAuthorizationCodeGrantOutcome ===
|
|
197
|
+
InitialAuthorizationCodeGrantOutcomes.success;
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
`initialAuthorizationCodeGrantOutcome` describes only the automatic
|
|
201
|
+
`requestAuthorizationCodeGrant()` call made while this authorization plugin
|
|
202
|
+
instance initializes. Read it after `ready`:
|
|
203
|
+
|
|
204
|
+
- `not_attempted`: initialization did not invoke the exchange.
|
|
205
|
+
- `success`: the initialization exchange fulfilled.
|
|
206
|
+
- `failure`: the initialization exchange threw or rejected.
|
|
207
|
+
|
|
208
|
+
The value is a historical result retained for the lifetime of the SDK instance
|
|
209
|
+
and is not reset by logout. It does not represent current authorization state
|
|
210
|
+
or credentials hydrated from storage. It also does not track guest or device
|
|
211
|
+
authentication, token refreshes, or authorization-code exchanges requested
|
|
212
|
+
later on the same SDK instance.
|
|
213
|
+
|
|
214
|
+
OAuth redirect errors and CSRF validation failures occur before the exchange,
|
|
215
|
+
so the value remains `not_attempted`; these errors can throw before `ready`
|
|
216
|
+
becomes `true`. A non-redirecting logout does not cancel an initialization
|
|
217
|
+
exchange already in flight. If that exchange later settles, it can still update
|
|
218
|
+
credentials and this retained outcome.
|
|
188
219
|
|
|
189
220
|
## Security Considerations
|
|
190
221
|
|
package/dist/authorization.js
CHANGED
|
@@ -5,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 = exports.Events = void 0;
|
|
8
|
+
exports.default = exports.InitialAuthorizationCodeGrantOutcomes = exports.Events = void 0;
|
|
9
9
|
var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/objectWithoutProperties"));
|
|
10
10
|
var _apply = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/reflect/apply"));
|
|
11
11
|
var _promise = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/promise"));
|
|
@@ -53,6 +53,18 @@ var Events = exports.Events = {
|
|
|
53
53
|
qRCodeLogin: 'qRCodeLogin'
|
|
54
54
|
};
|
|
55
55
|
|
|
56
|
+
/**
|
|
57
|
+
* Terminal outcomes for the automatic authorization-code exchange performed
|
|
58
|
+
* during authorization plugin initialization.
|
|
59
|
+
*
|
|
60
|
+
* @enum {string}
|
|
61
|
+
*/
|
|
62
|
+
var InitialAuthorizationCodeGrantOutcomes = exports.InitialAuthorizationCodeGrantOutcomes = {
|
|
63
|
+
failure: 'failure',
|
|
64
|
+
notAttempted: 'not_attempted',
|
|
65
|
+
success: 'success'
|
|
66
|
+
};
|
|
67
|
+
|
|
56
68
|
/**
|
|
57
69
|
* Browser support for OAuth2 for first-party (Webex Web Client) usage.
|
|
58
70
|
*
|
|
@@ -83,6 +95,37 @@ var Events = exports.Events = {
|
|
|
83
95
|
*/
|
|
84
96
|
var Authorization = _webexCore.WebexPlugin.extend((_dec = (0, _common.whileInFlight)('isAuthorizing'), _dec2 = (0, _common.whileInFlight)('isAuthorizing'), _obj = {
|
|
85
97
|
derived: {
|
|
98
|
+
/**
|
|
99
|
+
* Retains the terminal outcome of the automatic authorization-code exchange
|
|
100
|
+
* performed during this authorization plugin instance's initialization.
|
|
101
|
+
*
|
|
102
|
+
* This historical value does not represent current authorization state,
|
|
103
|
+
* credentials hydrated from storage, guest authentication, or
|
|
104
|
+
* authorization-code exchanges requested later on the same SDK instance. It
|
|
105
|
+
* is not reset by logout. OAuth redirect errors and CSRF validation failures
|
|
106
|
+
* occur before the exchange, so the value remains not_attempted; these errors
|
|
107
|
+
* can throw before ready becomes true.
|
|
108
|
+
*
|
|
109
|
+
* Calling logout({noRedirect: true}) does not cancel an initialization
|
|
110
|
+
* exchange already in flight. If that exchange later settles, it can still
|
|
111
|
+
* update credentials and this retained outcome.
|
|
112
|
+
*
|
|
113
|
+
* Interpret only after authorization readiness:
|
|
114
|
+
* - not_attempted: initialization did not invoke requestAuthorizationCodeGrant()
|
|
115
|
+
* - success: the initialization exchange fulfilled
|
|
116
|
+
* - failure: the initialization exchange threw or rejected
|
|
117
|
+
*
|
|
118
|
+
* @instance
|
|
119
|
+
* @memberof AuthorizationBrowserFirstParty
|
|
120
|
+
* @readonly
|
|
121
|
+
* @type {string}
|
|
122
|
+
*/
|
|
123
|
+
initialAuthorizationCodeGrantOutcome: {
|
|
124
|
+
deps: ['_initialAuthorizationCodeGrantOutcome'],
|
|
125
|
+
fn: function fn() {
|
|
126
|
+
return this._initialAuthorizationCodeGrantOutcome;
|
|
127
|
+
}
|
|
128
|
+
},
|
|
86
129
|
/**
|
|
87
130
|
* Alias of {@link AuthorizationBrowserFirstParty#isAuthorizing}
|
|
88
131
|
* @instance
|
|
@@ -107,6 +150,14 @@ var Authorization = _webexCore.WebexPlugin.extend((_dec = (0, _common.whileInFli
|
|
|
107
150
|
default: false,
|
|
108
151
|
type: 'boolean'
|
|
109
152
|
},
|
|
153
|
+
/**
|
|
154
|
+
* Internal backing state for the initial authorization-code grant outcome.
|
|
155
|
+
* @private
|
|
156
|
+
*/
|
|
157
|
+
_initialAuthorizationCodeGrantOutcome: {
|
|
158
|
+
default: InitialAuthorizationCodeGrantOutcomes.notAttempted,
|
|
159
|
+
type: 'string'
|
|
160
|
+
},
|
|
110
161
|
/**
|
|
111
162
|
* Indicates that the plugin has finished any automatic startup
|
|
112
163
|
* processing (e.g., exchanging a returned authorization code)
|
|
@@ -248,7 +299,10 @@ var Authorization = _webexCore.WebexPlugin.extend((_dec = (0, _common.whileInFli
|
|
|
248
299
|
code: code,
|
|
249
300
|
codeVerifier: codeVerifier
|
|
250
301
|
});
|
|
302
|
+
}).then(function () {
|
|
303
|
+
_this._initialAuthorizationCodeGrantOutcome = InitialAuthorizationCodeGrantOutcomes.success;
|
|
251
304
|
}).catch(function (error) {
|
|
305
|
+
_this._initialAuthorizationCodeGrantOutcome = InitialAuthorizationCodeGrantOutcomes.failure;
|
|
252
306
|
_this.logger.warn('authorization: failed initial authorization code grant request', error);
|
|
253
307
|
}).then(function () {
|
|
254
308
|
// Mark plugin ready regardless of success/failure of token exchange
|
|
@@ -899,7 +953,7 @@ var Authorization = _webexCore.WebexPlugin.extend((_dec = (0, _common.whileInFli
|
|
|
899
953
|
throw new Error("CSRF token ".concat(token, " does not match stored token ").concat(sessionToken));
|
|
900
954
|
}
|
|
901
955
|
},
|
|
902
|
-
version: "3.12.0-next.
|
|
956
|
+
version: "3.12.0-next.40"
|
|
903
957
|
}, (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));
|
|
904
958
|
var _default = exports.default = Authorization;
|
|
905
959
|
//# sourceMappingURL=authorization.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_querystring","_interopRequireDefault","require","_url2","_events","_common","_webexCore","_lodash","_uuid","_encBase64url","_cryptoJs","_excluded","_dec","_dec2","_obj","lodash","OAUTH2_CSRF_TOKEN","OAUTH2_CODE_VERIFIER","Events","exports","login","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","decodeState","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","emit","eventType","data","hasEmail","email","hasState","cloneDeep","emailHash","CryptoJS","SHA256","toString","csrf_token","_generateSecurityToken","code_challenge","_generateCodeChallenge","code_challenge_method","initiateAuthorizationCodeGrant","info","loginUrl","credentials","buildLoginUrl","_assign","response_type","separateWindow","defaultWindowSettings","width","height","windowSettings","_typeof2","windowFeatures","_entries","map","_ref","_ref2","_slicedToArray2","key","value","concat","join","open","initiateThirdPartyLogin","isObject","Error","initiateThirdPartyLoginRedirect","buildThirdPartyLoginUrl","err","reject","handleThirdPartyCallback","requireMatch","_location$query","idToken","id_token","_location$query$state","_objectWithoutProperties2","logout","noRedirect","buildLogoutUrl","_this2","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","_generateQRCodeVerificationUrl","verificationUrl","baseUrl","urlParams","URLSearchParams","URL","search","userCode","get","oauthHelperUrl","newVerificationUrl","searchParams","initQRCodeLogin","_this3","message","service","resource","scope","_res$body","user_code","verification_uri","verification_uri_complete","verificationUriComplete","userData","verificationUri","_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","encodeState","querystring","stringify","format","safeCharacterMap","base64url","_safe_map","times","random","codeChallenge","setItem","token","uuid","v4","_query$state","sessionToken","version","_applyDecoratedDescriptor2","_getOwnPropertyDescriptor","oneFlight","_default"],"sources":["authorization.js"],"sourcesContent":["// @ts-nocheck\n/* eslint-disable */\n/*!\n * Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.\n */\n\n/* eslint camelcase: [0] */\n/**\n * TS checking disabled: file uses legacy decorator syntax inside an object literal\n * transformed by Babel. Safe to ignore for now.\n */\n\nimport querystring from 'querystring';\nimport url from 'url';\nimport {EventEmitter} from 'events';\n\nimport {decodeState, encodeState, oneFlight, whileInFlight} from '@webex/common';\nimport {grantErrors, WebexPlugin} from '@webex/webex-core';\nimport {cloneDeep, isEmpty, omit, isObject} 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 login: 'login',\n /**\n * QR code login events\n */\n qRCodeLogin: 'qRCodeLogin',\n};\n\n/**\n * Browser support for OAuth2 for first-party (Webex Web Client) usage.\n *\n * High-level flow handled by this module:\n * 1. initiateLogin() constructs authorization request (adds CSRF + PKCE).\n * 2. Browser navigates to IdBroker (login).\n * 3. IdBroker redirects back with ?code=... (&state=...).\n * 4. initialize() detects code, validates state/CSRF, cleans URL, optionally\n * pre-fetches a preauth catalog, then exchanges the code via\n * requestAuthorizationCodeGrant().\n * 5. Sets resulting supertoken (access/refresh token bundle) on credentials.\n *\n * Additional supported flow:\n * - Device Authorization (QR Code login):\n * initQRCodeLogin() obtains device + user codes and begins polling\n * _startQRCodePolling() until tokens are issued or timeout/cancel occurs.\n *\n * Security considerations implemented:\n * - CSRF token (state.csrf_token) generation + verification.\n * - PKCE (S256) code verifier + challenge generation and consumption.\n * - URL cleanup after redirect (removes code & CSRF to prevent leakage).\n *\n * Use of this plugin for anything other than the Webex Web Client is discouraged.\n *\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 /**\n * Indicates that the plugin has finished any automatic startup\n * processing (e.g., exchanging a returned authorization code)\n */\n ready: {\n default: false,\n type: 'boolean',\n },\n },\n\n namespace: 'Credentials',\n\n /**\n * EventEmitter for authorization events such as QR code login progress\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 (device authorization)\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 (overall timeout)\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 * Used to safely ignore late poll responses after a cancel/reset.\n * @instance\n * @memberof AuthorizationBrowserFirstParty\n * @type {number}\n * @private\n */\n pollingId: 0,\n\n /**\n * Identifier for the current polling request (snapshot of pollingId)\n * @instance\n * @memberof AuthorizationBrowserFirstParty\n * @type {?number}\n * @private\n */\n currentPollingId: null,\n\n /**\n * Auto executes during Webex.init() – you do NOT call this yourself.\n *\n * Purpose: Seamless \"redirect completion\" of the OAuth Authorization Code (+ PKCE) flow.\n *\n * Simple summary:\n * - You call initiateLogin() which redirects user to IdBroker.\n * - User signs in; IdBroker redirects back to your redirect_uri with ?code=... (&state=...).\n * - During SDK startup this initialize() runs automatically, sees the code, and\n * silently finishes the login (validates state/CSRF + PKCE, scrubs URL, exchanges code).\n * - When done, webex.credentials.supertoken holds access+refresh and ready=true.\n *\n * Step-by-step:\n * 1. Inspect current window.location for ?code= (& state=).\n * 2. If no code: set ready=true immediately (nothing to complete).\n * 3. If code present:\n * - Decode base64 state JSON.\n * - Verify CSRF token matches sessionStorage value.\n * - Retrieve then delete PKCE code_verifier (single use).\n * - Optionally derive preauth hint (emailhash in state OR orgId parsed from code).\n * - Clean the URL (history.replaceState) to remove code & csrf token data.\n * - nextTick:\n * a. Best‑effort preauth catalog fetch (non-blocking).\n * b. Exchange authorization code (with code_verifier if any) for supertoken\n * and store on webex.credentials.\n * 4. Set ready=true after the async sequence finishes (or immediately if step 2).\n *\n * Result: If the redirect included a valid code the token exchange is completed\n * automatically—no extra API call needed after Webex.init().\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 // Check if redirect includes error\n this._checkForErrors(location);\n\n const {code} = location.query;\n\n // If no authorization code returned, nothing to do\n if (!code) {\n this.ready = true;\n return ret;\n }\n\n // Decode and parse state object (if present)\n if (location.query.state) {\n location.query.state = decodeState(location.query.state);\n } else {\n location.query.state = {};\n }\n\n // Retrieve PKCE code verifier (if a PKCE flow was initiated)\n const codeVerifier = this.webex.getWindow().sessionStorage.getItem(OAUTH2_CODE_VERIFIER);\n // Immediately remove code verifier to minimize exposure\n this.webex.getWindow().sessionStorage.removeItem(OAUTH2_CODE_VERIFIER);\n\n const {emailhash} = location.query.state;\n\n // Validate CSRF token included in state\n this._verifySecurityToken(location.query);\n // Remove code + CSRF token remnants from URL (history replace)\n this._cleanUrl(location);\n\n let preauthCatalogParams;\n\n // Attempt to extract orgId from structured authorization code (if present)\n const orgId = this._extractOrgIdFromCode(code);\n\n if (emailhash) {\n preauthCatalogParams = {emailhash};\n } else if (orgId) {\n preauthCatalogParams = {orgId};\n }\n\n // Defer token exchange until next tick in case credentials plugin not ready yet\n process.nextTick(() => {\n this.webex.internal.services\n .collectPreauthCatalog(preauthCatalogParams)\n .catch(() => Promise.resolve()) // Non-fatal if catalog collection fails\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 // Mark plugin ready regardless of success/failure of token exchange\n this.ready = true;\n });\n });\n\n return ret;\n },\n\n /**\n * Kicks off an OAuth authorization code flow (first party).\n *\n * Adds security + PKCE properties:\n * - SHA256(email) (emailHash & emailhash) for preauth and redirect flows\n * - state.csrf_token for CSRF protection\n * - PKCE code_challenge (S256)\n *\n * NOTE: This does not itself perform the redirect; it calls\n * initiateAuthorizationCodeGrant() which changes window location or opens\n * a separate window as configured.\n *\n * @instance\n * @memberof AuthorizationBrowserFirstParty\n * @param {Object} options\n * @returns {Promise}\n */\n initiateLogin(options = {}) {\n this.eventEmitter.emit(Events.login, {\n eventType: 'initiateLogin',\n data: {\n hasEmail: !!options.email,\n hasState: !!options.state,\n },\n });\n\n options = cloneDeep(options);\n\n // Optionally compute heuristic email hash for preauth usage\n if (options.email) {\n options.emailHash = CryptoJS.SHA256(options.email).toString();\n }\n delete options.email; // Ensure raw email not propagated further\n\n options.state = options.state || {};\n // Embed CSRF token\n options.state.csrf_token = this._generateSecurityToken();\n // Provide email hash in lower-case key used by catalog service\n // (Note: catalog uses emailhash and redirectCI uses emailHash)\n options.state.emailhash = options.emailHash;\n\n // PKCE - produce code_challenge (S256) and persist code_verifier\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 * Performs the navigation step of the Authorization Code flow.\n * Builds login URL and either:\n * - Replaces current window location (default), or\n * - Opens a separate window (popup) if options.separateWindow supplied.\n *\n * Decorated with whileInFlight('isAuthorizing') to set isAuthorizing=true\n * during execution to prevent concurrent overlapping attempts.\n *\n * @instance\n * @memberof AuthorizationBrowserFirstParty\n * @param {Object} options - Already augmented with state + PKCE info\n * @returns {Promise<void>}\n */\n initiateAuthorizationCodeGrant(options) {\n this.logger.info('authorization: initiating authorization code grant flow');\n const loginUrl = this.webex.credentials.buildLoginUrl(\n Object.assign({response_type: 'code'}, options)\n );\n\n this.eventEmitter.emit(Events.login, {\n eventType: 'redirectToLoginUrl',\n data: {loginUrl},\n });\n\n if (options?.separateWindow) {\n // If a separate popup window is requested, combine user supplied window features\n const defaultWindowSettings = {\n width: 600,\n height: 800,\n };\n\n const windowSettings = Object.assign(\n defaultWindowSettings,\n typeof options.separateWindow === 'object' ? options.separateWindow : {}\n );\n\n const windowFeatures = Object.entries(windowSettings)\n .map(([key, value]) => `${key}=${value}`)\n .join(',');\n this.webex.getWindow().open(loginUrl, '_blank', windowFeatures);\n } else {\n // Normal (in-tab) redirect\n this.webex.getWindow().location = loginUrl;\n }\n\n return Promise.resolve();\n },\n\n /**\n * Initiates third-party (social provider) login. Generates a CSRF token,\n * embeds it in `options.state.csrf_token`, and delegates to\n * `initiateThirdPartyLoginRedirect` for navigation.\n *\n * @instance\n * @memberof AuthorizationBrowserFirstParty\n * @param {Object} options\n * @param {string} options.oauth2provider\n * @param {string} options.returnURL\n * @param {Object} [options.state] - Caller-supplied state object. Merged\n * with the generated `csrf_token`.\n * @returns {Promise<void>}\n */\n initiateThirdPartyLogin(options = {}) {\n options = cloneDeep(options);\n if (options.state !== undefined && !isObject(options.state)) {\n throw new Error('if specified, `options.state` must be an object');\n }\n options.state = options.state || {};\n options.state.csrf_token = this._generateSecurityToken();\n\n return this.initiateThirdPartyLoginRedirect(options);\n },\n\n /**\n * Performs the navigation step of the third-party login flow. Builds the\n * IdBroker URL via `Credentials#buildThirdPartyLoginUrl` and assigns it\n * to `getWindow().location`.\n *\n * Mirrors `initiateAuthorizationCodeGrant` for the `/authorize` flow.\n * Consumers may override this method for custom navigation handling\n * (e.g. postMessage in iframed contexts).\n *\n * @instance\n * @memberof AuthorizationBrowserFirstParty\n * @param {Object} options\n * @param {string} options.oauth2provider\n * @param {string} options.returnURL\n * @returns {Promise<void>}\n */\n initiateThirdPartyLoginRedirect(options = {}) {\n this.logger.info('authorization: initiating third-party login redirect');\n\n try {\n const url = this.webex.credentials.buildThirdPartyLoginUrl(options);\n\n this.webex.getWindow().location = url;\n } catch (err) {\n return Promise.reject(err);\n }\n\n return Promise.resolve();\n },\n\n /**\n * Handles the third-party (social provider) login callback. Reads the\n * current `window.location`, decodes `state`, validates the CSRF token\n * (`state.csrf_token`), scrubs sensitive parameters from the URL via\n * `_cleanUrl`, and returns the parsed payload.\n *\n * Mirrors `initialize()` in always operating on the live\n * `window.location`\n *\n * `idToken` is single-use: it is parsed out of the URL exactly once and\n * the calling client is expected to exchange it (or discard it)\n * immediately. The returned `state` has `csrf_token` removed.\n *\n * @instance\n * @memberof AuthorizationBrowserFirstParty\n * @returns {{idToken: string|undefined, email: string|undefined,\n * error: string|undefined, state: Object}}\n */\n handleThirdPartyCallback() {\n const location = url.parse(this.webex.getWindow().location.href, true);\n\n location.query.state = decodeState(location.query.state || 'e30');\n\n this._verifySecurityToken(location.query, {requireMatch: true});\n this._cleanUrl(location);\n\n const {id_token: idToken, email, error, state: {csrf_token, ...state}} = location.query;\n\n return {idToken, email, error, state};\n },\n\n /**\n * Called by {@link WebexCore#logout()}.\n * Constructs logout URL and (unless suppressed) navigates away to ensure\n * server-side session termination.\n *\n * @instance\n * @memberof AuthorizationBrowserFirstParty\n * @param {Object} options\n * @param {boolean} options.noRedirect if true, does not redirect\n * @returns {Promise<void>}\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 (super) token bundle.\n *\n * Decorators:\n * - @whileInFlight('isAuthorizing'): prevents overlapping exchanges.\n * - @oneFlight: collapses simultaneous calls into one network request.\n *\n * Includes PKCE code_verifier if present from earlier login initiation.\n *\n * Error Handling:\n * - Non-400 responses are propagated.\n * - 400 responses map to OAuth-specific grantErrors.\n *\n * @instance\n * @memberof AuthorizationBrowserFirstParty\n * @param {Object} options\n * @param {string} options.code - Authorization code from redirect\n * @param {string} [options.codeVerifier] - PKCE code verifier if used\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, // Request combined access/refresh response\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, // This is the token acquisition call itself\n })\n .then((res) => {\n // Store supertoken into credentials (includes refresh token)\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 // Map standard OAuth error to strongly typed error class\n const ErrorConstructor = grantErrors.select(res.body.error);\n\n return Promise.reject(new ErrorConstructor(res._res || res));\n });\n },\n\n /**\n * Generate a QR code verification URL for device authorization flow.\n * When a user scans the QR code with a mobile device, this deep-links into\n * Webex (web) to continue login, including passing along userCode and the\n * helper service base URL.\n *\n * @instance\n * @memberof AuthorizationBrowserFirstParty\n * @param {String} verificationUrl - Original verification URI (complete)\n * @returns {String} Possibly rewritten verification URL\n */\n _generateQRCodeVerificationUrl(verificationUrl) {\n const baseUrl = 'https://web.webex.com/deviceAuth';\n const urlParams = new URLSearchParams(new URL(verificationUrl).search);\n const userCode = urlParams.get('userCode');\n\n if (userCode) {\n const {services} = this.webex.internal;\n const oauthHelperUrl = services.get('oauth-helper');\n const newVerificationUrl = new URL(baseUrl);\n newVerificationUrl.searchParams.set('usercode', userCode);\n newVerificationUrl.searchParams.set('oauthhelper', oauthHelperUrl);\n return newVerificationUrl.toString();\n } else {\n return verificationUrl;\n }\n },\n\n /**\n * Initiates Device Authorization (QR Code) flow.\n *\n * Steps:\n * 1. Obtain device_code, user_code, verification URLs from oauth-helper.\n * 2. Emit getUserCodeSuccess (provides data for generating QR code).\n * 3. Start polling token endpoint with device_code.\n *\n * Emits qRCodeLogin events for UI to react (success, failure, pending, etc.).\n *\n * @instance\n * @memberof AuthorizationBrowserFirstParty\n * @emits #qRCodeLogin\n */\n initQRCodeLogin() {\n if (this.pollingTimer) {\n // Prevent concurrent device authorization attempts\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 const verificationUriComplete =\n this._generateQRCodeVerificationUrl(verification_uri_complete);\n this.eventEmitter.emit(Events.qRCodeLogin, {\n eventType: 'getUserCodeSuccess',\n userData: {\n userCode: user_code,\n verificationUri: verification_uri,\n verificationUriComplete,\n },\n });\n // Begin polling for authorization completion\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 * Poll the device token endpoint until user authorizes, an error occurs,\n * or timeout happens.\n *\n * Polling behavior:\n * - Interval provided by server (default 2s). 'slow_down' doubles interval once.\n * - 428 status => pending (continue).\n * - Success => set credentials + emit authorizationSuccess + stop polling.\n * - Any other error => emit authorizationFailure + stop polling.\n *\n * Cancellation:\n * - cancelQRCodePolling() resets timers and polling ids so late responses are ignored.\n *\n * @instance\n * @memberof AuthorizationBrowserFirstParty\n * @param {Object} options - Must include device_code, may include interval/expires_in\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 // Already polling; avoid starting a duplicate cycle\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 // Server recommended polling interval (seconds)\n let interval = options.interval ?? 2;\n\n // Global timeout for entire device authorization attempt\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 // Increment id so any previous poll loops can be invalidated\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 polling canceled (id changed), ignore this response\n if (this.currentPollingId !== this.pollingId) return;\n\n this.eventEmitter.emit(Events.qRCodeLogin, {\n eventType: 'authorizationSuccess',\n data: res.body,\n });\n this.webex.credentials.set({supertoken: res.body});\n this.cancelQRCodePolling();\n })\n .catch((res) => {\n if (this.currentPollingId !== this.pollingId) return;\n\n // Backoff signal from server; increase interval just once for next cycle\n if (res.statusCode === 400 && res.body.message === 'slow_down') {\n schedulePolling(interval * 2);\n return;\n }\n\n // Pending: 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 // Terminal error\n this.cancelQRCodePolling();\n\n this.eventEmitter.emit(Events.qRCodeLogin, {\n eventType: 'authorizationFailure',\n data: res.body,\n });\n });\n };\n\n // Schedules next poll invocation\n const schedulePolling = (interval) =>\n (this.pollingTimer = setTimeout(polling, interval * 1000));\n\n schedulePolling(interval);\n },\n\n /**\n * Cancel active device authorization polling loop.\n *\n * @param {boolean} withCancelEvent emit a pollingCanceled event (default true)\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 *\n * Certain authorization codes encode organization info in a structured\n * underscore-delimited format. This method parses out the 3rd segment.\n *\n * For undocumented formats or unexpected code shapes, returns undefined.\n *\n * @instance\n * @memberof AuthorizationBrowserFirstParty\n * @param {String} code\n * @private\n * @returns {String|undefined}\n */\n _extractOrgIdFromCode(code) {\n return code?.split('_')[2] || undefined;\n },\n\n /**\n * Checks if the result of the login redirect contains an OAuth error.\n * Throws a mapped grant error if encountered.\n *\n * @instance\n * @memberof AuthorizationBrowserFirstParty\n * @param {Object} location\n * @private\n * @returns {void}\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 (authorization code, CSRF token).\n * This is important to avoid leaking sensitive parameters via:\n * - Browser history\n * - Copy/paste of URL\n * - HTTP referrer headers to third-party content\n *\n * Approach:\n * - Remove 'code' (OAuth code-grant), 'id_token', and 'email'\n * (third-party callback).\n * - Remove 'state' entirely if it only contained csrf_token.\n * - Else, re-encode remaining state fields (minus csrf_token).\n * - Replace current history entry (no page reload).\n *\n * @instance\n * @memberof AuthorizationBrowserFirstParty\n * @param {Object} location\n * @private\n * @returns {void}\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 Reflect.deleteProperty(location.query, 'id_token');\n Reflect.deleteProperty(location.query, 'email');\n if (isEmpty(omit(location.query.state, 'csrf_token'))) {\n Reflect.deleteProperty(location.query, 'state');\n } else {\n location.query.state = encodeState(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 a PKCE (RFC 7636) code verifier and corresponding S256 code challenge.\n * Persists the verifier in sessionStorage (single-use) for later retrieval\n * during authorization code exchange; removes it once consumed.\n *\n * Implementation details:\n * - Creates a 128 character string using base64url safe alphabet.\n * - Computes SHA256 hash, encodes to base64url (no padding).\n *\n * @instance\n * @memberof AuthorizationBrowserFirstParty\n * @private\n * @returns {string} code_challenge\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 stores it in sessionStorage.\n * Token is embedded in 'state' and validated upon redirect return.\n *\n * Uses UUID v4 for randomness.\n *\n * @instance\n * @memberof AuthorizationBrowserFirstParty\n * @private\n * @returns {string} token\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 * Verifies that the CSRF token returned in the 'state' matches the one\n * previously stored in sessionStorage.\n *\n * Steps:\n * - Retrieve and immediately remove stored token (one-time use).\n * - Ensure state + state.csrf_token exist.\n * - Compare values; throw descriptive errors on mismatch / absence.\n *\n * If no stored token (e.g., user navigated directly), silently returns\n * unless `options.requireMatch` is `true`, in which case absence of a\n * stored token is treated as a CSRF failure.\n *\n * @instance\n * @memberof AuthorizationBrowserFirstParty\n * @param {Object} query - Parsed query (location.query)\n * @param {Object} [options]\n * @param {boolean} [options.requireMatch=false] - When true, throws if\n * no stored sessionToken is present.\n * @private\n * @returns {void}\n */\n _verifySecurityToken(query, options = {}) {\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 if (options.requireMatch) {\n throw new Error('CSRF token missing from session storage');\n }\n\n return;\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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","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":["_querystring","_interopRequireDefault","require","_url2","_events","_common","_webexCore","_lodash","_uuid","_encBase64url","_cryptoJs","_excluded","_dec","_dec2","_obj","lodash","OAUTH2_CSRF_TOKEN","OAUTH2_CODE_VERIFIER","Events","exports","login","qRCodeLogin","InitialAuthorizationCodeGrantOutcomes","failure","notAttempted","success","Authorization","WebexPlugin","extend","whileInFlight","derived","initialAuthorizationCodeGrantOutcome","deps","fn","_initialAuthorizationCodeGrantOutcome","isAuthenticating","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","decodeState","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","emit","eventType","data","hasEmail","email","hasState","cloneDeep","emailHash","CryptoJS","SHA256","toString","csrf_token","_generateSecurityToken","code_challenge","_generateCodeChallenge","code_challenge_method","initiateAuthorizationCodeGrant","info","loginUrl","credentials","buildLoginUrl","_assign","response_type","separateWindow","defaultWindowSettings","width","height","windowSettings","_typeof2","windowFeatures","_entries","map","_ref","_ref2","_slicedToArray2","key","value","concat","join","open","initiateThirdPartyLogin","isObject","Error","initiateThirdPartyLoginRedirect","buildThirdPartyLoginUrl","err","reject","handleThirdPartyCallback","requireMatch","_location$query","idToken","id_token","_location$query$state","_objectWithoutProperties2","logout","noRedirect","buildLogoutUrl","_this2","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","_generateQRCodeVerificationUrl","verificationUrl","baseUrl","urlParams","URLSearchParams","URL","search","userCode","get","oauthHelperUrl","newVerificationUrl","searchParams","initQRCodeLogin","_this3","message","service","resource","scope","_res$body","user_code","verification_uri","verification_uri_complete","verificationUriComplete","userData","verificationUri","_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","encodeState","querystring","stringify","format","safeCharacterMap","base64url","_safe_map","times","random","codeChallenge","setItem","token","uuid","v4","_query$state","sessionToken","version","_applyDecoratedDescriptor2","_getOwnPropertyDescriptor","oneFlight","_default"],"sources":["authorization.js"],"sourcesContent":["// @ts-nocheck\n/* eslint-disable */\n/*!\n * Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.\n */\n\n/* eslint camelcase: [0] */\n/**\n * TS checking disabled: file uses legacy decorator syntax inside an object literal\n * transformed by Babel. Safe to ignore for now.\n */\n\nimport querystring from 'querystring';\nimport url from 'url';\nimport {EventEmitter} from 'events';\n\nimport {decodeState, encodeState, oneFlight, whileInFlight} from '@webex/common';\nimport {grantErrors, WebexPlugin} from '@webex/webex-core';\nimport {cloneDeep, isEmpty, omit, isObject} 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 login: 'login',\n /**\n * QR code login events\n */\n qRCodeLogin: 'qRCodeLogin',\n};\n\n/**\n * Terminal outcomes for the automatic authorization-code exchange performed\n * during authorization plugin initialization.\n *\n * @enum {string}\n */\nexport const InitialAuthorizationCodeGrantOutcomes = {\n failure: 'failure',\n notAttempted: 'not_attempted',\n success: 'success',\n};\n\n/**\n * Browser support for OAuth2 for first-party (Webex Web Client) usage.\n *\n * High-level flow handled by this module:\n * 1. initiateLogin() constructs authorization request (adds CSRF + PKCE).\n * 2. Browser navigates to IdBroker (login).\n * 3. IdBroker redirects back with ?code=... (&state=...).\n * 4. initialize() detects code, validates state/CSRF, cleans URL, optionally\n * pre-fetches a preauth catalog, then exchanges the code via\n * requestAuthorizationCodeGrant().\n * 5. Sets resulting supertoken (access/refresh token bundle) on credentials.\n *\n * Additional supported flow:\n * - Device Authorization (QR Code login):\n * initQRCodeLogin() obtains device + user codes and begins polling\n * _startQRCodePolling() until tokens are issued or timeout/cancel occurs.\n *\n * Security considerations implemented:\n * - CSRF token (state.csrf_token) generation + verification.\n * - PKCE (S256) code verifier + challenge generation and consumption.\n * - URL cleanup after redirect (removes code & CSRF to prevent leakage).\n *\n * Use of this plugin for anything other than the Webex Web Client is discouraged.\n *\n * @class\n * @name AuthorizationBrowserFirstParty\n * @private\n */\nconst Authorization = WebexPlugin.extend({\n derived: {\n /**\n * Retains the terminal outcome of the automatic authorization-code exchange\n * performed during this authorization plugin instance's initialization.\n *\n * This historical value does not represent current authorization state,\n * credentials hydrated from storage, guest authentication, or\n * authorization-code exchanges requested later on the same SDK instance. It\n * is not reset by logout. OAuth redirect errors and CSRF validation failures\n * occur before the exchange, so the value remains not_attempted; these errors\n * can throw before ready becomes true.\n *\n * Calling logout({noRedirect: true}) does not cancel an initialization\n * exchange already in flight. If that exchange later settles, it can still\n * update credentials and this retained outcome.\n *\n * Interpret only after authorization readiness:\n * - not_attempted: initialization did not invoke requestAuthorizationCodeGrant()\n * - success: the initialization exchange fulfilled\n * - failure: the initialization exchange threw or rejected\n *\n * @instance\n * @memberof AuthorizationBrowserFirstParty\n * @readonly\n * @type {string}\n */\n initialAuthorizationCodeGrantOutcome: {\n deps: ['_initialAuthorizationCodeGrantOutcome'],\n fn() {\n return this._initialAuthorizationCodeGrantOutcome;\n },\n },\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 /**\n * Internal backing state for the initial authorization-code grant outcome.\n * @private\n */\n _initialAuthorizationCodeGrantOutcome: {\n default: InitialAuthorizationCodeGrantOutcomes.notAttempted,\n type: 'string',\n },\n /**\n * Indicates that the plugin has finished any automatic startup\n * processing (e.g., exchanging a returned authorization code)\n */\n ready: {\n default: false,\n type: 'boolean',\n },\n },\n\n namespace: 'Credentials',\n\n /**\n * EventEmitter for authorization events such as QR code login progress\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 (device authorization)\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 (overall timeout)\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 * Used to safely ignore late poll responses after a cancel/reset.\n * @instance\n * @memberof AuthorizationBrowserFirstParty\n * @type {number}\n * @private\n */\n pollingId: 0,\n\n /**\n * Identifier for the current polling request (snapshot of pollingId)\n * @instance\n * @memberof AuthorizationBrowserFirstParty\n * @type {?number}\n * @private\n */\n currentPollingId: null,\n\n /**\n * Auto executes during Webex.init() – you do NOT call this yourself.\n *\n * Purpose: Seamless \"redirect completion\" of the OAuth Authorization Code (+ PKCE) flow.\n *\n * Simple summary:\n * - You call initiateLogin() which redirects user to IdBroker.\n * - User signs in; IdBroker redirects back to your redirect_uri with ?code=... (&state=...).\n * - During SDK startup this initialize() runs automatically, sees the code, and\n * silently finishes the login (validates state/CSRF + PKCE, scrubs URL, exchanges code).\n * - When done, webex.credentials.supertoken holds access+refresh and ready=true.\n *\n * Step-by-step:\n * 1. Inspect current window.location for ?code= (& state=).\n * 2. If no code: set ready=true immediately (nothing to complete).\n * 3. If code present:\n * - Decode base64 state JSON.\n * - Verify CSRF token matches sessionStorage value.\n * - Retrieve then delete PKCE code_verifier (single use).\n * - Optionally derive preauth hint (emailhash in state OR orgId parsed from code).\n * - Clean the URL (history.replaceState) to remove code & csrf token data.\n * - nextTick:\n * a. Best‑effort preauth catalog fetch (non-blocking).\n * b. Exchange authorization code (with code_verifier if any) for supertoken\n * and store on webex.credentials.\n * 4. Set ready=true after the async sequence finishes (or immediately if step 2).\n *\n * Result: If the redirect included a valid code the token exchange is completed\n * automatically—no extra API call needed after Webex.init().\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 // Check if redirect includes error\n this._checkForErrors(location);\n\n const {code} = location.query;\n\n // If no authorization code returned, nothing to do\n if (!code) {\n this.ready = true;\n return ret;\n }\n\n // Decode and parse state object (if present)\n if (location.query.state) {\n location.query.state = decodeState(location.query.state);\n } else {\n location.query.state = {};\n }\n\n // Retrieve PKCE code verifier (if a PKCE flow was initiated)\n const codeVerifier = this.webex.getWindow().sessionStorage.getItem(OAUTH2_CODE_VERIFIER);\n // Immediately remove code verifier to minimize exposure\n this.webex.getWindow().sessionStorage.removeItem(OAUTH2_CODE_VERIFIER);\n\n const {emailhash} = location.query.state;\n\n // Validate CSRF token included in state\n this._verifySecurityToken(location.query);\n // Remove code + CSRF token remnants from URL (history replace)\n this._cleanUrl(location);\n\n let preauthCatalogParams;\n\n // Attempt to extract orgId from structured authorization code (if present)\n const orgId = this._extractOrgIdFromCode(code);\n\n if (emailhash) {\n preauthCatalogParams = {emailhash};\n } else if (orgId) {\n preauthCatalogParams = {orgId};\n }\n\n // Defer token exchange until next tick in case credentials plugin not ready yet\n process.nextTick(() => {\n this.webex.internal.services\n .collectPreauthCatalog(preauthCatalogParams)\n .catch(() => Promise.resolve()) // Non-fatal if catalog collection fails\n .then(() => this.requestAuthorizationCodeGrant({code, codeVerifier}))\n .then(() => {\n this._initialAuthorizationCodeGrantOutcome =\n InitialAuthorizationCodeGrantOutcomes.success;\n })\n .catch((error) => {\n this._initialAuthorizationCodeGrantOutcome =\n InitialAuthorizationCodeGrantOutcomes.failure;\n this.logger.warn('authorization: failed initial authorization code grant request', error);\n })\n .then(() => {\n // Mark plugin ready regardless of success/failure of token exchange\n this.ready = true;\n });\n });\n\n return ret;\n },\n\n /**\n * Kicks off an OAuth authorization code flow (first party).\n *\n * Adds security + PKCE properties:\n * - SHA256(email) (emailHash & emailhash) for preauth and redirect flows\n * - state.csrf_token for CSRF protection\n * - PKCE code_challenge (S256)\n *\n * NOTE: This does not itself perform the redirect; it calls\n * initiateAuthorizationCodeGrant() which changes window location or opens\n * a separate window as configured.\n *\n * @instance\n * @memberof AuthorizationBrowserFirstParty\n * @param {Object} options\n * @returns {Promise}\n */\n initiateLogin(options = {}) {\n this.eventEmitter.emit(Events.login, {\n eventType: 'initiateLogin',\n data: {\n hasEmail: !!options.email,\n hasState: !!options.state,\n },\n });\n\n options = cloneDeep(options);\n\n // Optionally compute heuristic email hash for preauth usage\n if (options.email) {\n options.emailHash = CryptoJS.SHA256(options.email).toString();\n }\n delete options.email; // Ensure raw email not propagated further\n\n options.state = options.state || {};\n // Embed CSRF token\n options.state.csrf_token = this._generateSecurityToken();\n // Provide email hash in lower-case key used by catalog service\n // (Note: catalog uses emailhash and redirectCI uses emailHash)\n options.state.emailhash = options.emailHash;\n\n // PKCE - produce code_challenge (S256) and persist code_verifier\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 * Performs the navigation step of the Authorization Code flow.\n * Builds login URL and either:\n * - Replaces current window location (default), or\n * - Opens a separate window (popup) if options.separateWindow supplied.\n *\n * Decorated with whileInFlight('isAuthorizing') to set isAuthorizing=true\n * during execution to prevent concurrent overlapping attempts.\n *\n * @instance\n * @memberof AuthorizationBrowserFirstParty\n * @param {Object} options - Already augmented with state + PKCE info\n * @returns {Promise<void>}\n */\n initiateAuthorizationCodeGrant(options) {\n this.logger.info('authorization: initiating authorization code grant flow');\n const loginUrl = this.webex.credentials.buildLoginUrl(\n Object.assign({response_type: 'code'}, options)\n );\n\n this.eventEmitter.emit(Events.login, {\n eventType: 'redirectToLoginUrl',\n data: {loginUrl},\n });\n\n if (options?.separateWindow) {\n // If a separate popup window is requested, combine user supplied window features\n const defaultWindowSettings = {\n width: 600,\n height: 800,\n };\n\n const windowSettings = Object.assign(\n defaultWindowSettings,\n typeof options.separateWindow === 'object' ? options.separateWindow : {}\n );\n\n const windowFeatures = Object.entries(windowSettings)\n .map(([key, value]) => `${key}=${value}`)\n .join(',');\n this.webex.getWindow().open(loginUrl, '_blank', windowFeatures);\n } else {\n // Normal (in-tab) redirect\n this.webex.getWindow().location = loginUrl;\n }\n\n return Promise.resolve();\n },\n\n /**\n * Initiates third-party (social provider) login. Generates a CSRF token,\n * embeds it in `options.state.csrf_token`, and delegates to\n * `initiateThirdPartyLoginRedirect` for navigation.\n *\n * @instance\n * @memberof AuthorizationBrowserFirstParty\n * @param {Object} options\n * @param {string} options.oauth2provider\n * @param {string} options.returnURL\n * @param {Object} [options.state] - Caller-supplied state object. Merged\n * with the generated `csrf_token`.\n * @returns {Promise<void>}\n */\n initiateThirdPartyLogin(options = {}) {\n options = cloneDeep(options);\n if (options.state !== undefined && !isObject(options.state)) {\n throw new Error('if specified, `options.state` must be an object');\n }\n options.state = options.state || {};\n options.state.csrf_token = this._generateSecurityToken();\n\n return this.initiateThirdPartyLoginRedirect(options);\n },\n\n /**\n * Performs the navigation step of the third-party login flow. Builds the\n * IdBroker URL via `Credentials#buildThirdPartyLoginUrl` and assigns it\n * to `getWindow().location`.\n *\n * Mirrors `initiateAuthorizationCodeGrant` for the `/authorize` flow.\n * Consumers may override this method for custom navigation handling\n * (e.g. postMessage in iframed contexts).\n *\n * @instance\n * @memberof AuthorizationBrowserFirstParty\n * @param {Object} options\n * @param {string} options.oauth2provider\n * @param {string} options.returnURL\n * @returns {Promise<void>}\n */\n initiateThirdPartyLoginRedirect(options = {}) {\n this.logger.info('authorization: initiating third-party login redirect');\n\n try {\n const url = this.webex.credentials.buildThirdPartyLoginUrl(options);\n\n this.webex.getWindow().location = url;\n } catch (err) {\n return Promise.reject(err);\n }\n\n return Promise.resolve();\n },\n\n /**\n * Handles the third-party (social provider) login callback. Reads the\n * current `window.location`, decodes `state`, validates the CSRF token\n * (`state.csrf_token`), scrubs sensitive parameters from the URL via\n * `_cleanUrl`, and returns the parsed payload.\n *\n * Mirrors `initialize()` in always operating on the live\n * `window.location`\n *\n * `idToken` is single-use: it is parsed out of the URL exactly once and\n * the calling client is expected to exchange it (or discard it)\n * immediately. The returned `state` has `csrf_token` removed.\n *\n * @instance\n * @memberof AuthorizationBrowserFirstParty\n * @returns {{idToken: string|undefined, email: string|undefined,\n * error: string|undefined, state: Object}}\n */\n handleThirdPartyCallback() {\n const location = url.parse(this.webex.getWindow().location.href, true);\n\n location.query.state = decodeState(location.query.state || 'e30');\n\n this._verifySecurityToken(location.query, {requireMatch: true});\n this._cleanUrl(location);\n\n const {\n id_token: idToken,\n email,\n error,\n state: {csrf_token, ...state},\n } = location.query;\n\n return {idToken, email, error, state};\n },\n\n /**\n * Called by {@link WebexCore#logout()}.\n * Constructs logout URL and (unless suppressed) navigates away to ensure\n * server-side session termination.\n *\n * @instance\n * @memberof AuthorizationBrowserFirstParty\n * @param {Object} options\n * @param {boolean} options.noRedirect if true, does not redirect\n * @returns {Promise<void>}\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 (super) token bundle.\n *\n * Decorators:\n * - @whileInFlight('isAuthorizing'): prevents overlapping exchanges.\n * - @oneFlight: collapses simultaneous calls into one network request.\n *\n * Includes PKCE code_verifier if present from earlier login initiation.\n *\n * Error Handling:\n * - Non-400 responses are propagated.\n * - 400 responses map to OAuth-specific grantErrors.\n *\n * @instance\n * @memberof AuthorizationBrowserFirstParty\n * @param {Object} options\n * @param {string} options.code - Authorization code from redirect\n * @param {string} [options.codeVerifier] - PKCE code verifier if used\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, // Request combined access/refresh response\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, // This is the token acquisition call itself\n })\n .then((res) => {\n // Store supertoken into credentials (includes refresh token)\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 // Map standard OAuth error to strongly typed error class\n const ErrorConstructor = grantErrors.select(res.body.error);\n\n return Promise.reject(new ErrorConstructor(res._res || res));\n });\n },\n\n /**\n * Generate a QR code verification URL for device authorization flow.\n * When a user scans the QR code with a mobile device, this deep-links into\n * Webex (web) to continue login, including passing along userCode and the\n * helper service base URL.\n *\n * @instance\n * @memberof AuthorizationBrowserFirstParty\n * @param {String} verificationUrl - Original verification URI (complete)\n * @returns {String} Possibly rewritten verification URL\n */\n _generateQRCodeVerificationUrl(verificationUrl) {\n const baseUrl = 'https://web.webex.com/deviceAuth';\n const urlParams = new URLSearchParams(new URL(verificationUrl).search);\n const userCode = urlParams.get('userCode');\n\n if (userCode) {\n const {services} = this.webex.internal;\n const oauthHelperUrl = services.get('oauth-helper');\n const newVerificationUrl = new URL(baseUrl);\n newVerificationUrl.searchParams.set('usercode', userCode);\n newVerificationUrl.searchParams.set('oauthhelper', oauthHelperUrl);\n return newVerificationUrl.toString();\n } else {\n return verificationUrl;\n }\n },\n\n /**\n * Initiates Device Authorization (QR Code) flow.\n *\n * Steps:\n * 1. Obtain device_code, user_code, verification URLs from oauth-helper.\n * 2. Emit getUserCodeSuccess (provides data for generating QR code).\n * 3. Start polling token endpoint with device_code.\n *\n * Emits qRCodeLogin events for UI to react (success, failure, pending, etc.).\n *\n * @instance\n * @memberof AuthorizationBrowserFirstParty\n * @emits #qRCodeLogin\n */\n initQRCodeLogin() {\n if (this.pollingTimer) {\n // Prevent concurrent device authorization attempts\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 const verificationUriComplete =\n this._generateQRCodeVerificationUrl(verification_uri_complete);\n this.eventEmitter.emit(Events.qRCodeLogin, {\n eventType: 'getUserCodeSuccess',\n userData: {\n userCode: user_code,\n verificationUri: verification_uri,\n verificationUriComplete,\n },\n });\n // Begin polling for authorization completion\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 * Poll the device token endpoint until user authorizes, an error occurs,\n * or timeout happens.\n *\n * Polling behavior:\n * - Interval provided by server (default 2s). 'slow_down' doubles interval once.\n * - 428 status => pending (continue).\n * - Success => set credentials + emit authorizationSuccess + stop polling.\n * - Any other error => emit authorizationFailure + stop polling.\n *\n * Cancellation:\n * - cancelQRCodePolling() resets timers and polling ids so late responses are ignored.\n *\n * @instance\n * @memberof AuthorizationBrowserFirstParty\n * @param {Object} options - Must include device_code, may include interval/expires_in\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 // Already polling; avoid starting a duplicate cycle\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 // Server recommended polling interval (seconds)\n let interval = options.interval ?? 2;\n\n // Global timeout for entire device authorization attempt\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 // Increment id so any previous poll loops can be invalidated\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 polling canceled (id changed), ignore this response\n if (this.currentPollingId !== this.pollingId) return;\n\n this.eventEmitter.emit(Events.qRCodeLogin, {\n eventType: 'authorizationSuccess',\n data: res.body,\n });\n this.webex.credentials.set({supertoken: res.body});\n this.cancelQRCodePolling();\n })\n .catch((res) => {\n if (this.currentPollingId !== this.pollingId) return;\n\n // Backoff signal from server; increase interval just once for next cycle\n if (res.statusCode === 400 && res.body.message === 'slow_down') {\n schedulePolling(interval * 2);\n return;\n }\n\n // Pending: 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 // Terminal error\n this.cancelQRCodePolling();\n\n this.eventEmitter.emit(Events.qRCodeLogin, {\n eventType: 'authorizationFailure',\n data: res.body,\n });\n });\n };\n\n // Schedules next poll invocation\n const schedulePolling = (interval) =>\n (this.pollingTimer = setTimeout(polling, interval * 1000));\n\n schedulePolling(interval);\n },\n\n /**\n * Cancel active device authorization polling loop.\n *\n * @param {boolean} withCancelEvent emit a pollingCanceled event (default true)\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 *\n * Certain authorization codes encode organization info in a structured\n * underscore-delimited format. This method parses out the 3rd segment.\n *\n * For undocumented formats or unexpected code shapes, returns undefined.\n *\n * @instance\n * @memberof AuthorizationBrowserFirstParty\n * @param {String} code\n * @private\n * @returns {String|undefined}\n */\n _extractOrgIdFromCode(code) {\n return code?.split('_')[2] || undefined;\n },\n\n /**\n * Checks if the result of the login redirect contains an OAuth error.\n * Throws a mapped grant error if encountered.\n *\n * @instance\n * @memberof AuthorizationBrowserFirstParty\n * @param {Object} location\n * @private\n * @returns {void}\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 (authorization code, CSRF token).\n * This is important to avoid leaking sensitive parameters via:\n * - Browser history\n * - Copy/paste of URL\n * - HTTP referrer headers to third-party content\n *\n * Approach:\n * - Remove 'code' (OAuth code-grant), 'id_token', and 'email'\n * (third-party callback).\n * - Remove 'state' entirely if it only contained csrf_token.\n * - Else, re-encode remaining state fields (minus csrf_token).\n * - Replace current history entry (no page reload).\n *\n * @instance\n * @memberof AuthorizationBrowserFirstParty\n * @param {Object} location\n * @private\n * @returns {void}\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 Reflect.deleteProperty(location.query, 'id_token');\n Reflect.deleteProperty(location.query, 'email');\n if (isEmpty(omit(location.query.state, 'csrf_token'))) {\n Reflect.deleteProperty(location.query, 'state');\n } else {\n location.query.state = encodeState(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 a PKCE (RFC 7636) code verifier and corresponding S256 code challenge.\n * Persists the verifier in sessionStorage (single-use) for later retrieval\n * during authorization code exchange; removes it once consumed.\n *\n * Implementation details:\n * - Creates a 128 character string using base64url safe alphabet.\n * - Computes SHA256 hash, encodes to base64url (no padding).\n *\n * @instance\n * @memberof AuthorizationBrowserFirstParty\n * @private\n * @returns {string} code_challenge\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 stores it in sessionStorage.\n * Token is embedded in 'state' and validated upon redirect return.\n *\n * Uses UUID v4 for randomness.\n *\n * @instance\n * @memberof AuthorizationBrowserFirstParty\n * @private\n * @returns {string} token\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 * Verifies that the CSRF token returned in the 'state' matches the one\n * previously stored in sessionStorage.\n *\n * Steps:\n * - Retrieve and immediately remove stored token (one-time use).\n * - Ensure state + state.csrf_token exist.\n * - Compare values; throw descriptive errors on mismatch / absence.\n *\n * If no stored token (e.g., user navigated directly), silently returns\n * unless `options.requireMatch` is `true`, in which case absence of a\n * stored token is treated as a CSRF failure.\n *\n * @instance\n * @memberof AuthorizationBrowserFirstParty\n * @param {Object} query - Parsed query (location.query)\n * @param {Object} [options]\n * @param {boolean} [options.requireMatch=false] - When true, throws if\n * no stored sessionToken is present.\n * @private\n * @returns {void}\n */\n _verifySecurityToken(query, options = {}) {\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 if (options.requireMatch) {\n throw new Error('CSRF token missing from session storage');\n }\n\n return;\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":";;;;;;;;;;;;;;;;;;AAYA,IAAAA,YAAA,GAAAC,sBAAA,CAAAC,OAAA;AACA,IAAAC,KAAA,GAAAF,sBAAA,CAAAC,OAAA;AACA,IAAAE,OAAA,GAAAF,OAAA;AAEA,IAAAG,OAAA,GAAAH,OAAA;AACA,IAAAI,UAAA,GAAAJ,OAAA;AACA,IAAAK,OAAA,GAAAL,OAAA;AACA,IAAAM,KAAA,GAAAP,sBAAA,CAAAC,OAAA;AACA,IAAAO,aAAA,GAAAR,sBAAA,CAAAC,OAAA;AACA,IAAAQ,SAAA,GAAAT,sBAAA,CAAAC,OAAA;AAAiC,IAAAS,SAAA;AAAA,IAAAC,IAAA,EAAAC,KAAA,EAAAC,IAAA,EArBjC;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AAaA;AACA;AACA,IAAMC,MAAM,GAAGb,OAAO,CAAC,QAAQ,CAAC;AAEhC,IAAMc,iBAAiB,GAAG,mBAAmB;AAC7C,IAAMC,oBAAoB,GAAG,sBAAsB;;AAEnD;AACA;AACA;AACO,IAAMC,MAAM,GAAAC,OAAA,CAAAD,MAAA,GAAG;EACpBE,KAAK,EAAE,OAAO;EACd;AACF;AACA;EACEC,WAAW,EAAE;AACf,CAAC;;AAED;AACA;AACA;AACA;AACA;AACA;AACO,IAAMC,qCAAqC,GAAAH,OAAA,CAAAG,qCAAA,GAAG;EACnDC,OAAO,EAAE,SAAS;EAClBC,YAAY,EAAE,eAAe;EAC7BC,OAAO,EAAE;AACX,CAAC;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAMC,aAAa,GAAGC,sBAAW,CAACC,MAAM,EAAAhB,IAAA,GA+QrC,IAAAiB,qBAAa,EAAC,eAAe,CAAC,EAAAhB,KAAA,GA8J9B,IAAAgB,qBAAa,EAAC,eAAe,CAAC,EAAAf,IAAA,GA7aQ;EACvCgB,OAAO,EAAE;IACP;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;IACIC,oCAAoC,EAAE;MACpCC,IAAI,EAAE,CAAC,uCAAuC,CAAC;MAC/CC,EAAE,WAAFA,EAAEA,CAAA,EAAG;QACH,OAAO,IAAI,CAACC,qCAAqC;MACnD;IACF,CAAC;IACD;AACJ;AACA;AACA;AACA;AACA;IACIC,gBAAgB,EAAE;MAChBH,IAAI,EAAE,CAAC,eAAe,CAAC;MACvBC,EAAE,WAAFA,EAAEA,CAAA,EAAG;QACH,OAAO,IAAI,CAACG,aAAa;MAC3B;IACF;EACF,CAAC;EAEDC,OAAO,EAAE;IACP;AACJ;AACA;AACA;AACA;AACA;IACID,aAAa,EAAE;MACbE,OAAO,EAAE,KAAK;MACdC,IAAI,EAAE;IACR,CAAC;IACD;AACJ;AACA;AACA;IACIL,qCAAqC,EAAE;MACrCI,OAAO,EAAEhB,qCAAqC,CAACE,YAAY;MAC3De,IAAI,EAAE;IACR,CAAC;IACD;AACJ;AACA;AACA;IACIC,KAAK,EAAE;MACLF,OAAO,EAAE,KAAK;MACdC,IAAI,EAAE;IACR;EACF,CAAC;EAEDE,SAAS,EAAE,aAAa;EAExB;AACF;AACA;AACA;AACA;AACA;AACA;EACEC,YAAY,EAAE,IAAIC,oBAAY,CAAC,CAAC;EAEhC;AACF;AACA;AACA;AACA;AACA;AACA;EACEC,YAAY,EAAE,IAAI;EAClB;AACF;AACA;AACA;AACA;AACA;AACA;EACEC,sBAAsB,EAAE,IAAI;EAE5B;AACF;AACA;AACA;AACA;AACA;AACA;AACA;EACEC,SAAS,EAAE,CAAC;EAEZ;AACF;AACA;AACA;AACA;AACA;AACA;EACEC,gBAAgB,EAAE,IAAI;EAEtB;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;EACE;EACAC,UAAU,WAAVA,UAAUA,CAAA,EAAW;IAAA,IAAAC,KAAA;IAAA,SAAAC,IAAA,GAAAC,SAAA,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","ignoreList":[]}
|
package/dist/index.js
CHANGED
|
@@ -14,6 +14,12 @@ _Object$defineProperty(exports, "Events", {
|
|
|
14
14
|
return _authorization.Events;
|
|
15
15
|
}
|
|
16
16
|
});
|
|
17
|
+
_Object$defineProperty(exports, "InitialAuthorizationCodeGrantOutcomes", {
|
|
18
|
+
enumerable: true,
|
|
19
|
+
get: function get() {
|
|
20
|
+
return _authorization.InitialAuthorizationCodeGrantOutcomes;
|
|
21
|
+
}
|
|
22
|
+
});
|
|
17
23
|
_Object$defineProperty(exports, "config", {
|
|
18
24
|
enumerable: true,
|
|
19
25
|
get: function get() {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_webexCore","require","_authorization","_interopRequireWildcard","_config","_interopRequireDefault","e","t","_WeakMap","r","n","__esModule","o","i","f","__proto__","default","_typeof","has","get","set","_t","hasOwnProperty","call","_Object$defineProperty","_Object$getOwnPropertyDescriptor","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":"
|
|
1
|
+
{"version":3,"names":["_webexCore","require","_authorization","_interopRequireWildcard","_config","_interopRequireDefault","e","t","_WeakMap","r","n","__esModule","o","i","f","__proto__","default","_typeof","has","get","set","_t","hasOwnProperty","call","_Object$defineProperty","_Object$getOwnPropertyDescriptor","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, InitialAuthorizationCodeGrantOutcomes} 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,SAAAE,wBAAAG,CAAA,EAAAC,CAAA,6BAAAC,QAAA,MAAAC,CAAA,OAAAD,QAAA,IAAAE,CAAA,OAAAF,QAAA,YAAAL,uBAAA,YAAAA,wBAAAG,CAAA,EAAAC,CAAA,SAAAA,CAAA,IAAAD,CAAA,IAAAA,CAAA,CAAAK,UAAA,SAAAL,CAAA,MAAAM,CAAA,EAAAC,CAAA,EAAAC,CAAA,KAAAC,SAAA,QAAAC,OAAA,EAAAV,CAAA,iBAAAA,CAAA,gBAAAW,OAAA,CAAAX,CAAA,0BAAAA,CAAA,SAAAQ,CAAA,MAAAF,CAAA,GAAAL,CAAA,GAAAG,CAAA,GAAAD,CAAA,QAAAG,CAAA,CAAAM,GAAA,CAAAZ,CAAA,UAAAM,CAAA,CAAAO,GAAA,CAAAb,CAAA,GAAAM,CAAA,CAAAQ,GAAA,CAAAd,CAAA,EAAAQ,CAAA,cAAAO,EAAA,IAAAf,CAAA,gBAAAe,EAAA,OAAAC,cAAA,CAAAC,IAAA,CAAAjB,CAAA,EAAAe,EAAA,OAAAR,CAAA,IAAAD,CAAA,GAAAY,sBAAA,KAAAC,gCAAA,CAAAnB,CAAA,EAAAe,EAAA,OAAAR,CAAA,CAAAM,GAAA,IAAAN,CAAA,CAAAO,GAAA,IAAAR,CAAA,CAAAE,CAAA,EAAAO,EAAA,EAAAR,CAAA,IAAAC,CAAA,CAAAO,EAAA,IAAAf,CAAA,CAAAe,EAAA,WAAAP,CAAA,KAAAR,CAAA,EAAAC,CAAA;AAP9B;AACA;AACA;;AAOA,IAAMmB,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","ignoreList":[]}
|
package/package.json
CHANGED
package/src/authorization.js
CHANGED
|
@@ -39,6 +39,18 @@ export const Events = {
|
|
|
39
39
|
qRCodeLogin: 'qRCodeLogin',
|
|
40
40
|
};
|
|
41
41
|
|
|
42
|
+
/**
|
|
43
|
+
* Terminal outcomes for the automatic authorization-code exchange performed
|
|
44
|
+
* during authorization plugin initialization.
|
|
45
|
+
*
|
|
46
|
+
* @enum {string}
|
|
47
|
+
*/
|
|
48
|
+
export const InitialAuthorizationCodeGrantOutcomes = {
|
|
49
|
+
failure: 'failure',
|
|
50
|
+
notAttempted: 'not_attempted',
|
|
51
|
+
success: 'success',
|
|
52
|
+
};
|
|
53
|
+
|
|
42
54
|
/**
|
|
43
55
|
* Browser support for OAuth2 for first-party (Webex Web Client) usage.
|
|
44
56
|
*
|
|
@@ -69,6 +81,37 @@ export const Events = {
|
|
|
69
81
|
*/
|
|
70
82
|
const Authorization = WebexPlugin.extend({
|
|
71
83
|
derived: {
|
|
84
|
+
/**
|
|
85
|
+
* Retains the terminal outcome of the automatic authorization-code exchange
|
|
86
|
+
* performed during this authorization plugin instance's initialization.
|
|
87
|
+
*
|
|
88
|
+
* This historical value does not represent current authorization state,
|
|
89
|
+
* credentials hydrated from storage, guest authentication, or
|
|
90
|
+
* authorization-code exchanges requested later on the same SDK instance. It
|
|
91
|
+
* is not reset by logout. OAuth redirect errors and CSRF validation failures
|
|
92
|
+
* occur before the exchange, so the value remains not_attempted; these errors
|
|
93
|
+
* can throw before ready becomes true.
|
|
94
|
+
*
|
|
95
|
+
* Calling logout({noRedirect: true}) does not cancel an initialization
|
|
96
|
+
* exchange already in flight. If that exchange later settles, it can still
|
|
97
|
+
* update credentials and this retained outcome.
|
|
98
|
+
*
|
|
99
|
+
* Interpret only after authorization readiness:
|
|
100
|
+
* - not_attempted: initialization did not invoke requestAuthorizationCodeGrant()
|
|
101
|
+
* - success: the initialization exchange fulfilled
|
|
102
|
+
* - failure: the initialization exchange threw or rejected
|
|
103
|
+
*
|
|
104
|
+
* @instance
|
|
105
|
+
* @memberof AuthorizationBrowserFirstParty
|
|
106
|
+
* @readonly
|
|
107
|
+
* @type {string}
|
|
108
|
+
*/
|
|
109
|
+
initialAuthorizationCodeGrantOutcome: {
|
|
110
|
+
deps: ['_initialAuthorizationCodeGrantOutcome'],
|
|
111
|
+
fn() {
|
|
112
|
+
return this._initialAuthorizationCodeGrantOutcome;
|
|
113
|
+
},
|
|
114
|
+
},
|
|
72
115
|
/**
|
|
73
116
|
* Alias of {@link AuthorizationBrowserFirstParty#isAuthorizing}
|
|
74
117
|
* @instance
|
|
@@ -94,6 +137,14 @@ const Authorization = WebexPlugin.extend({
|
|
|
94
137
|
default: false,
|
|
95
138
|
type: 'boolean',
|
|
96
139
|
},
|
|
140
|
+
/**
|
|
141
|
+
* Internal backing state for the initial authorization-code grant outcome.
|
|
142
|
+
* @private
|
|
143
|
+
*/
|
|
144
|
+
_initialAuthorizationCodeGrantOutcome: {
|
|
145
|
+
default: InitialAuthorizationCodeGrantOutcomes.notAttempted,
|
|
146
|
+
type: 'string',
|
|
147
|
+
},
|
|
97
148
|
/**
|
|
98
149
|
* Indicates that the plugin has finished any automatic startup
|
|
99
150
|
* processing (e.g., exchanging a returned authorization code)
|
|
@@ -233,7 +284,13 @@ const Authorization = WebexPlugin.extend({
|
|
|
233
284
|
.collectPreauthCatalog(preauthCatalogParams)
|
|
234
285
|
.catch(() => Promise.resolve()) // Non-fatal if catalog collection fails
|
|
235
286
|
.then(() => this.requestAuthorizationCodeGrant({code, codeVerifier}))
|
|
287
|
+
.then(() => {
|
|
288
|
+
this._initialAuthorizationCodeGrantOutcome =
|
|
289
|
+
InitialAuthorizationCodeGrantOutcomes.success;
|
|
290
|
+
})
|
|
236
291
|
.catch((error) => {
|
|
292
|
+
this._initialAuthorizationCodeGrantOutcome =
|
|
293
|
+
InitialAuthorizationCodeGrantOutcomes.failure;
|
|
237
294
|
this.logger.warn('authorization: failed initial authorization code grant request', error);
|
|
238
295
|
})
|
|
239
296
|
.then(() => {
|
|
@@ -424,7 +481,12 @@ const Authorization = WebexPlugin.extend({
|
|
|
424
481
|
this._verifySecurityToken(location.query, {requireMatch: true});
|
|
425
482
|
this._cleanUrl(location);
|
|
426
483
|
|
|
427
|
-
const {
|
|
484
|
+
const {
|
|
485
|
+
id_token: idToken,
|
|
486
|
+
email,
|
|
487
|
+
error,
|
|
488
|
+
state: {csrf_token, ...state},
|
|
489
|
+
} = location.query;
|
|
428
490
|
|
|
429
491
|
return {idToken, email, error, state};
|
|
430
492
|
},
|
package/src/index.js
CHANGED
|
@@ -14,7 +14,7 @@ import {base64, patterns} from '@webex/common';
|
|
|
14
14
|
import {merge, times} from 'lodash';
|
|
15
15
|
import CryptoJS from 'crypto-js';
|
|
16
16
|
import Authorization from '@webex/plugin-authorization-browser-first-party';
|
|
17
|
-
import {Events} from '../../../src';
|
|
17
|
+
import {Events, InitialAuthorizationCodeGrantOutcomes} from '../../../src';
|
|
18
18
|
|
|
19
19
|
// Necessary to require lodash this way in order to stub the method
|
|
20
20
|
const lodash = require('lodash');
|
|
@@ -104,6 +104,35 @@ describe('plugin-authorization-browser-first-party', () => {
|
|
|
104
104
|
sinon.restore();
|
|
105
105
|
});
|
|
106
106
|
|
|
107
|
+
it('exposes the initial authorization code grant outcome as readonly', () => {
|
|
108
|
+
const webex = makeWebex();
|
|
109
|
+
const changeSpy = sinon.spy();
|
|
110
|
+
|
|
111
|
+
webex.authorization.on('change:initialAuthorizationCodeGrantOutcome', changeSpy);
|
|
112
|
+
|
|
113
|
+
assert.equal(
|
|
114
|
+
webex.authorization.initialAuthorizationCodeGrantOutcome,
|
|
115
|
+
InitialAuthorizationCodeGrantOutcomes.notAttempted
|
|
116
|
+
);
|
|
117
|
+
assert.throws(() => {
|
|
118
|
+
webex.authorization.initialAuthorizationCodeGrantOutcome =
|
|
119
|
+
InitialAuthorizationCodeGrantOutcomes.success;
|
|
120
|
+
}, /derived property, it can't be set directly/);
|
|
121
|
+
|
|
122
|
+
webex.authorization._initialAuthorizationCodeGrantOutcome =
|
|
123
|
+
InitialAuthorizationCodeGrantOutcomes.success;
|
|
124
|
+
|
|
125
|
+
assert.equal(
|
|
126
|
+
webex.authorization.initialAuthorizationCodeGrantOutcome,
|
|
127
|
+
InitialAuthorizationCodeGrantOutcomes.success
|
|
128
|
+
);
|
|
129
|
+
assert.calledOnceWithExactly(
|
|
130
|
+
changeSpy,
|
|
131
|
+
webex.authorization,
|
|
132
|
+
InitialAuthorizationCodeGrantOutcomes.success
|
|
133
|
+
);
|
|
134
|
+
});
|
|
135
|
+
|
|
107
136
|
describe('#initialize()', () => {
|
|
108
137
|
describe('when there is a code in the url', () => {
|
|
109
138
|
it('exchanges it for an access token and sets ready', () => {
|
|
@@ -119,9 +148,25 @@ describe('plugin-authorization-browser-first-party', () => {
|
|
|
119
148
|
assert.calledTwice(webex.request);
|
|
120
149
|
assert.isTrue(webex.authorization.ready);
|
|
121
150
|
assert.isTrue(webex.credentials.canAuthorize);
|
|
151
|
+
assert.equal(
|
|
152
|
+
webex.authorization.initialAuthorizationCodeGrantOutcome,
|
|
153
|
+
InitialAuthorizationCodeGrantOutcomes.success
|
|
154
|
+
);
|
|
122
155
|
});
|
|
123
156
|
});
|
|
124
157
|
|
|
158
|
+
it('retains the initialization exchange outcome after logout', async () => {
|
|
159
|
+
const webex = makeWebex('http://example.com/?code=5');
|
|
160
|
+
|
|
161
|
+
await webex.authorization.when('change:ready');
|
|
162
|
+
webex.authorization.logout({noRedirect: true});
|
|
163
|
+
|
|
164
|
+
assert.equal(
|
|
165
|
+
webex.authorization.initialAuthorizationCodeGrantOutcome,
|
|
166
|
+
InitialAuthorizationCodeGrantOutcomes.success
|
|
167
|
+
);
|
|
168
|
+
});
|
|
169
|
+
|
|
125
170
|
it('validates the csrf token', () => {
|
|
126
171
|
const csrfToken = 'abcd';
|
|
127
172
|
|
|
@@ -264,8 +309,32 @@ describe('plugin-authorization-browser-first-party', () => {
|
|
|
264
309
|
'authorization: failed initial authorization code grant request',
|
|
265
310
|
error
|
|
266
311
|
);
|
|
312
|
+
assert.equal(
|
|
313
|
+
webex.authorization.initialAuthorizationCodeGrantOutcome,
|
|
314
|
+
InitialAuthorizationCodeGrantOutcomes.failure
|
|
315
|
+
);
|
|
267
316
|
});
|
|
268
317
|
});
|
|
318
|
+
|
|
319
|
+
it('retains failure when the automatic exchange promise rejects', async () => {
|
|
320
|
+
const error = new Error('exchange rejected');
|
|
321
|
+
|
|
322
|
+
sinon.stub(Authorization.prototype, 'requestAuthorizationCodeGrant').rejects(error);
|
|
323
|
+
|
|
324
|
+
const webex = makeWebex('http://example.com?code=5');
|
|
325
|
+
|
|
326
|
+
await webex.authorization.when('change:ready');
|
|
327
|
+
|
|
328
|
+
assert.equal(
|
|
329
|
+
webex.authorization.initialAuthorizationCodeGrantOutcome,
|
|
330
|
+
InitialAuthorizationCodeGrantOutcomes.failure
|
|
331
|
+
);
|
|
332
|
+
assert.calledOnceWithExactly(
|
|
333
|
+
webex.logger.warn,
|
|
334
|
+
'authorization: failed initial authorization code grant request',
|
|
335
|
+
error
|
|
336
|
+
);
|
|
337
|
+
});
|
|
269
338
|
});
|
|
270
339
|
describe('when the url contains an error', () => {
|
|
271
340
|
it('throws a grant error', () => {
|
|
@@ -287,6 +356,21 @@ describe('plugin-authorization-browser-first-party', () => {
|
|
|
287
356
|
|
|
288
357
|
assert.isTrue(webex.authorization.ready);
|
|
289
358
|
assert.isFalse(webex.credentials.canAuthorize);
|
|
359
|
+
assert.equal(
|
|
360
|
+
webex.authorization.initialAuthorizationCodeGrantOutcome,
|
|
361
|
+
InitialAuthorizationCodeGrantOutcomes.notAttempted
|
|
362
|
+
);
|
|
363
|
+
});
|
|
364
|
+
|
|
365
|
+
it('does not treat a later authorization-code grant as the initialization exchange', async () => {
|
|
366
|
+
const webex = makeWebex('http://example.com');
|
|
367
|
+
|
|
368
|
+
await webex.authorization.requestAuthorizationCodeGrant({code: 'later-code'});
|
|
369
|
+
|
|
370
|
+
assert.equal(
|
|
371
|
+
webex.authorization.initialAuthorizationCodeGrantOutcome,
|
|
372
|
+
InitialAuthorizationCodeGrantOutcomes.notAttempted
|
|
373
|
+
);
|
|
290
374
|
});
|
|
291
375
|
});
|
|
292
376
|
|