@webex/plugin-authorization-browser 3.8.0 → 3.8.1-next.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -24,23 +24,23 @@
24
24
  "@webex/eslint-config-legacy": "0.0.0",
25
25
  "@webex/jest-config-legacy": "0.0.0",
26
26
  "@webex/legacy-tools": "0.0.0",
27
- "@webex/test-helper-appid": "3.8.0",
28
- "@webex/test-helper-automation": "3.8.0",
29
- "@webex/test-helper-chai": "3.8.0",
30
- "@webex/test-helper-mocha": "3.8.0",
31
- "@webex/test-helper-mock-webex": "3.8.0",
32
- "@webex/test-helper-test-users": "3.8.0",
27
+ "@webex/test-helper-appid": "3.8.1-next.2",
28
+ "@webex/test-helper-automation": "3.8.1-next.2",
29
+ "@webex/test-helper-chai": "3.8.1-next.2",
30
+ "@webex/test-helper-mocha": "3.8.1-next.2",
31
+ "@webex/test-helper-mock-webex": "3.8.1-next.2",
32
+ "@webex/test-helper-test-users": "3.8.1-next.2",
33
33
  "eslint": "^8.24.0",
34
34
  "prettier": "^2.7.1",
35
35
  "sinon": "^9.2.4"
36
36
  },
37
37
  "dependencies": {
38
- "@webex/common": "3.8.0",
39
- "@webex/internal-plugin-device": "3.8.0",
40
- "@webex/plugin-authorization-node": "3.8.0",
41
- "@webex/storage-adapter-local-storage": "3.8.0",
42
- "@webex/storage-adapter-spec": "3.8.0",
43
- "@webex/webex-core": "3.8.0",
38
+ "@webex/common": "3.8.1-next.2",
39
+ "@webex/internal-plugin-device": "3.8.1-next.2",
40
+ "@webex/plugin-authorization-node": "3.8.1-next.2",
41
+ "@webex/storage-adapter-local-storage": "3.8.1-next.2",
42
+ "@webex/storage-adapter-spec": "3.8.1-next.2",
43
+ "@webex/webex-core": "3.8.1-next.2",
44
44
  "jsonwebtoken": "^9.0.2",
45
45
  "lodash": "^4.17.21",
46
46
  "uuid": "^3.3.2"
@@ -54,5 +54,5 @@
54
54
  "test:style": "eslint ./src/**/*.*",
55
55
  "test:unit": "webex-legacy-tools test --unit --runner jest"
56
56
  },
57
- "version": "3.8.0"
57
+ "version": "3.8.1-next.2"
58
58
  }
@@ -113,13 +113,26 @@ const Authorization = WebexPlugin.extend({
113
113
  return ret;
114
114
  },
115
115
 
116
- /**
117
- * Kicks off an oauth flow
118
- * @instance
119
- * @memberof AuthorizationBrowser
120
- * @param {Object} options
121
- * @returns {Promise}
122
- */
116
+ /**
117
+ * Initiates the OAuth flow for user authentication.
118
+ * This function determines the type of OAuth flow to use based on the client type configuration.
119
+ * If the client is configured as "confidential", it will initiate the Authorization Code Grant flow;
120
+ * otherwise, it will initiate the Implicit Grant flow.
121
+ *
122
+ * @instance
123
+ * @memberof AuthorizationBrowser
124
+ * @param {Object} options - The options to configure the OAuth flow.
125
+ * @param {Object} [options.state] - An optional state object that can be used to include additional
126
+ * information such as security tokens. A CSRF token will be automatically generated and added to
127
+ * this state object.
128
+ * @param {boolean|Object} [options.separateWindow] - Determines if the login should open in a separate window.
129
+ * This can be a boolean or an object specifying window features:
130
+ * - If `true`, a new window with default dimensions is opened.
131
+ * - If an object, custom window features can be specified (e.g., `{width: 800, height: 600}`).
132
+ * @returns {Promise<void>} - A promise that resolves when the appropriate OAuth flow has been initiated.
133
+ * The promise does not necessarily indicate the completion of the login process.
134
+ * @throws {Error} - Throws an error if there are issues initiating the OAuth flow.
135
+ */
123
136
  initiateLogin(options = {}) {
124
137
  options.state = options.state || {};
125
138
  options.state.csrf_token = this._generateSecurityToken();
@@ -134,20 +147,52 @@ const Authorization = WebexPlugin.extend({
134
147
  },
135
148
 
136
149
  @whileInFlight('isAuthorizing')
137
- /**
138
- * Kicks off the Authorization Code grant flow. Typically called via
139
- * {@link AuthorizationBrowser#initiateLogin}
140
- * @instance
141
- * @memberof AuthorizationBrowser
142
- * @param {Object} options
143
- * @returns {Promise}
144
- */
150
+ /**
151
+ * Initiates the Implicit Grant flow for authorization.
152
+ * This function constructs the login URL and either opens it in a new
153
+ * window or in the current window based on the provided options.
154
+ * Typically called via {@link AuthorizationBrowser#initiateLogin}.
155
+ *
156
+ * @instance
157
+ * @memberof AuthorizationBrowser
158
+ * @param {Object} options - The options to configure the login flow.
159
+ * @param {Object} [options.separateWindow] - Determines if the login should open in a separate window.
160
+ * This can be a boolean or an object specifying window features:
161
+ * - If `true`, a new window with default dimensions is opened.
162
+ * - If an object, custom window features can be specified (e.g., `{width: 800, height: 600}`).
163
+ * @returns {Promise<void>} - A promise that resolves immediately after initiating the login flow.
164
+ * This promise does not indicate the completion of the login process.
165
+ * @throws {Error} - Throws an error if the login URL cannot be constructed or if window opening fails.
166
+ */
145
167
  initiateImplicitGrant(options) {
168
+
146
169
  this.logger.info('authorization: initiating implicit grant flow');
147
- this.webex.getWindow().location = this.webex.credentials.buildLoginUrl(
170
+ const loginUrl = this.webex.credentials.buildLoginUrl(
148
171
  Object.assign({response_type: 'token'}, options)
149
172
  );
150
173
 
174
+ if (options?.separateWindow) {
175
+ // Default window settings
176
+ const defaultWindowSettings = {
177
+ width: 600,
178
+ height: 800
179
+ };
180
+
181
+ // Merge user provided settings with defaults
182
+ const windowSettings = Object.assign(
183
+ defaultWindowSettings,
184
+ typeof options.separateWindow === 'object' ? options.separateWindow : {}
185
+ );
186
+ // Convert settings object to window.open features string
187
+ const windowFeatures = Object.entries(windowSettings)
188
+ .map(([key, value]) => `${key}=${value}`)
189
+ .join(',');
190
+ this.webex.getWindow().open(loginUrl, '_blank', windowFeatures);
191
+ } else {
192
+ // Default behavior - open in same window
193
+ this.webex.getWindow().location = loginUrl;
194
+ }
195
+
151
196
  return Promise.resolve();
152
197
  },
153
198
 
@@ -408,6 +408,65 @@ describe('plugin-authorization-browser', () => {
408
408
  assert.include(webex.getWindow().location, 'response_type=token');
409
409
  });
410
410
  });
411
+
412
+ it('redirects to the login page in the same window by default', () => {
413
+ const webex = makeWebexCore();
414
+
415
+ return webex.authorization.initiateImplicitGrant().then(() => {
416
+ assert.isDefined(webex.getWindow().location);
417
+ assert.isUndefined(webex.getWindow().open);
418
+ });
419
+ });
420
+
421
+ it('opens login page in a new window when separateWindow is true', () => {
422
+ const webex = makeWebexCore();
423
+ webex.getWindow().open = sinon.spy();
424
+
425
+ return webex.authorization.initiateImplicitGrant({ separateWindow: true }).then(() => {
426
+ assert.called(webex.getWindow().open);
427
+ const openCall = webex.getWindow().open.getCall(0);
428
+ assert.equal(openCall.args[1], '_blank');
429
+ assert.equal(openCall.args[2], 'width=600,height=800');
430
+ });
431
+ });
432
+
433
+ it('opens login page in a new window with custom dimensions', () => {
434
+ const webex = makeWebexCore();
435
+ webex.getWindow().open = sinon.spy();
436
+
437
+ const customWindow = {
438
+ width: 800,
439
+ height: 600,
440
+ menubar: 'no',
441
+ toolbar: 'no'
442
+ };
443
+
444
+ return webex.authorization.initiateImplicitGrant({
445
+ separateWindow: customWindow
446
+ }).then(() => {
447
+ assert.called(webex.getWindow().open);
448
+ const openCall = webex.getWindow().open.getCall(0);
449
+ assert.equal(openCall.args[1], '_blank');
450
+ assert.equal(
451
+ openCall.args[2],
452
+ 'width=800,height=600,menubar=no,toolbar=no'
453
+ );
454
+ });
455
+ });
456
+
457
+ it('preserves other options when using separateWindow', () => {
458
+ const webex = makeWebexCore();
459
+ webex.getWindow().open = sinon.spy();
460
+
461
+ return webex.authorization.initiateImplicitGrant({
462
+ separateWindow: true,
463
+ state: {}
464
+ }).then(() => {
465
+ assert.called(webex.getWindow().open);
466
+ const url = webex.getWindow().open.getCall(0).args[0];
467
+ assert.include(url, "https://idbrokerbts.webex.com/idb/oauth2/v1/authorize?response_type=token&separateWindow=true&client_id=fake&redirect_uri=http%3A%2F%2Fexample.com&scope=scope%3Aone");
468
+ });
469
+ });
411
470
  });
412
471
 
413
472
  describe('#initiateAuthorizationCodeGrant()', () => {