@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/README.md CHANGED
@@ -1,14 +1,38 @@
1
1
  # @webex/plugin-authorization-browser
2
2
 
3
- [![standard-readme compliant](https://img.shields.io/badge/readme%20style-standard-brightgreen.svg?style=flat-square)](https://github.com/RichardLitt/standard-readme)
3
+ > OAuth2 authorization plugin for browser environments in the Cisco Webex JS SDK. Handles OAuth2 flows including Implicit Grant and Authorization Code Grant for web applications.
4
4
 
5
- > Authorization plugin loaded when the Cisco Webex JS SDK is used in a web browser.
5
+ ## Table of Contents
6
6
 
7
- - [Install](#install)
8
- - [Usage](#usage)
9
- - [Contribute](#contribute)
10
- - [Maintainers](#maintainers)
11
- - [License](#license)
7
+ - [@webex/plugin-authorization-browser](#webexplugin-authorization-browser)
8
+ - [Table of Contents](#table-of-contents)
9
+ - [Install](#install)
10
+ - [What it Does](#what-it-does)
11
+ - [Usage](#usage)
12
+ - [Basic OAuth2 Login](#basic-oauth2-login)
13
+ - [Implicit Grant Flow](#implicit-grant-flow)
14
+ - [Authorization Code Grant Flow](#authorization-code-grant-flow)
15
+ - [Login with Popup Window](#login-with-popup-window)
16
+ - [JWT Authentication](#jwt-authentication)
17
+ - [Guest JWT Creation](#guest-jwt-creation)
18
+ - [Logout](#logout)
19
+ - [Checking Authentication Status](#checking-authentication-status)
20
+ - [Error Handling](#error-handling)
21
+ - [API Reference](#api-reference)
22
+ - [Methods](#methods)
23
+ - [`initiateLogin(options)`](#initiateloginoptions)
24
+ - [`initiateImplicitGrant(options)`](#initiateimplicitgrantoptions)
25
+ - [`initiateAuthorizationCodeGrant(options)`](#initiateauthorizationcodegrantoptions)
26
+ - [`requestAccessTokenFromJwt({ jwt })`](#requestaccesstokenfromjwt-jwt-)
27
+ - [`createJwt(options)`](#createjwtoptions)
28
+ - [`logout(options)`](#logoutoptions)
29
+ - [Properties](#properties)
30
+ - [`isAuthorizing` (boolean)](#isauthorizing-boolean)
31
+ - [`isAuthenticating` (boolean)](#isauthenticating-boolean)
32
+ - [`ready` (boolean)](#ready-boolean)
33
+ - [Maintainers](#maintainers)
34
+ - [Contribute](#contribute)
35
+ - [License](#license)
12
36
 
13
37
  ## Install
14
38
 
@@ -16,38 +40,301 @@
16
40
  npm install --save @webex/plugin-authorization-browser
17
41
  ```
18
42
 
43
+ ## What it Does
44
+
45
+ The `@webex/plugin-authorization-browser` plugin provides OAuth2 authentication capabilities specifically for browser environments. It:
46
+
47
+ - **Automatically handles OAuth2 flows**: Supports both Implicit Grant and Authorization Code Grant flows
48
+ - **Manages authentication state**: Tracks authorization status and handles token parsing from URL
49
+ - **Provides CSRF protection**: Generates and validates CSRF tokens for security
50
+ - **Supports popup authentication**: Can open login in a separate window
51
+ - **JWT token support**: Create and use JWT tokens for guest authentication
52
+ - **URL cleanup**: Automatically removes sensitive tokens from browser URL after authentication
53
+ - **Cross-browser compatibility**: Works across different browser environments
54
+
19
55
  ## Usage
20
56
 
21
- This is a plugin for the Cisco Webex JS SDK . Please see our [developer portal](https://developer.webex.com/) and the [API docs](https://webex.github.io/webex-js-sdk/api/) for full details.
57
+ ### Basic OAuth2 Login
22
58
 
23
- ## Install
59
+ The simplest way to authenticate users:
24
60
 
25
- ```bash
26
- npm install --save @webex/plugin-authorization-browser
61
+ ```javascript
62
+ const Webex = require('webex');
63
+
64
+ // Initialize Webex SDK
65
+ const webex = Webex.init({
66
+ credentials: {
67
+ client_id: 'your-client-id',
68
+ redirect_uri: 'https://your-app.com/callback',
69
+ scope: 'spark:all'
70
+ }
71
+ });
72
+
73
+ // Start the login process
74
+ webex.authorization.initiateLogin()
75
+ .then(() => {
76
+ console.log('Login initiated');
77
+ // User will be redirected to Webex login page
78
+ });
79
+
80
+ // After redirect, check if user is authenticated
81
+ if (webex.canAuthorize) {
82
+ console.log('User is authenticated');
83
+ // Make API calls
84
+ }
27
85
  ```
28
86
 
29
- ## Usage
87
+ ### Implicit Grant Flow
30
88
 
31
- ```js
89
+ For public clients (single-page applications):
32
90
 
33
- const Webex = require('webex');
91
+ ```javascript
92
+ const webex = Webex.init({
93
+ credentials: {
94
+ client_id: 'your-client-id',
95
+ redirect_uri: 'https://your-app.com/callback',
96
+ scope: 'spark:all'
97
+ // No client_secret for public clients
98
+ }
99
+ });
100
+
101
+ // Initiate implicit grant flow
102
+ webex.authorization.initiateImplicitGrant({
103
+ state: { customData: 'value' } // Optional state data
104
+ })
105
+ .then(() => {
106
+ console.log('Implicit grant flow started');
107
+ });
108
+ ```
109
+
110
+ ### Authorization Code Grant Flow
111
+
112
+ For confidential clients with client secret:
113
+
114
+ ```javascript
115
+ const webex = Webex.init({
116
+ credentials: {
117
+ client_id: 'your-client-id',
118
+ client_secret: 'your-client-secret',
119
+ redirect_uri: 'https://your-app.com/callback',
120
+ scope: 'spark:all',
121
+ clientType: 'confidential' // This triggers authorization code flow
122
+ }
123
+ });
124
+
125
+ // Initiate authorization code grant flow
126
+ webex.authorization.initiateAuthorizationCodeGrant({
127
+ state: { customData: 'value' }
128
+ })
129
+ .then(() => {
130
+ console.log('Authorization code flow started');
131
+ });
132
+ ```
133
+
134
+ ### Login with Popup Window
135
+
136
+ Open login in a separate popup window instead of redirecting:
137
+
138
+ ```javascript
139
+ // Basic popup with default dimensions (600x800)
140
+ webex.authorization.initiateLogin({
141
+ separateWindow: true
142
+ });
143
+
144
+ // Custom popup dimensions
145
+ webex.authorization.initiateLogin({
146
+ separateWindow: {
147
+ width: 800,
148
+ height: 600
149
+ }
150
+ });
151
+
152
+ // With custom state and popup
153
+ webex.authorization.initiateLogin({
154
+ state: {
155
+ returnUrl: '/dashboard',
156
+ userId: 'user123'
157
+ },
158
+ separateWindow: {
159
+ width: 900,
160
+ height: 700
161
+ }
162
+ });
163
+ ```
164
+
165
+ ### JWT Authentication
166
+
167
+ Authenticate using a JWT token (useful for guest users):
168
+
169
+ ```javascript
170
+ // Assuming you have a JWT from your backend
171
+ const jwtToken = '<YOUR_JWT_TOKEN_HERE>';
172
+
173
+ webex.authorization.requestAccessTokenFromJwt({
174
+ jwt: jwtToken
175
+ })
176
+ .then(() => {
177
+ console.log('Authenticated with JWT');
178
+ // User is now authenticated and can make API calls
179
+ })
180
+ .catch(error => {
181
+ console.error('JWT authentication failed:', error);
182
+ });
183
+ ```
184
+
185
+ ### Guest JWT Creation
186
+
187
+ Create JWT tokens for guest users:
188
+
189
+ ```javascript
190
+ // Create a guest JWT token
191
+ webex.authorization.createJwt({
192
+ issuer: 'your-guest-issuer-id',
193
+ secretId: 'your-base64-encoded-secret',
194
+ displayName: 'Guest User Name', // Optional
195
+ expiresIn: '12h' // Token expiration
196
+ })
197
+ .then(({ jwt }) => {
198
+ console.log('Created guest JWT:', jwt);
199
+
200
+ // Use the JWT to authenticate
201
+ return webex.authorization.requestAccessTokenFromJwt({ jwt });
202
+ })
203
+ .then(() => {
204
+ console.log('Guest user authenticated');
205
+ })
206
+ .catch(error => {
207
+ console.error('Guest JWT creation failed:', error);
208
+ });
209
+ ```
210
+
211
+ ### Logout
212
+
213
+ Log out the current user:
214
+
215
+ ```javascript
216
+ // Logout and redirect to Webex logout page
217
+ webex.authorization.logout();
34
218
 
35
- const webex = Webex.init();
36
- webex.authorization-browser.get(id)
37
- .then((authorization-browser) => {
38
- console.log(authorization-browser);
39
- })
219
+ // Logout without redirect (clean up local session only)
220
+ webex.authorization.logout({ noRedirect: true });
40
221
 
222
+ // Logout with custom logout URL
223
+ webex.authorization.logout({
224
+ goto: 'https://your-app.com/goodbye'
225
+ });
41
226
  ```
42
227
 
228
+ ### Checking Authentication Status
229
+
230
+ ```javascript
231
+ // Check if SDK can authorize (has valid token)
232
+ if (webex.canAuthorize) {
233
+ console.log('User is authenticated');
234
+ }
235
+
236
+ // Check if authorization is in progress
237
+ if (webex.authorization.isAuthorizing) {
238
+ console.log('Authorization in progress...');
239
+ }
240
+
241
+ // Listen for authentication events
242
+ webex.on('ready', () => {
243
+ console.log('SDK is ready and authenticated');
244
+ });
245
+
246
+ webex.on('unauthorized', () => {
247
+ console.log('User is not authenticated');
248
+ });
249
+ ```
250
+
251
+ ### Error Handling
252
+
253
+ ```javascript
254
+ // Handle authentication errors from URL
255
+ try {
256
+ const webex = Webex.init({
257
+ credentials: { /* your config */ }
258
+ });
259
+ } catch (error) {
260
+ if (error.name === 'OAuthError') {
261
+ console.error('OAuth error:', error.message);
262
+ // Handle specific OAuth errors like access_denied
263
+ }
264
+ }
265
+
266
+ // Handle JWT authentication errors
267
+ webex.authorization.requestAccessTokenFromJwt({ jwt: 'invalid-jwt' })
268
+ .catch(error => {
269
+ console.error('JWT authentication failed:', error);
270
+ });
271
+ ```
272
+
273
+ ## API Reference
274
+
275
+ ### Methods
276
+
277
+ #### `initiateLogin(options)`
278
+
279
+ Initiates the appropriate OAuth flow based on client configuration.
280
+
281
+ - `options.state` - Optional state object for custom data
282
+ - `options.separateWindow` - Boolean or object for popup window settings
283
+
284
+ #### `initiateImplicitGrant(options)`
285
+
286
+ Starts the Implicit Grant flow for public clients.
287
+
288
+ #### `initiateAuthorizationCodeGrant(options)`
289
+
290
+ Starts the Authorization Code Grant flow for confidential clients.
291
+
292
+ #### `requestAccessTokenFromJwt({ jwt })`
293
+
294
+ Exchanges a JWT for an access token.
295
+
296
+ #### `createJwt(options)`
297
+
298
+ Creates a JWT token for guest authentication.
299
+
300
+ - `options.issuer` - Guest issuer ID
301
+ - `options.secretId` - Base64 encoded secret
302
+ - `options.displayName` - Optional display name
303
+ - `options.expiresIn` - Token expiration time
304
+
305
+ #### `logout(options)`
306
+
307
+ Logs out the current user.
308
+
309
+ - `options.noRedirect` - Skip redirect to logout page
310
+ - `options.goto` - Custom redirect URL after logout
311
+
312
+ ### Properties
313
+
314
+ #### `isAuthorizing` (boolean)
315
+
316
+ Indicates if an authorization flow is currently in progress.
317
+
318
+ #### `isAuthenticating` (boolean)
319
+
320
+ Alias for `isAuthorizing`.
321
+
322
+ #### `ready` (boolean)
323
+
324
+ Indicates if the authorization plugin has finished initialization.
325
+
326
+ ---
327
+
43
328
  ## Maintainers
44
329
 
45
- This package is maintained by [Cisco Webex for Developers](https://developer.webex.com/).
330
+ This package is maintained by Cisco Webex for Developers.
46
331
 
47
332
  ## Contribute
48
333
 
49
- Pull requests welcome. Please see [CONTRIBUTING.md](https://github.com/webex/webex-js-sdk/blob/master/CONTRIBUTING.md) for more details.
334
+ Pull requests welcome. Please see CONTRIBUTING.md for more details.
50
335
 
51
336
  ## License
52
337
 
53
- © 2016-2020 Cisco and/or its affiliates. All Rights Reserved.
338
+ This project is licensed under the Cisco General Terms - see the LICENSE for details.
339
+
340
+ © 2016-2025 Cisco and/or its affiliates. All Rights Reserved.
@@ -8,10 +8,13 @@ _Object$defineProperty(exports, "__esModule", {
8
8
  exports.default = void 0;
9
9
  var _regenerator = _interopRequireDefault(require("@babel/runtime-corejs2/regenerator"));
10
10
  var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/asyncToGenerator"));
11
+ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/slicedToArray"));
12
+ var _typeof2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/typeof"));
11
13
  var _applyDecoratedDescriptor2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/applyDecoratedDescriptor"));
12
14
  var _stringify = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/json/stringify"));
13
15
  var _apply = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/reflect/apply"));
14
16
  var _assign = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/object/assign"));
17
+ var _entries = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/object/entries"));
15
18
  var _promise = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/promise"));
16
19
  var _deleteProperty = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/reflect/delete-property"));
17
20
  var _parseInt2 = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/parse-int"));
@@ -121,11 +124,24 @@ var Authorization = _webexCore.WebexPlugin.extend((_dec = (0, _common.whileInFli
121
124
  return ret;
122
125
  },
123
126
  /**
124
- * Kicks off an oauth flow
127
+ * Initiates the OAuth flow for user authentication.
128
+ * This function determines the type of OAuth flow to use based on the client type configuration.
129
+ * If the client is configured as "confidential", it will initiate the Authorization Code Grant flow;
130
+ * otherwise, it will initiate the Implicit Grant flow.
131
+ *
125
132
  * @instance
126
133
  * @memberof AuthorizationBrowser
127
- * @param {Object} options
128
- * @returns {Promise}
134
+ * @param {Object} options - The options to configure the OAuth flow.
135
+ * @param {Object} [options.state] - An optional state object that can be used to include additional
136
+ * information such as security tokens. A CSRF token will be automatically generated and added to
137
+ * this state object.
138
+ * @param {boolean|Object} [options.separateWindow] - Determines if the login should open in a separate window.
139
+ * This can be a boolean or an object specifying window features:
140
+ * - If `true`, a new window with default dimensions is opened.
141
+ * - If an object, custom window features can be specified (e.g., `{width: 800, height: 600}`).
142
+ * @returns {Promise<void>} - A promise that resolves when the appropriate OAuth flow has been initiated.
143
+ * The promise does not necessarily indicate the completion of the login process.
144
+ * @throws {Error} - Throws an error if there are issues initiating the OAuth flow.
129
145
  */
130
146
  initiateLogin: function initiateLogin() {
131
147
  var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
@@ -140,18 +156,48 @@ var Authorization = _webexCore.WebexPlugin.extend((_dec = (0, _common.whileInFli
140
156
  return this.initiateImplicitGrant(options);
141
157
  },
142
158
  /**
143
- * Kicks off the Authorization Code grant flow. Typically called via
144
- * {@link AuthorizationBrowser#initiateLogin}
159
+ * Initiates the Implicit Grant flow for authorization.
160
+ * This function constructs the login URL and either opens it in a new
161
+ * window or in the current window based on the provided options.
162
+ * Typically called via {@link AuthorizationBrowser#initiateLogin}.
163
+ *
145
164
  * @instance
146
165
  * @memberof AuthorizationBrowser
147
- * @param {Object} options
148
- * @returns {Promise}
166
+ * @param {Object} options - The options to configure the login flow.
167
+ * @param {Object} [options.separateWindow] - Determines if the login should open in a separate window.
168
+ * This can be a boolean or an object specifying window features:
169
+ * - If `true`, a new window with default dimensions is opened.
170
+ * - If an object, custom window features can be specified (e.g., `{width: 800, height: 600}`).
171
+ * @returns {Promise<void>} - A promise that resolves immediately after initiating the login flow.
172
+ * This promise does not indicate the completion of the login process.
173
+ * @throws {Error} - Throws an error if the login URL cannot be constructed or if window opening fails.
149
174
  */
150
175
  initiateImplicitGrant: function initiateImplicitGrant(options) {
151
176
  this.logger.info('authorization: initiating implicit grant flow');
152
- this.webex.getWindow().location = this.webex.credentials.buildLoginUrl((0, _assign.default)({
177
+ var loginUrl = this.webex.credentials.buildLoginUrl((0, _assign.default)({
153
178
  response_type: 'token'
154
179
  }, options));
180
+ if (options !== null && options !== void 0 && options.separateWindow) {
181
+ // Default window settings
182
+ var defaultWindowSettings = {
183
+ width: 600,
184
+ height: 800
185
+ };
186
+
187
+ // Merge user provided settings with defaults
188
+ var windowSettings = (0, _assign.default)(defaultWindowSettings, (0, _typeof2.default)(options.separateWindow) === 'object' ? options.separateWindow : {});
189
+ // Convert settings object to window.open features string
190
+ var windowFeatures = (0, _entries.default)(windowSettings).map(function (_ref) {
191
+ var _ref2 = (0, _slicedToArray2.default)(_ref, 2),
192
+ key = _ref2[0],
193
+ value = _ref2[1];
194
+ return "".concat(key, "=").concat(value);
195
+ }).join(',');
196
+ this.webex.getWindow().open(loginUrl, '_blank', windowFeatures);
197
+ } else {
198
+ // Default behavior - open in same window
199
+ this.webex.getWindow().location = loginUrl;
200
+ }
155
201
  return _promise.default.resolve();
156
202
  },
157
203
  /**
@@ -184,9 +230,9 @@ var Authorization = _webexCore.WebexPlugin.extend((_dec = (0, _common.whileInFli
184
230
  * identifies a user in your system
185
231
  * @returns {Promise}
186
232
  */
187
- requestAccessTokenFromJwt: function requestAccessTokenFromJwt(_ref) {
233
+ requestAccessTokenFromJwt: function requestAccessTokenFromJwt(_ref3) {
188
234
  var _this2 = this;
189
- var jwt = _ref.jwt;
235
+ var jwt = _ref3.jwt;
190
236
  var hydraUri = this.webex.internal.services.get('hydra', true);
191
237
  if (hydraUri && hydraUri.slice(-1) !== '/') {
192
238
  // add a `/` to hydra's uri from the services catalog so that
@@ -200,8 +246,8 @@ var Authorization = _webexCore.WebexPlugin.extend((_dec = (0, _common.whileInFli
200
246
  headers: {
201
247
  authorization: jwt
202
248
  }
203
- }).then(function (_ref2) {
204
- var body = _ref2.body;
249
+ }).then(function (_ref4) {
250
+ var body = _ref4.body;
205
251
  return {
206
252
  access_token: body.token,
207
253
  token_type: 'Bearer',
@@ -238,13 +284,13 @@ var Authorization = _webexCore.WebexPlugin.extend((_dec = (0, _common.whileInFli
238
284
  * @param {String} options.expiresIn
239
285
  * @returns {Promise<object>}
240
286
  */
241
- createJwt: function createJwt(_ref3) {
287
+ createJwt: function createJwt(_ref5) {
242
288
  return (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee() {
243
289
  var issuer, secretId, displayName, expiresIn, secret, payload, alg, jwtToken;
244
290
  return _regenerator.default.wrap(function _callee$(_context) {
245
291
  while (1) switch (_context.prev = _context.next) {
246
292
  case 0:
247
- issuer = _ref3.issuer, secretId = _ref3.secretId, displayName = _ref3.displayName, expiresIn = _ref3.expiresIn;
293
+ issuer = _ref5.issuer, secretId = _ref5.secretId, displayName = _ref5.displayName, expiresIn = _ref5.expiresIn;
248
294
  secret = Buffer.from(secretId, 'base64');
249
295
  payload = {
250
296
  "sub": "guest-user-".concat((0, _uuid.default)()),
@@ -375,7 +421,7 @@ var Authorization = _webexCore.WebexPlugin.extend((_dec = (0, _common.whileInFli
375
421
  throw new Error("CSRF token ".concat(token, " does not match stored token ").concat(sessionToken));
376
422
  }
377
423
  },
378
- version: "3.8.0"
424
+ version: "3.8.1-next.2"
379
425
  }, ((0, _applyDecoratedDescriptor2.default)(_obj, "initiateImplicitGrant", [_dec], (0, _getOwnPropertyDescriptor.default)(_obj, "initiateImplicitGrant"), _obj), (0, _applyDecoratedDescriptor2.default)(_obj, "initiateAuthorizationCodeGrant", [_dec2], (0, _getOwnPropertyDescriptor.default)(_obj, "initiateAuthorizationCodeGrant"), _obj), (0, _applyDecoratedDescriptor2.default)(_obj, "requestAccessTokenFromJwt", [_common.oneFlight], (0, _getOwnPropertyDescriptor.default)(_obj, "requestAccessTokenFromJwt"), _obj)), _obj)));
380
426
  var _default = exports.default = Authorization;
381
427
  //# sourceMappingURL=authorization.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["_querystring","_interopRequireDefault","require","_url","_common","_webexCore","_lodash","_uuid","_dec","_dec2","_obj","jwt","OAUTH2_CSRF_TOKEN","EMPTY_OBJECT_STRING","base64","encode","_stringify","default","Authorization","WebexPlugin","extend","whileInFlight","derived","isAuthenticating","deps","fn","isAuthorizing","session","type","ready","namespace","initialize","attrs","options","_this","ret","_apply","prototype","parse","location","url","webex","getWindow","href","_checkForErrors","hash","includes","substr","querystring","state","JSON","decode","tokenData","_parseHash","_cleanUrl","process","nextTick","credentials","set","supertoken","initiateLogin","arguments","length","undefined","csrf_token","_generateSecurityToken","config","clientType","initiateAuthorizationCodeGrant","initiateImplicitGrant","logger","info","buildLoginUrl","_assign","response_type","_promise","resolve","requestAccessTokenFromJwt","_ref","_this2","hydraUri","internal","services","get","slice","env","HYDRA_SERVICE_URL","request","method","uri","concat","headers","authorization","then","_ref2","body","access_token","token","token_type","expires_in","expiresIn","initServiceCatalogs","logout","noRedirect","buildLogoutUrl","createJwt","_ref3","_asyncToGenerator2","_regenerator","mark","_callee","issuer","secretId","displayName","secret","payload","alg","jwtToken","wrap","_callee$","_context","prev","next","Buffer","from","uuid","sign","abrupt","t0","reject","stop","query","error","ErrorConstructor","grantErrors","select","cloneDeep","history","replaceState","forEach","key","_deleteProperty","isEmpty","omit","stringify","format","v4","sessionStorage","setItem","_verifySecurityToken","_parseInt2","refresh_token_expires_in","sessionToken","getItem","removeItem","Error","version","_applyDecoratedDescriptor2","_getOwnPropertyDescriptor","oneFlight","_default","exports"],"sources":["authorization.js"],"sourcesContent":["/*!\n * Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.\n */\n\n/* eslint camelcase: [0] */\n\nimport querystring from 'querystring';\nimport url from 'url';\n\nimport {base64, oneFlight, whileInFlight} from '@webex/common';\nimport {grantErrors, WebexPlugin} from '@webex/webex-core';\nimport {cloneDeep, isEmpty, omit} from 'lodash';\nimport uuid from 'uuid';\nconst jwt = require('jsonwebtoken');\n\nconst OAUTH2_CSRF_TOKEN = 'oauth2-csrf-token';\nconst EMPTY_OBJECT_STRING = base64.encode(JSON.stringify({}));\n\n/**\n * Browser support for OAuth2. Automatically parses the URL hash for an access\n * token\n * @class\n * @name AuthorizationBrowser\n */\nconst Authorization = WebexPlugin.extend({\n derived: {\n /**\n * Alias of {@link AuthorizationBrowser#isAuthorizing}\n * @instance\n * @memberof AuthorizationBrowser\n * @type {boolean}\n */\n isAuthenticating: {\n deps: ['isAuthorizing'],\n fn() {\n return this.isAuthorizing;\n },\n },\n },\n\n session: {\n /**\n * Indicates if an Authorization Code exchange is inflight\n * @instance\n * @memberof AuthorizationBrowser\n * @type {boolean}\n */\n isAuthorizing: {\n default: false,\n type: 'boolean',\n },\n ready: {\n default: false,\n type: 'boolean',\n },\n },\n\n namespace: 'Credentials',\n\n /**\n * Initializer\n * @instance\n * @memberof AuthorizationBrowser\n * @param {Object} attrs {@link AmpersandState}\n * @param {boolean} attrs.parse Controls whether or not the the url should get\n * parsed for an access token\n * @private\n * @returns {Authorization}\n */\n // eslint-disable-next-line complexity\n initialize(attrs, options) {\n const ret = Reflect.apply(WebexPlugin.prototype.initialize, this, [attrs, options]);\n\n // Reminder, we can't do parse based on config, because config is not\n // available until nextTick and we want to be able to throw errors found in\n // the url.\n if (attrs.parse === false) {\n this.ready = true;\n\n return ret;\n }\n const location = url.parse(this.webex.getWindow().location.href, true);\n\n this._checkForErrors(location);\n\n let {hash} = location;\n\n if (!hash) {\n this.ready = true;\n\n return ret;\n }\n if (hash.includes('#')) {\n hash = hash.substr(1);\n }\n location.hash = querystring.parse(hash);\n if (location.hash.state) {\n location.hash.state = JSON.parse(base64.decode(location.hash.state));\n }\n const tokenData = this._parseHash(location);\n\n if (!tokenData) {\n return ret;\n }\n this._cleanUrl(location);\n\n // Wait until nextTick in case `credentials` hasn't initialized yet\n process.nextTick(() => {\n this.webex.credentials.set({supertoken: tokenData});\n this.ready = true;\n });\n\n return ret;\n },\n\n /**\n * Kicks off an oauth flow\n * @instance\n * @memberof AuthorizationBrowser\n * @param {Object} options\n * @returns {Promise}\n */\n initiateLogin(options = {}) {\n options.state = options.state || {};\n options.state.csrf_token = this._generateSecurityToken();\n\n // If we're not explicitly a confidential client, assume we're a public\n // client\n if (this.config.clientType === 'confidential') {\n return this.initiateAuthorizationCodeGrant(options);\n }\n\n return this.initiateImplicitGrant(options);\n },\n\n @whileInFlight('isAuthorizing')\n /**\n * Kicks off the Authorization Code grant flow. Typically called via\n * {@link AuthorizationBrowser#initiateLogin}\n * @instance\n * @memberof AuthorizationBrowser\n * @param {Object} options\n * @returns {Promise}\n */\n initiateImplicitGrant(options) {\n this.logger.info('authorization: initiating implicit grant flow');\n this.webex.getWindow().location = this.webex.credentials.buildLoginUrl(\n Object.assign({response_type: 'token'}, options)\n );\n\n return Promise.resolve();\n },\n\n @whileInFlight('isAuthorizing')\n /**\n * Kicks off the Implicit Code grant flow. Typically called via\n * {@link AuthorizationBrowser#initiateLogin}\n * @instance\n * @memberof AuthorizationBrowser\n * @param {Object} options\n * @returns {Promise}\n */\n initiateAuthorizationCodeGrant(options) {\n this.logger.info('authorization: initiating authorization code grant flow');\n this.webex.getWindow().location = this.webex.credentials.buildLoginUrl(\n Object.assign({response_type: 'code'}, options)\n );\n\n return Promise.resolve();\n },\n\n @oneFlight\n /**\n * Requests a Webex access token for a user already authenticated into\n * your product.\n *\n * Note: You'll need to supply a jwtRefreshCallback of the form\n * `Promise<jwt> = jwtRefreshCallback(webex)` for automatic token refresh to\n * work.\n *\n * @instance\n * @memberof AuthorizationBrowser\n * @param {Object} options\n * @param {Object} options.jwt This is a jwt generated by your backend that\n * identifies a user in your system\n * @returns {Promise}\n */\n requestAccessTokenFromJwt({jwt}) {\n let hydraUri = this.webex.internal.services.get('hydra', true);\n\n if (hydraUri && hydraUri.slice(-1) !== '/') {\n // add a `/` to hydra's uri from the services catalog so that\n // it matches the current env service format.\n hydraUri += '/';\n }\n\n hydraUri = hydraUri || process.env.HYDRA_SERVICE_URL || 'https://api.ciscospark.com/v1/';\n\n return this.webex\n .request({\n method: 'POST',\n uri: `${hydraUri}jwt/login`,\n headers: {\n authorization: jwt,\n },\n })\n .then(({body}) => ({\n access_token: body.token,\n token_type: 'Bearer',\n expires_in: body.expiresIn,\n }))\n .then((token) => {\n this.webex.credentials.set({\n supertoken: token,\n });\n })\n .then(() => this.webex.internal.services.initServiceCatalogs());\n },\n\n /**\n * Called by {@link WebexCore#logout()}. Redirects to the logout page\n * @instance\n * @memberof AuthorizationBrowser\n * @param {Object} options\n * @param {boolean} options.noRedirect if true, does not redirect\n * @returns {Promise}\n */\n logout(options = {}) {\n if (!options.noRedirect) {\n this.webex.getWindow().location = this.webex.credentials.buildLogoutUrl(options);\n }\n },\n\n /**\n * Creates a jwt user token\n * @param {object} options\n * @param {String} options.issuer Guest Issuer ID\n * @param {String} options.secretId Guest Secret ID\n * @param {String} options.displayName Guest Display Name | optional\n * @param {String} options.expiresIn\n * @returns {Promise<object>}\n */\n async createJwt({issuer, secretId, displayName, expiresIn}) {\n const secret = Buffer.from(secretId, 'base64');\n const payload = {\n \"sub\": `guest-user-${uuid()}`,\n \"iss\": issuer,\n \"name\": displayName || `Guest User - ${uuid()}`\n };\n const alg = 'HS256';\n\n try {\n\n const jwtToken = jwt.sign(payload, secret, { expiresIn });\n\n return Promise.resolve({jwt: jwtToken});\n } catch (e) {\n return Promise.reject(e);\n }\n },\n\n /**\n * Checks if the result of the login redirect contains an error string\n * @instance\n * @memberof AuthorizationBrowser\n * @param {Object} location\n * @private\n * @returns {Promise}\n */\n _checkForErrors(location) {\n const {query} = location;\n\n if (query && query.error) {\n const ErrorConstructor = grantErrors.select(query.error);\n\n throw new ErrorConstructor(query);\n }\n },\n\n /**\n * Removes no-longer needed values from the url (access token, csrf token, etc)\n * @instance\n * @memberof AuthorizationBrowser\n * @param {Object} location\n * @private\n * @returns {Promise}\n */\n _cleanUrl(location) {\n location = cloneDeep(location);\n if (this.webex.getWindow().history && this.webex.getWindow().history.replaceState) {\n [\n 'access_token',\n 'token_type',\n 'expires_in',\n 'refresh_token',\n 'refresh_token_expires_in',\n ].forEach((key) => Reflect.deleteProperty(location.hash, key));\n if (!isEmpty(location.hash.state)) {\n location.hash.state = base64.encode(\n JSON.stringify(omit(location.hash.state, 'csrf_token'))\n );\n if (location.hash.state === EMPTY_OBJECT_STRING) {\n Reflect.deleteProperty(location.hash, 'state');\n }\n } else {\n Reflect.deleteProperty(location.hash, 'state');\n }\n location.hash = querystring.stringify(location.hash);\n this.webex.getWindow().history.replaceState({}, null, url.format(location));\n }\n },\n\n /**\n * Generates a CSRF token and sticks in in sessionStorage\n * @instance\n * @memberof AuthorizationBrowser\n * @private\n * @returns {Promise}\n */\n _generateSecurityToken() {\n this.logger.info('authorization: generating csrf token');\n\n const token = uuid.v4();\n\n this.webex.getWindow().sessionStorage.setItem('oauth2-csrf-token', token);\n\n return token;\n },\n\n /**\n * Parses the url hash into an access token object\n * @instance\n * @memberof AuthorizationBrowser\n * @param {Object} location\n * @private\n * @returns {Object}\n */\n _parseHash(location) {\n const hash = cloneDeep(location.hash);\n\n if (hash) {\n this._verifySecurityToken(hash);\n }\n if (!hash.access_token) {\n this.ready = true;\n\n return undefined;\n }\n if (hash.expires_in) {\n hash.expires_in = parseInt(hash.expires_in, 10);\n }\n if (hash.refresh_token_expires_in) {\n hash.refresh_token_expires_in = parseInt(hash.refresh_token_expires_in, 10);\n }\n\n return hash;\n },\n\n /**\n * Checks if the CSRF token in sessionStorage is the same as the one returned\n * in the url.\n * @instance\n * @memberof AuthorizationBrowser\n * @param {Object} hash\n * @private\n * @returns {Promise}\n */\n _verifySecurityToken(hash) {\n const sessionToken = this.webex.getWindow().sessionStorage.getItem(OAUTH2_CSRF_TOKEN);\n\n this.webex.getWindow().sessionStorage.removeItem(OAUTH2_CSRF_TOKEN);\n if (!sessionToken) {\n return;\n }\n\n if (!hash.state) {\n throw new Error(`Expected CSRF token ${sessionToken}, but not found in redirect hash`);\n }\n\n if (!hash.state.csrf_token) {\n throw new Error(`Expected CSRF token ${sessionToken}, but not found in redirect hash`);\n }\n\n const token = hash.state.csrf_token;\n\n if (token !== sessionToken) {\n throw new Error(`CSRF token ${token} does not match stored token ${sessionToken}`);\n }\n },\n});\n\nexport default Authorization;\n"],"mappings":"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"}
1
+ {"version":3,"names":["_querystring","_interopRequireDefault","require","_url","_common","_webexCore","_lodash","_uuid","_dec","_dec2","_obj","jwt","OAUTH2_CSRF_TOKEN","EMPTY_OBJECT_STRING","base64","encode","_stringify","default","Authorization","WebexPlugin","extend","whileInFlight","derived","isAuthenticating","deps","fn","isAuthorizing","session","type","ready","namespace","initialize","attrs","options","_this","ret","_apply","prototype","parse","location","url","webex","getWindow","href","_checkForErrors","hash","includes","substr","querystring","state","JSON","decode","tokenData","_parseHash","_cleanUrl","process","nextTick","credentials","set","supertoken","initiateLogin","arguments","length","undefined","csrf_token","_generateSecurityToken","config","clientType","initiateAuthorizationCodeGrant","initiateImplicitGrant","logger","info","loginUrl","buildLoginUrl","_assign","response_type","separateWindow","defaultWindowSettings","width","height","windowSettings","_typeof2","windowFeatures","_entries","map","_ref","_ref2","_slicedToArray2","key","value","concat","join","open","_promise","resolve","requestAccessTokenFromJwt","_ref3","_this2","hydraUri","internal","services","get","slice","env","HYDRA_SERVICE_URL","request","method","uri","headers","authorization","then","_ref4","body","access_token","token","token_type","expires_in","expiresIn","initServiceCatalogs","logout","noRedirect","buildLogoutUrl","createJwt","_ref5","_asyncToGenerator2","_regenerator","mark","_callee","issuer","secretId","displayName","secret","payload","alg","jwtToken","wrap","_callee$","_context","prev","next","Buffer","from","uuid","sign","abrupt","t0","reject","stop","query","error","ErrorConstructor","grantErrors","select","cloneDeep","history","replaceState","forEach","_deleteProperty","isEmpty","omit","stringify","format","v4","sessionStorage","setItem","_verifySecurityToken","_parseInt2","refresh_token_expires_in","sessionToken","getItem","removeItem","Error","version","_applyDecoratedDescriptor2","_getOwnPropertyDescriptor","oneFlight","_default","exports"],"sources":["authorization.js"],"sourcesContent":["/*!\n * Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.\n */\n\n/* eslint camelcase: [0] */\n\nimport querystring from 'querystring';\nimport url from 'url';\n\nimport {base64, oneFlight, whileInFlight} from '@webex/common';\nimport {grantErrors, WebexPlugin} from '@webex/webex-core';\nimport {cloneDeep, isEmpty, omit} from 'lodash';\nimport uuid from 'uuid';\nconst jwt = require('jsonwebtoken');\n\nconst OAUTH2_CSRF_TOKEN = 'oauth2-csrf-token';\nconst EMPTY_OBJECT_STRING = base64.encode(JSON.stringify({}));\n\n/**\n * Browser support for OAuth2. Automatically parses the URL hash for an access\n * token\n * @class\n * @name AuthorizationBrowser\n */\nconst Authorization = WebexPlugin.extend({\n derived: {\n /**\n * Alias of {@link AuthorizationBrowser#isAuthorizing}\n * @instance\n * @memberof AuthorizationBrowser\n * @type {boolean}\n */\n isAuthenticating: {\n deps: ['isAuthorizing'],\n fn() {\n return this.isAuthorizing;\n },\n },\n },\n\n session: {\n /**\n * Indicates if an Authorization Code exchange is inflight\n * @instance\n * @memberof AuthorizationBrowser\n * @type {boolean}\n */\n isAuthorizing: {\n default: false,\n type: 'boolean',\n },\n ready: {\n default: false,\n type: 'boolean',\n },\n },\n\n namespace: 'Credentials',\n\n /**\n * Initializer\n * @instance\n * @memberof AuthorizationBrowser\n * @param {Object} attrs {@link AmpersandState}\n * @param {boolean} attrs.parse Controls whether or not the the url should get\n * parsed for an access token\n * @private\n * @returns {Authorization}\n */\n // eslint-disable-next-line complexity\n initialize(attrs, options) {\n const ret = Reflect.apply(WebexPlugin.prototype.initialize, this, [attrs, options]);\n\n // Reminder, we can't do parse based on config, because config is not\n // available until nextTick and we want to be able to throw errors found in\n // the url.\n if (attrs.parse === false) {\n this.ready = true;\n\n return ret;\n }\n const location = url.parse(this.webex.getWindow().location.href, true);\n\n this._checkForErrors(location);\n\n let {hash} = location;\n\n if (!hash) {\n this.ready = true;\n\n return ret;\n }\n if (hash.includes('#')) {\n hash = hash.substr(1);\n }\n location.hash = querystring.parse(hash);\n if (location.hash.state) {\n location.hash.state = JSON.parse(base64.decode(location.hash.state));\n }\n const tokenData = this._parseHash(location);\n\n if (!tokenData) {\n return ret;\n }\n this._cleanUrl(location);\n\n // Wait until nextTick in case `credentials` hasn't initialized yet\n process.nextTick(() => {\n this.webex.credentials.set({supertoken: tokenData});\n this.ready = true;\n });\n\n return ret;\n },\n\n/**\n * Initiates the OAuth flow for user authentication.\n * This function determines the type of OAuth flow to use based on the client type configuration.\n * If the client is configured as \"confidential\", it will initiate the Authorization Code Grant flow;\n * otherwise, it will initiate the Implicit Grant flow.\n *\n * @instance\n * @memberof AuthorizationBrowser\n * @param {Object} options - The options to configure the OAuth flow.\n * @param {Object} [options.state] - An optional state object that can be used to include additional\n * information such as security tokens. A CSRF token will be automatically generated and added to\n * this state object.\n * @param {boolean|Object} [options.separateWindow] - Determines if the login should open in a separate window.\n * This can be a boolean or an object specifying window features:\n * - If `true`, a new window with default dimensions is opened.\n * - If an object, custom window features can be specified (e.g., `{width: 800, height: 600}`).\n * @returns {Promise<void>} - A promise that resolves when the appropriate OAuth flow has been initiated.\n * The promise does not necessarily indicate the completion of the login process.\n * @throws {Error} - Throws an error if there are issues initiating the OAuth flow.\n */\n initiateLogin(options = {}) {\n options.state = options.state || {};\n options.state.csrf_token = this._generateSecurityToken();\n\n // If we're not explicitly a confidential client, assume we're a public\n // client\n if (this.config.clientType === 'confidential') {\n return this.initiateAuthorizationCodeGrant(options);\n }\n\n return this.initiateImplicitGrant(options);\n },\n\n @whileInFlight('isAuthorizing')\n/**\n * Initiates the Implicit Grant flow for authorization.\n * This function constructs the login URL and either opens it in a new\n * window or in the current window based on the provided options.\n * Typically called via {@link AuthorizationBrowser#initiateLogin}.\n *\n * @instance\n * @memberof AuthorizationBrowser\n * @param {Object} options - The options to configure the login flow.\n * @param {Object} [options.separateWindow] - Determines if the login should open in a separate window.\n * This can be a boolean or an object specifying window features:\n * - If `true`, a new window with default dimensions is opened.\n * - If an object, custom window features can be specified (e.g., `{width: 800, height: 600}`).\n * @returns {Promise<void>} - A promise that resolves immediately after initiating the login flow.\n * This promise does not indicate the completion of the login process.\n * @throws {Error} - Throws an error if the login URL cannot be constructed or if window opening fails.\n */\n initiateImplicitGrant(options) {\n\n this.logger.info('authorization: initiating implicit grant flow');\n const loginUrl = this.webex.credentials.buildLoginUrl(\n Object.assign({response_type: 'token'}, options)\n );\n\n if (options?.separateWindow) {\n // Default window settings\n const defaultWindowSettings = {\n width: 600,\n height: 800\n };\n\n // Merge user provided settings with defaults\n const windowSettings = Object.assign(\n defaultWindowSettings, \n typeof options.separateWindow === 'object' ? options.separateWindow : {}\n );\n // Convert settings object to window.open features string\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 // Default behavior - open in same window\n this.webex.getWindow().location = loginUrl;\n }\n\n return Promise.resolve();\n },\n\n @whileInFlight('isAuthorizing')\n /**\n * Kicks off the Implicit Code grant flow. Typically called via\n * {@link AuthorizationBrowser#initiateLogin}\n * @instance\n * @memberof AuthorizationBrowser\n * @param {Object} options\n * @returns {Promise}\n */\n initiateAuthorizationCodeGrant(options) {\n this.logger.info('authorization: initiating authorization code grant flow');\n this.webex.getWindow().location = this.webex.credentials.buildLoginUrl(\n Object.assign({response_type: 'code'}, options)\n );\n\n return Promise.resolve();\n },\n\n @oneFlight\n /**\n * Requests a Webex access token for a user already authenticated into\n * your product.\n *\n * Note: You'll need to supply a jwtRefreshCallback of the form\n * `Promise<jwt> = jwtRefreshCallback(webex)` for automatic token refresh to\n * work.\n *\n * @instance\n * @memberof AuthorizationBrowser\n * @param {Object} options\n * @param {Object} options.jwt This is a jwt generated by your backend that\n * identifies a user in your system\n * @returns {Promise}\n */\n requestAccessTokenFromJwt({jwt}) {\n let hydraUri = this.webex.internal.services.get('hydra', true);\n\n if (hydraUri && hydraUri.slice(-1) !== '/') {\n // add a `/` to hydra's uri from the services catalog so that\n // it matches the current env service format.\n hydraUri += '/';\n }\n\n hydraUri = hydraUri || process.env.HYDRA_SERVICE_URL || 'https://api.ciscospark.com/v1/';\n\n return this.webex\n .request({\n method: 'POST',\n uri: `${hydraUri}jwt/login`,\n headers: {\n authorization: jwt,\n },\n })\n .then(({body}) => ({\n access_token: body.token,\n token_type: 'Bearer',\n expires_in: body.expiresIn,\n }))\n .then((token) => {\n this.webex.credentials.set({\n supertoken: token,\n });\n })\n .then(() => this.webex.internal.services.initServiceCatalogs());\n },\n\n /**\n * Called by {@link WebexCore#logout()}. Redirects to the logout page\n * @instance\n * @memberof AuthorizationBrowser\n * @param {Object} options\n * @param {boolean} options.noRedirect if true, does not redirect\n * @returns {Promise}\n */\n logout(options = {}) {\n if (!options.noRedirect) {\n this.webex.getWindow().location = this.webex.credentials.buildLogoutUrl(options);\n }\n },\n\n /**\n * Creates a jwt user token\n * @param {object} options\n * @param {String} options.issuer Guest Issuer ID\n * @param {String} options.secretId Guest Secret ID\n * @param {String} options.displayName Guest Display Name | optional\n * @param {String} options.expiresIn\n * @returns {Promise<object>}\n */\n async createJwt({issuer, secretId, displayName, expiresIn}) {\n const secret = Buffer.from(secretId, 'base64');\n const payload = {\n \"sub\": `guest-user-${uuid()}`,\n \"iss\": issuer,\n \"name\": displayName || `Guest User - ${uuid()}`\n };\n const alg = 'HS256';\n\n try {\n\n const jwtToken = jwt.sign(payload, secret, { expiresIn });\n\n return Promise.resolve({jwt: jwtToken});\n } catch (e) {\n return Promise.reject(e);\n }\n },\n\n /**\n * Checks if the result of the login redirect contains an error string\n * @instance\n * @memberof AuthorizationBrowser\n * @param {Object} location\n * @private\n * @returns {Promise}\n */\n _checkForErrors(location) {\n const {query} = location;\n\n if (query && query.error) {\n const ErrorConstructor = grantErrors.select(query.error);\n\n throw new ErrorConstructor(query);\n }\n },\n\n /**\n * Removes no-longer needed values from the url (access token, csrf token, etc)\n * @instance\n * @memberof AuthorizationBrowser\n * @param {Object} location\n * @private\n * @returns {Promise}\n */\n _cleanUrl(location) {\n location = cloneDeep(location);\n if (this.webex.getWindow().history && this.webex.getWindow().history.replaceState) {\n [\n 'access_token',\n 'token_type',\n 'expires_in',\n 'refresh_token',\n 'refresh_token_expires_in',\n ].forEach((key) => Reflect.deleteProperty(location.hash, key));\n if (!isEmpty(location.hash.state)) {\n location.hash.state = base64.encode(\n JSON.stringify(omit(location.hash.state, 'csrf_token'))\n );\n if (location.hash.state === EMPTY_OBJECT_STRING) {\n Reflect.deleteProperty(location.hash, 'state');\n }\n } else {\n Reflect.deleteProperty(location.hash, 'state');\n }\n location.hash = querystring.stringify(location.hash);\n this.webex.getWindow().history.replaceState({}, null, url.format(location));\n }\n },\n\n /**\n * Generates a CSRF token and sticks in in sessionStorage\n * @instance\n * @memberof AuthorizationBrowser\n * @private\n * @returns {Promise}\n */\n _generateSecurityToken() {\n this.logger.info('authorization: generating csrf token');\n\n const token = uuid.v4();\n\n this.webex.getWindow().sessionStorage.setItem('oauth2-csrf-token', token);\n\n return token;\n },\n\n /**\n * Parses the url hash into an access token object\n * @instance\n * @memberof AuthorizationBrowser\n * @param {Object} location\n * @private\n * @returns {Object}\n */\n _parseHash(location) {\n const hash = cloneDeep(location.hash);\n\n if (hash) {\n this._verifySecurityToken(hash);\n }\n if (!hash.access_token) {\n this.ready = true;\n\n return undefined;\n }\n if (hash.expires_in) {\n hash.expires_in = parseInt(hash.expires_in, 10);\n }\n if (hash.refresh_token_expires_in) {\n hash.refresh_token_expires_in = parseInt(hash.refresh_token_expires_in, 10);\n }\n\n return hash;\n },\n\n /**\n * Checks if the CSRF token in sessionStorage is the same as the one returned\n * in the url.\n * @instance\n * @memberof AuthorizationBrowser\n * @param {Object} hash\n * @private\n * @returns {Promise}\n */\n _verifySecurityToken(hash) {\n const sessionToken = this.webex.getWindow().sessionStorage.getItem(OAUTH2_CSRF_TOKEN);\n\n this.webex.getWindow().sessionStorage.removeItem(OAUTH2_CSRF_TOKEN);\n if (!sessionToken) {\n return;\n }\n\n if (!hash.state) {\n throw new Error(`Expected CSRF token ${sessionToken}, but not found in redirect hash`);\n }\n\n if (!hash.state.csrf_token) {\n throw new Error(`Expected CSRF token ${sessionToken}, but not found in redirect hash`);\n }\n\n const token = hash.state.csrf_token;\n\n if (token !== sessionToken) {\n throw new Error(`CSRF token ${token} does not match stored token ${sessionToken}`);\n }\n },\n});\n\nexport default Authorization;\n"],"mappings":"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"}