box-node-sdk 1.35.0 → 1.37.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.
Files changed (126) hide show
  1. package/CHANGELOG.md +37 -2
  2. package/README.md +1 -1
  3. package/lib/api-request-manager.d.ts +38 -0
  4. package/lib/api-request-manager.js +48 -55
  5. package/lib/api-request-manager.js.map +1 -0
  6. package/lib/api-request.d.ts +141 -0
  7. package/lib/api-request.js +202 -281
  8. package/lib/api-request.js.map +1 -0
  9. package/lib/box-client.d.ts +269 -0
  10. package/lib/box-client.js +551 -713
  11. package/lib/box-client.js.map +1 -0
  12. package/lib/box-node-sdk.d.ts +216 -0
  13. package/lib/box-node-sdk.js +317 -352
  14. package/lib/box-node-sdk.js.map +1 -0
  15. package/lib/chunked-uploader.d.ts +129 -0
  16. package/lib/chunked-uploader.js +287 -358
  17. package/lib/chunked-uploader.js.map +1 -0
  18. package/lib/enterprise-event-stream.d.ts +82 -0
  19. package/lib/enterprise-event-stream.js +189 -203
  20. package/lib/enterprise-event-stream.js.map +1 -0
  21. package/lib/event-stream.d.ts +92 -0
  22. package/lib/event-stream.js +274 -302
  23. package/lib/event-stream.js.map +1 -0
  24. package/lib/managers/collaboration-allowlist.d.ts +137 -0
  25. package/lib/managers/collaboration-allowlist.js +200 -0
  26. package/lib/managers/collaboration-allowlist.js.map +1 -0
  27. package/lib/managers/collaboration-whitelist.d.ts +3 -0
  28. package/lib/managers/collaboration-whitelist.js +8 -222
  29. package/lib/managers/collaboration-whitelist.js.map +1 -0
  30. package/lib/managers/collaborations.d.ts +166 -0
  31. package/lib/managers/collaborations.js +225 -258
  32. package/lib/managers/collaborations.js.map +1 -0
  33. package/lib/managers/collections.d.ts +42 -0
  34. package/lib/managers/collections.js +45 -50
  35. package/lib/managers/collections.js.map +1 -0
  36. package/lib/managers/comments.d.ts +103 -0
  37. package/lib/managers/comments.js +158 -173
  38. package/lib/managers/comments.js.map +1 -0
  39. package/lib/managers/device-pins.d.ts +52 -0
  40. package/lib/managers/device-pins.js +75 -88
  41. package/lib/managers/device-pins.js.map +1 -0
  42. package/lib/managers/enterprise.d.ts +162 -0
  43. package/lib/managers/enterprise.js +168 -199
  44. package/lib/managers/enterprise.js.map +1 -0
  45. package/lib/managers/events.d.ts +177 -0
  46. package/lib/managers/events.js +230 -254
  47. package/lib/managers/events.js.map +1 -0
  48. package/lib/managers/files.d.ts +772 -0
  49. package/lib/managers/files.js +1400 -1602
  50. package/lib/managers/files.js.map +1 -0
  51. package/lib/managers/folders.d.ts +347 -0
  52. package/lib/managers/folders.js +551 -567
  53. package/lib/managers/folders.js.map +1 -0
  54. package/lib/managers/groups.d.ts +202 -0
  55. package/lib/managers/groups.js +238 -287
  56. package/lib/managers/groups.js.map +1 -0
  57. package/lib/managers/legal-hold-policies.d.ts +190 -0
  58. package/lib/managers/legal-hold-policies.js +228 -272
  59. package/lib/managers/legal-hold-policies.js.map +1 -0
  60. package/lib/managers/metadata.d.ts +228 -0
  61. package/lib/managers/metadata.js +265 -328
  62. package/lib/managers/metadata.js.map +1 -0
  63. package/lib/managers/recent-items.d.ts +38 -0
  64. package/lib/managers/recent-items.js +32 -39
  65. package/lib/managers/recent-items.js.map +1 -0
  66. package/lib/managers/retention-policies.d.ts +213 -0
  67. package/lib/managers/retention-policies.js +235 -281
  68. package/lib/managers/retention-policies.js.map +1 -0
  69. package/lib/managers/search.d.ts +82 -0
  70. package/lib/managers/search.js +68 -88
  71. package/lib/managers/search.js.map +1 -0
  72. package/lib/managers/shared-items.d.ts +33 -0
  73. package/lib/managers/shared-items.js +54 -62
  74. package/lib/managers/shared-items.js.map +1 -0
  75. package/lib/managers/storage-policies.d.ts +86 -0
  76. package/lib/managers/storage-policies.js +108 -142
  77. package/lib/managers/storage-policies.js.map +1 -0
  78. package/lib/managers/tasks.d.ts +161 -0
  79. package/lib/managers/tasks.js +219 -260
  80. package/lib/managers/tasks.js.map +1 -0
  81. package/lib/managers/terms-of-service.d.ts +161 -0
  82. package/lib/managers/terms-of-service.js +250 -273
  83. package/lib/managers/terms-of-service.js.map +1 -0
  84. package/lib/managers/trash.d.ts +30 -0
  85. package/lib/managers/trash.js +30 -41
  86. package/lib/managers/trash.js.map +1 -0
  87. package/lib/managers/users.d.ts +131 -0
  88. package/lib/managers/users.js +160 -203
  89. package/lib/managers/users.js.map +1 -0
  90. package/lib/managers/web-links.d.ts +127 -0
  91. package/lib/managers/web-links.js +183 -209
  92. package/lib/managers/web-links.js.map +1 -0
  93. package/lib/managers/webhooks.d.ts +166 -0
  94. package/lib/managers/webhooks.js +312 -305
  95. package/lib/managers/webhooks.js.map +1 -0
  96. package/lib/sessions/anonymous-session.d.ts +69 -0
  97. package/lib/sessions/anonymous-session.js +88 -102
  98. package/lib/sessions/anonymous-session.js.map +1 -0
  99. package/lib/sessions/app-auth-session.d.ts +92 -0
  100. package/lib/sessions/app-auth-session.js +140 -160
  101. package/lib/sessions/app-auth-session.js.map +1 -0
  102. package/lib/sessions/basic-session.d.ts +56 -0
  103. package/lib/sessions/basic-session.js +40 -50
  104. package/lib/sessions/basic-session.js.map +1 -0
  105. package/lib/sessions/persistent-session.d.ts +96 -0
  106. package/lib/sessions/persistent-session.js +191 -211
  107. package/lib/sessions/persistent-session.js.map +1 -0
  108. package/lib/token-manager.d.ts +191 -0
  109. package/lib/token-manager.js +390 -465
  110. package/lib/token-manager.js.map +1 -0
  111. package/lib/util/config.d.ts +86 -0
  112. package/lib/util/config.js +124 -152
  113. package/lib/util/config.js.map +1 -0
  114. package/lib/util/errors.d.ts +50 -0
  115. package/lib/util/errors.js +134 -145
  116. package/lib/util/errors.js.map +1 -0
  117. package/lib/util/exponential-backoff.d.ts +11 -0
  118. package/lib/util/exponential-backoff.js +10 -22
  119. package/lib/util/exponential-backoff.js.map +1 -0
  120. package/lib/util/paging-iterator.d.ts +53 -0
  121. package/lib/util/paging-iterator.js +202 -218
  122. package/lib/util/paging-iterator.js.map +1 -0
  123. package/lib/util/url-path.d.ts +16 -0
  124. package/lib/util/url-path.js +20 -35
  125. package/lib/util/url-path.js.map +1 -0
  126. package/package.json +24 -9
@@ -1,80 +1,39 @@
1
+ "use strict";
1
2
  /**
2
3
  * @fileoverview Token Manager
3
4
  */
4
-
5
- 'use strict';
6
-
5
+ var __importDefault = (this && this.__importDefault) || function (mod) {
6
+ return (mod && mod.__esModule) ? mod : { "default": mod };
7
+ };
7
8
  // ------------------------------------------------------------------------------
8
- // Typedefs and Callbacks
9
+ // Requirements
9
10
  // ------------------------------------------------------------------------------
10
-
11
- /**
12
- * Token request options. Set by the consumer to add/modify the params sent to the
13
- * request.
14
- *
15
- * @typedef {Object} TokenRequestOptions
16
- * @property {string} [ip] The IP Address of the requesting user. This IP will be reflected in authentication
17
- * notification emails sent to your users on login. Defaults to the IP address of the
18
- * server requesting the tokens.
19
- */
20
-
11
+ var bluebird_1 = __importDefault(require("bluebird"));
12
+ var http_status_1 = __importDefault(require("http-status"));
13
+ var jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
14
+ var uuid_1 = __importDefault(require("uuid"));
15
+ var errors_1 = __importDefault(require("./util/errors"));
16
+ var exponential_backoff_1 = __importDefault(require("./util/exponential-backoff"));
21
17
  /**
22
- * Parameters for creating a token using a Box shared link via token exchange
23
- * @typedef {Object} SharedLinkParams
24
- * @property {string} url Shared link URL
25
- */
26
-
27
- /**
28
- * Parameters for creating an actor token via token exchange
29
- * @typedef {Object} ActorParams
30
- * @property {string} id The external identifier for the actor
31
- * @property {string} name The display name of the actor
32
- */
33
-
34
- /**
35
- * An object representing all token information for a single Box user.
36
- *
37
- * @typedef {Object} TokenInfo
38
- * @property {string} accessToken The API access token. Used to authenticate API requests to a certain
39
- * user and/or application.
40
- * @property {int} acquiredAtMS The time that the tokens were acquired.
41
- * @property {int} accessTokenTTLMS The TTL of the access token. Can be used with acquiredAtMS to
42
- * calculate if the current access token has expired.
43
- * @property {string} [refreshToken] The API refresh token is a Longer-lasting than an access token, and can
44
- * be used to gain a new access token if the current access token becomes
45
- * expired. Grants like the 'client credentials' grant don't return a
46
- * refresh token, and have no refresh capabilities.
18
+ * Determines whether a JWT auth error can be retried
19
+ * @param {Error} err The JWT auth error
20
+ * @returns {boolean} True if the error is retryable
47
21
  */
48
-
49
- /**
50
- * Determines whether a JWT auth error can be retried
51
- * @param {Error} err The JWT auth error
52
- * @returns {boolean} True if the error is retryable
53
- */
54
- function isJWTAuthErrorRetryable(err) {
55
-
56
- if (err.authExpired && err.response.headers.date && (err.response.body.error_description.indexOf('exp') > -1 || err.response.body.error_description.indexOf('jti') > -1)) {
57
- return true;
58
- } else if (err.statusCode === 429 || err.statusCode >= 500) {
59
- return true;
60
- }
61
- return false;
22
+ function isJWTAuthErrorRetryable(err /* FIXME */) {
23
+ if (err.authExpired &&
24
+ err.response.headers.date &&
25
+ (err.response.body.error_description.indexOf('exp') > -1 ||
26
+ err.response.body.error_description.indexOf('jti') > -1)) {
27
+ return true;
28
+ }
29
+ else if (err.statusCode === 429 || err.statusCode >= 500) {
30
+ return true;
31
+ }
32
+ return false;
62
33
  }
63
-
64
- // ------------------------------------------------------------------------------
65
- // Requirements
66
- // ------------------------------------------------------------------------------
67
- var errors = require('./util/errors'),
68
- jwt = require('jsonwebtoken'),
69
- uuid = require('uuid'),
70
- httpStatusCodes = require('http-status'),
71
- Promise = require('bluebird'),
72
- getRetryTimeout = require('./util/exponential-backoff');
73
-
74
34
  // ------------------------------------------------------------------------------
75
35
  // Constants
76
36
  // ------------------------------------------------------------------------------
77
-
78
37
  /**
79
38
  * Collection of grant types that can be used to acquire tokens via OAuth2
80
39
  *
@@ -82,39 +41,34 @@ var errors = require('./util/errors'),
82
41
  * @enum {string}
83
42
  */
84
43
  var grantTypes = {
85
- AUTHORIZATION_CODE: 'authorization_code',
86
- REFRESH_TOKEN: 'refresh_token',
87
- CLIENT_CREDENTIALS: 'client_credentials',
88
- JWT: 'urn:ietf:params:oauth:grant-type:jwt-bearer',
89
- TOKEN_EXCHANGE: 'urn:ietf:params:oauth:grant-type:token-exchange'
44
+ AUTHORIZATION_CODE: 'authorization_code',
45
+ REFRESH_TOKEN: 'refresh_token',
46
+ CLIENT_CREDENTIALS: 'client_credentials',
47
+ JWT: 'urn:ietf:params:oauth:grant-type:jwt-bearer',
48
+ TOKEN_EXCHANGE: 'urn:ietf:params:oauth:grant-type:token-exchange',
90
49
  };
91
-
92
50
  /**
93
51
  * Collection of paths to interact with Box OAuth2 tokening system
94
52
  *
95
53
  * @readonly
96
54
  * @enum {string}
97
55
  */
98
- var tokenPaths = {
99
- ROOT: '/oauth2',
100
- GET: '/token',
101
- REVOKE: '/revoke'
102
- };
103
-
56
+ var tokenPaths;
57
+ (function (tokenPaths) {
58
+ tokenPaths["ROOT"] = "/oauth2";
59
+ tokenPaths["GET"] = "/token";
60
+ tokenPaths["REVOKE"] = "/revoke";
61
+ })(tokenPaths || (tokenPaths = {}));
104
62
  // Timer used to track elapsed time starting with executing an async request and ending with emitting the response.
105
- var asyncRequestTimer;
106
-
63
+ var asyncRequestTimer /* FIXME */;
107
64
  // The XFF header label - Used to give the API better information for uploads, rate-limiting, etc.
108
- const HEADER_XFF = 'X-Forwarded-For';
109
- const ACCESS_TOKEN_TYPE = 'urn:ietf:params:oauth:token-type:access_token';
110
- const ACTOR_TOKEN_TYPE = 'urn:ietf:params:oauth:token-type:id_token';
111
- const BOX_JWT_AUDIENCE = 'https://api.box.com/oauth2/token';
112
-
113
-
65
+ var HEADER_XFF = 'X-Forwarded-For';
66
+ var ACCESS_TOKEN_TYPE = 'urn:ietf:params:oauth:token-type:access_token';
67
+ var ACTOR_TOKEN_TYPE = 'urn:ietf:params:oauth:token-type:id_token';
68
+ var BOX_JWT_AUDIENCE = 'https://api.box.com/oauth2/token';
114
69
  // ------------------------------------------------------------------------------
115
70
  // Private
116
71
  // ------------------------------------------------------------------------------
117
-
118
72
  /**
119
73
  * Parse the response body to create a new TokenInfo object.
120
74
  *
@@ -122,17 +76,16 @@ const BOX_JWT_AUDIENCE = 'https://api.box.com/oauth2/token';
122
76
  * @returns {TokenInfo} A TokenInfo object.
123
77
  * @private
124
78
  */
125
- function getTokensFromGrantResponse(grantResponseBody) {
126
- return {
127
- // Set the access token & refresh token (if passed)
128
- accessToken: grantResponseBody.access_token,
129
- refreshToken: grantResponseBody.refresh_token,
130
- // Box API sends back expires_in in seconds, we convert to ms for consistency of keeping all time in ms
131
- accessTokenTTLMS: parseInt(grantResponseBody.expires_in, 10) * 1000,
132
- acquiredAtMS: Date.now()
133
- };
79
+ function getTokensFromGrantResponse(grantResponseBody /* FIXME */) {
80
+ return {
81
+ // Set the access token & refresh token (if passed)
82
+ accessToken: grantResponseBody.access_token,
83
+ refreshToken: grantResponseBody.refresh_token,
84
+ // Box API sends back expires_in in seconds, we convert to ms for consistency of keeping all time in ms
85
+ accessTokenTTLMS: parseInt(grantResponseBody.expires_in, 10) * 1000,
86
+ acquiredAtMS: Date.now(),
87
+ };
134
88
  }
135
-
136
89
  /**
137
90
  * Determines if a given string could represent an authorization code or token.
138
91
  *
@@ -141,9 +94,8 @@ function getTokensFromGrantResponse(grantResponseBody) {
141
94
  * @private
142
95
  */
143
96
  function isValidCodeOrToken(codeOrToken) {
144
- return (typeof codeOrToken === 'string' && codeOrToken.length > 0);
97
+ return typeof codeOrToken === 'string' && codeOrToken.length > 0;
145
98
  }
146
-
147
99
  /**
148
100
  * Determines if a token grant response is valid
149
101
  *
@@ -152,26 +104,24 @@ function isValidCodeOrToken(codeOrToken) {
152
104
  * @returns {boolean} True if response body has expected fields, false if not.
153
105
  * @private
154
106
  */
155
- function isValidTokenResponse(grantType, responseBody) {
156
- if (!isValidCodeOrToken(responseBody.access_token)) {
157
- return false;
158
- }
159
- if (typeof responseBody.expires_in !== 'number') {
160
- return false;
161
- }
162
- // Check the refresh_token for certain types of grants
163
- if (grantType === 'authorization_code' || grantType === 'refresh_token') {
164
- if (!isValidCodeOrToken(responseBody.refresh_token)) {
165
- return false;
166
- }
167
- }
168
- return true;
107
+ function isValidTokenResponse(grantType, responseBody /* FIXME */) {
108
+ if (!isValidCodeOrToken(responseBody.access_token)) {
109
+ return false;
110
+ }
111
+ if (typeof responseBody.expires_in !== 'number') {
112
+ return false;
113
+ }
114
+ // Check the refresh_token for certain types of grants
115
+ if (grantType === 'authorization_code' || grantType === 'refresh_token') {
116
+ if (!isValidCodeOrToken(responseBody.refresh_token)) {
117
+ return false;
118
+ }
119
+ }
120
+ return true;
169
121
  }
170
-
171
122
  // ------------------------------------------------------------------------------
172
123
  // Public
173
124
  // ------------------------------------------------------------------------------
174
-
175
125
  /**
176
126
  * Manager for API access abd refresh tokens
177
127
  *
@@ -179,354 +129,329 @@ function isValidTokenResponse(grantType, responseBody) {
179
129
  * @param {APIRequestManager} requestManager The API Request Manager
180
130
  * @constructor
181
131
  */
182
- function TokenManager(config, requestManager) {
183
-
184
- this.config = config;
185
- this.oauthBaseURL = config.apiRootURL + tokenPaths.ROOT;
186
- this.requestManager = requestManager;
187
- }
188
-
189
- TokenManager.prototype = {
190
-
191
- /**
192
- * Given a TokenInfo object, returns whether its access token is expired. An access token is considered
193
- * expired once its TTL surpasses the current time outside of the given buffer. This is a public method so
194
- * that other modules may check the validity of their tokens.
195
- *
196
- * @param {TokenInfo} tokenInfo the token info to be written
197
- * @param {int} [bufferMS] An optional buffer we'd like to test against. The greater this buffer, the more aggressively
198
- * we'll call a token invalid.
199
- * @returns {boolean} True if token is valid outside of buffer, otherwise false
200
- */
201
- isAccessTokenValid(tokenInfo, bufferMS) {
202
- if (typeof tokenInfo.acquiredAtMS === 'undefined' || typeof tokenInfo.accessTokenTTLMS === 'undefined') {
203
- return false;
204
- }
205
- bufferMS = bufferMS || 0;
206
- var expireTime = tokenInfo.acquiredAtMS + tokenInfo.accessTokenTTLMS - bufferMS;
207
- return (expireTime > Date.now());
208
- },
209
-
210
- /**
211
- * Acquires OAuth2 tokens using a grant type (authorization_code, password, refresh_token)
212
- *
213
- * @param {Object} formParams - should contain all params expected by Box OAuth2 token endpoint
214
- * @param {TokenRequestOptions} [options] - Sets optional behavior for the token grant, null for default behavior
215
- * @returns {Promise<TokenInfo>} Promise resolving to the token info
216
- * @private
217
- */
218
- getTokens(formParams, options) {
219
- var params = {
220
- method: 'POST',
221
- url: this.oauthBaseURL + tokenPaths.GET,
222
- headers: {},
223
- form: formParams
224
- };
225
- options = options || {};
226
-
227
- // add in app-specific id and secret to auth with Box
228
- params.form.client_id = this.config.clientID;
229
- params.form.client_secret = this.config.clientSecret;
230
-
231
- if (options.ip) {
232
- params.headers[HEADER_XFF] = options.ip;
233
- }
234
-
235
- return this.requestManager.makeRequest(params)
236
- .then(response => {
237
-
238
- // Response Error: The API is telling us that we attempted an invalid token grant. This
239
- // means that our refresh token or auth code has exipred, so propagate an "Expired Tokens"
240
- // error.
241
- if (response.body && response.body.error && response.body.error === 'invalid_grant') {
242
- var errDescription = response.body.error_description;
243
- var message = errDescription ? `Auth Error: ${errDescription}` : undefined;
244
- throw errors.buildAuthError(response, message);
245
- }
246
-
247
- // Unexpected Response: If the token request couldn't get a valid response, then we're
248
- // out of options. Build an "Unexpected Response" error and propagate it out for the
249
- // consumer to handle.
250
- if (response.statusCode !== httpStatusCodes.OK || response.body instanceof Buffer) {
251
- throw errors.buildUnexpectedResponseError(response);
252
- }
253
-
254
- // Check to see if token response is valid in case the API returns us a 200 with a malformed token
255
- if (!isValidTokenResponse(formParams.grant_type, response.body)) {
256
- throw errors.buildResponseError(response, 'Token format from response invalid');
257
- }
258
-
259
- // Got valid token response. Parse out the TokenInfo and propagate it back.
260
- return getTokensFromGrantResponse(response.body);
261
- });
262
- },
263
-
264
- /**
265
- * Acquires token info using an authorization code
266
- *
267
- * @param {string} authorizationCode - authorization code issued by Box
268
- * @param {TokenRequestOptions} [options] - Sets optional behavior for the token grant
269
- * @returns {Promise<TokenInfo>} Promise resolving to the token info
270
- */
271
- getTokensAuthorizationCodeGrant(authorizationCode, options) {
272
- if (!isValidCodeOrToken(authorizationCode)) {
273
- return Promise.reject(new Error('Invalid authorization code.'));
274
- }
275
-
276
- var params = {
277
- grant_type: grantTypes.AUTHORIZATION_CODE,
278
- code: authorizationCode
279
- };
280
-
281
- return this.getTokens(params, options);
282
- },
283
-
284
- /**
285
- * Acquires token info using the client credentials grant.
286
- *
287
- * @param {TokenRequestOptions} [options] - Sets optional behavior for the token grant
288
- * @returns {Promise<TokenInfo>} Promise resolving to the token info
289
- */
290
- getTokensClientCredentialsGrant(options) {
291
-
292
- var params = {
293
- grant_type: grantTypes.CLIENT_CREDENTIALS
294
- };
295
- return this.getTokens(params, options);
296
- },
297
-
298
- /**
299
- * Refreshes the access and refresh tokens for a given refresh token.
300
- *
301
- * @param {string} refreshToken - A valid OAuth refresh token
302
- * @param {TokenRequestOptions} [options] - Sets optional behavior for the token grant
303
- * @returns {Promise<TokenInfo>} Promise resolving to the token info
304
- */
305
- getTokensRefreshGrant(refreshToken, options) {
306
- if (!isValidCodeOrToken(refreshToken)) {
307
- return Promise.reject(new Error('Invalid refresh token.'));
308
- }
309
-
310
- var params = {
311
- grant_type: grantTypes.REFRESH_TOKEN,
312
- refresh_token: refreshToken
313
- };
314
-
315
- return this.getTokens(params, options);
316
- },
317
-
318
- /**
319
- * Gets tokens for enterprise administration of app users
320
- * @param {string} type The type of token to create, "user" or "enterprise"
321
- * @param {string} id The ID of the enterprise to generate a token for
322
- * @param {TokenRequestOptions} [options] - Sets optional behavior for the token grant
323
- * @returns {Promise<TokenInfo>} Promise resolving to the token info
324
- */
325
- getTokensJWTGrant(type, id, options) {
326
- if (!this.config.appAuth.keyID) {
327
- return Promise.reject(new Error('Must provide app auth configuration to use JWT Grant'));
328
- }
329
-
330
- var claims = {
331
- exp: Math.floor(Date.now() / 1000) + this.config.appAuth.expirationTime,
332
- box_sub_type: type
333
- };
334
- var jwtOptions = {
335
- algorithm: this.config.appAuth.algorithm,
336
- audience: BOX_JWT_AUDIENCE,
337
- subject: id,
338
- issuer: this.config.clientID,
339
- jwtid: uuid.v4(),
340
- noTimestamp: !this.config.appAuth.verifyTimestamp,
341
- keyid: this.config.appAuth.keyID
342
- };
343
- var keyParams = {
344
- key: this.config.appAuth.privateKey,
345
- passphrase: this.config.appAuth.passphrase
346
- };
347
-
348
- var assertion;
349
- try {
350
- assertion = jwt.sign(claims, keyParams, jwtOptions);
351
- } catch (jwtErr) {
352
- return Promise.reject(jwtErr);
353
- }
354
-
355
- var params = {
356
- grant_type: grantTypes.JWT,
357
- assertion
358
- };
359
- // Start the request timer immediately before executing the async request
360
- asyncRequestTimer = process.hrtime();
361
- return this.getTokens(params, options)
362
- .catch(err => this.retryJWTGrant(claims, jwtOptions, keyParams, params, options, err, 0));
363
- },
364
-
365
- /**
366
- * Attempt a retry if possible and create a new JTI claim. If the request hasn't exceeded it's maximum number of retries,
367
- * re-execute the request (after the retry interval). Otherwise, propagate a new error.
368
- *
369
- * @param {Object} claims - JTI claims object
370
- * @param {Object} [jwtOptions] - JWT options for the signature
371
- * @param {Object} keyParams - Key JWT parameters object that contains the private key and the passphrase
372
- * @param {Object} params - Should contain all params expected by Box OAuth2 token endpoint
373
- * @param {TokenRequestOptions} [options] - Sets optional behavior for the token grant
374
- * @param {Error} error - Error from the previous JWT request
375
- * @param {int} numRetries - Number of retries attempted
376
- * @returns {Promise<TokenInfo>} Promise resolving to the token info
377
- */
378
- // eslint-disable-next-line max-params
379
- retryJWTGrant(claims, jwtOptions, keyParams, params, options, error, numRetries) {
380
- if (numRetries < this.config.numMaxRetries && isJWTAuthErrorRetryable(error)) {
381
- var retryTimeout;
382
- numRetries += 1;
383
- // If the retry strategy is defined, then use it to determine the time (in ms) until the next retry or to
384
- // propagate an error to the user.
385
- if (this.config.retryStrategy) {
386
- // Get the total elapsed time so far since the request was executed
387
- var totalElapsedTime = process.hrtime(asyncRequestTimer);
388
- var totalElapsedTimeMS = (totalElapsedTime[0] * 1000) + (totalElapsedTime[1] / 1000000);
389
- var retryOptions = {
390
- error,
391
- numRetryAttempts: numRetries,
392
- numMaxRetries: this.config.numMaxRetries,
393
- retryIntervalMS: this.config.retryIntervalMS,
394
- totalElapsedTimeMS
395
- };
396
-
397
- retryTimeout = this.config.retryStrategy(retryOptions);
398
-
399
- // If the retry strategy doesn't return a number/time in ms, then propagate the response error to the user.
400
- // However, if the retry strategy returns its own error, this will be propagated to the user instead.
401
- if (typeof retryTimeout !== 'number') {
402
- if (retryTimeout instanceof Error) {
403
- error = retryTimeout;
404
- }
405
- throw error;
406
- }
407
- } else if (error.hasOwnProperty('response') && error.response.hasOwnProperty('headers') && error.response.headers.hasOwnProperty('retry-after')) {
408
- retryTimeout = error.response.headers['retry-after'] * 1000;
409
- } else {
410
- retryTimeout = getRetryTimeout(numRetries, this.config.retryIntervalMS);
411
- }
412
-
413
- var time = Math.floor(Date.now() / 1000);
414
- if (error.response.headers.date) {
415
- time = Math.floor(Date.parse(error.response.headers.date) / 1000);
416
- }
417
- // Add length of retry timeout to current expiration time to calculate the expiration time for the JTI claim.
418
- claims.exp = time + this.config.appAuth.expirationTime + (retryTimeout / 1000);
419
- jwtOptions.jwtid = uuid.v4();
420
-
421
- try {
422
- params.assertion = jwt.sign(claims, keyParams, jwtOptions);
423
- } catch (jwtErr) {
424
- throw jwtErr;
425
- }
426
-
427
- return Promise.delay(retryTimeout).then(() => {
428
- // Start the request timer immediately before executing the async request
429
- asyncRequestTimer = process.hrtime();
430
- return this.getTokens(params, options)
431
- .catch(err => this.retryJWTGrant(claims, jwtOptions, keyParams, params, options, err, numRetries));
432
- });
433
- } else if (numRetries >= this.config.numMaxRetries) {
434
- error.maxRetriesExceeded = true;
435
- }
436
-
437
- throw error;
438
- },
439
-
440
- /**
441
- * Exchange a valid access token for one with a lower scope, or delegated to
442
- * an external user identifier.
443
- *
444
- * @param {string} accessToken - The valid access token to exchange
445
- * @param {string|string[]} scopes - The scope(s) of the new access token
446
- * @param {string} [resource] - The absolute URL of an API resource to restrict the new token to
447
- * @param {Object} [options] - Optional parameters
448
- * @param {TokenRequestOptions} [options.tokenRequestOptions] - Sets optional behavior for the token grant
449
- * @param {ActorParams} [options.actor] - Optional actor parameters for creating annotator tokens
450
- * @param {SharedLinkParams} [options.sharedLink] - Optional shared link parameters for creating tokens using shared links
451
- * @returns {Promise<TokenInfo>} Promise resolving to the new token info
452
- */
453
- exchangeToken(accessToken, scopes, resource, options) {
454
- var params = {
455
- grant_type: grantTypes.TOKEN_EXCHANGE,
456
- subject_token_type: ACCESS_TOKEN_TYPE,
457
- subject_token: accessToken,
458
- scope: (typeof scopes === 'string' ? scopes : scopes.join(' '))
459
- };
460
-
461
- if (resource) {
462
- params.resource = resource;
463
- }
464
-
465
- if (options && options.sharedLink) {
466
- params.box_shared_link = options.sharedLink.url;
467
- }
468
-
469
- if (options && options.actor) {
470
-
471
- var payload = {
472
- iss: this.config.clientID,
473
- sub: options.actor.id,
474
- aud: BOX_JWT_AUDIENCE,
475
- box_sub_type: 'external',
476
- name: options.actor.name
477
- };
478
-
479
- var jwtOptions = {
480
- algorithm: 'none',
481
- expiresIn: '1m',
482
- noTimestamp: true,
483
- jwtid: uuid.v4()
484
- };
485
-
486
- var token;
487
- try {
488
- token = jwt.sign(payload, 'UNUSED', jwtOptions);
489
- } catch (jwtError) {
490
- return Promise.reject(jwtError);
491
- }
492
-
493
- params.actor_token = token;
494
- params.actor_token_type = ACTOR_TOKEN_TYPE;
495
- }
496
-
497
- return this.getTokens(params, options && options.tokenRequestOptions ? options.tokenRequestOptions : null);
498
- },
499
-
500
- /**
501
- * Revokes a token pair associated with a given access or refresh token.
502
- *
503
- * @param {string} token - A valid access or refresh token to revoke
504
- * @param {TokenRequestOptions} [options] - Sets optional behavior for the token grant
505
- * @returns {Promise} Promise resolving if the revoke succeeds
506
- */
507
- revokeTokens(token, options) {
508
- var params = {
509
- method: 'POST',
510
- url: this.oauthBaseURL + tokenPaths.REVOKE,
511
- form: {
512
- token,
513
- client_id: this.config.clientID,
514
- client_secret: this.config.clientSecret
515
- }
516
- };
517
-
518
- if (options && options.ip) {
519
- params.headers = {};
520
- params.headers[HEADER_XFF] = options.ip;
521
- }
522
-
523
- return this.requestManager.makeRequest(params);
524
- }
525
- };
526
-
527
- /**
528
- * Provides interactions with Box OAuth2 tokening system.
529
- *
530
- * @module box-node-sdk/lib/token-manager
531
- */
132
+ var TokenManager = /** @class */ (function () {
133
+ function TokenManager(config, requestManager) {
134
+ this.config = config;
135
+ this.oauthBaseURL = config.apiRootURL + tokenPaths.ROOT;
136
+ this.requestManager = requestManager;
137
+ }
138
+ /**
139
+ * Given a TokenInfo object, returns whether its access token is expired. An access token is considered
140
+ * expired once its TTL surpasses the current time outside of the given buffer. This is a public method so
141
+ * that other modules may check the validity of their tokens.
142
+ *
143
+ * @param {TokenInfo} tokenInfo the token info to be written
144
+ * @param {int} [bufferMS] An optional buffer we'd like to test against. The greater this buffer, the more aggressively
145
+ * we'll call a token invalid.
146
+ * @returns {boolean} True if token is valid outside of buffer, otherwise false
147
+ */
148
+ TokenManager.prototype.isAccessTokenValid = function (tokenInfo, bufferMS) {
149
+ if (typeof tokenInfo.acquiredAtMS === 'undefined' ||
150
+ typeof tokenInfo.accessTokenTTLMS === 'undefined') {
151
+ return false;
152
+ }
153
+ bufferMS = bufferMS || 0;
154
+ var expireTime = tokenInfo.acquiredAtMS + tokenInfo.accessTokenTTLMS - bufferMS;
155
+ return expireTime > Date.now();
156
+ };
157
+ /**
158
+ * Acquires OAuth2 tokens using a grant type (authorization_code, password, refresh_token)
159
+ *
160
+ * @param {Object} formParams - should contain all params expected by Box OAuth2 token endpoint
161
+ * @param {TokenRequestOptions} [options] - Sets optional behavior for the token grant, null for default behavior
162
+ * @returns {Promise<TokenInfo>} Promise resolving to the token info
163
+ * @private
164
+ */
165
+ TokenManager.prototype.getTokens = function (formParams, options) {
166
+ var params = {
167
+ method: 'POST',
168
+ url: this.oauthBaseURL + tokenPaths.GET,
169
+ headers: {},
170
+ form: formParams,
171
+ };
172
+ options = options || {};
173
+ // add in app-specific id and secret to auth with Box
174
+ params.form.client_id = this.config.clientID;
175
+ params.form.client_secret = this.config.clientSecret;
176
+ if (options.ip) {
177
+ params.headers[HEADER_XFF] = options.ip;
178
+ }
179
+ return this.requestManager.makeRequest(params).then(function (response /* FIXME */) {
180
+ // Response Error: The API is telling us that we attempted an invalid token grant. This
181
+ // means that our refresh token or auth code has exipred, so propagate an "Expired Tokens"
182
+ // error.
183
+ if (response.body &&
184
+ response.body.error &&
185
+ response.body.error === 'invalid_grant') {
186
+ var errDescription = response.body.error_description;
187
+ var message = errDescription
188
+ ? "Auth Error: " + errDescription
189
+ : undefined;
190
+ throw errors_1.default.buildAuthError(response, message);
191
+ }
192
+ // Unexpected Response: If the token request couldn't get a valid response, then we're
193
+ // out of options. Build an "Unexpected Response" error and propagate it out for the
194
+ // consumer to handle.
195
+ if (response.statusCode !== http_status_1.default.OK ||
196
+ response.body instanceof Buffer) {
197
+ throw errors_1.default.buildUnexpectedResponseError(response);
198
+ }
199
+ // Check to see if token response is valid in case the API returns us a 200 with a malformed token
200
+ if (!isValidTokenResponse(formParams.grant_type, response.body)) {
201
+ throw errors_1.default.buildResponseError(response, 'Token format from response invalid');
202
+ }
203
+ // Got valid token response. Parse out the TokenInfo and propagate it back.
204
+ return getTokensFromGrantResponse(response.body);
205
+ });
206
+ };
207
+ /**
208
+ * Acquires token info using an authorization code
209
+ *
210
+ * @param {string} authorizationCode - authorization code issued by Box
211
+ * @param {TokenRequestOptions} [options] - Sets optional behavior for the token grant
212
+ * @returns {Promise<TokenInfo>} Promise resolving to the token info
213
+ */
214
+ TokenManager.prototype.getTokensAuthorizationCodeGrant = function (authorizationCode, options) {
215
+ if (!isValidCodeOrToken(authorizationCode)) {
216
+ return bluebird_1.default.reject(new Error('Invalid authorization code.'));
217
+ }
218
+ var params = {
219
+ grant_type: grantTypes.AUTHORIZATION_CODE,
220
+ code: authorizationCode,
221
+ };
222
+ return this.getTokens(params, options);
223
+ };
224
+ /**
225
+ * Acquires token info using the client credentials grant.
226
+ *
227
+ * @param {TokenRequestOptions} [options] - Sets optional behavior for the token grant
228
+ * @returns {Promise<TokenInfo>} Promise resolving to the token info
229
+ */
230
+ TokenManager.prototype.getTokensClientCredentialsGrant = function (options) {
231
+ var params = {
232
+ grant_type: grantTypes.CLIENT_CREDENTIALS,
233
+ };
234
+ return this.getTokens(params, options);
235
+ };
236
+ /**
237
+ * Refreshes the access and refresh tokens for a given refresh token.
238
+ *
239
+ * @param {string} refreshToken - A valid OAuth refresh token
240
+ * @param {TokenRequestOptions} [options] - Sets optional behavior for the token grant
241
+ * @returns {Promise<TokenInfo>} Promise resolving to the token info
242
+ */
243
+ TokenManager.prototype.getTokensRefreshGrant = function (refreshToken, options) {
244
+ if (!isValidCodeOrToken(refreshToken)) {
245
+ return bluebird_1.default.reject(new Error('Invalid refresh token.'));
246
+ }
247
+ var params = {
248
+ grant_type: grantTypes.REFRESH_TOKEN,
249
+ refresh_token: refreshToken,
250
+ };
251
+ return this.getTokens(params, options);
252
+ };
253
+ /**
254
+ * Gets tokens for enterprise administration of app users
255
+ * @param {string} type The type of token to create, "user" or "enterprise"
256
+ * @param {string} id The ID of the enterprise to generate a token for
257
+ * @param {TokenRequestOptions} [options] - Sets optional behavior for the token grant
258
+ * @returns {Promise<TokenInfo>} Promise resolving to the token info
259
+ */
260
+ TokenManager.prototype.getTokensJWTGrant = function (type, id, options) {
261
+ var _this = this;
262
+ if (!this.config.appAuth.keyID) {
263
+ return bluebird_1.default.reject(new Error('Must provide app auth configuration to use JWT Grant'));
264
+ }
265
+ var claims = {
266
+ exp: Math.floor(Date.now() / 1000) + this.config.appAuth.expirationTime,
267
+ box_sub_type: type,
268
+ };
269
+ var jwtOptions = {
270
+ algorithm: this.config.appAuth.algorithm,
271
+ audience: BOX_JWT_AUDIENCE,
272
+ subject: id,
273
+ issuer: this.config.clientID,
274
+ jwtid: uuid_1.default.v4(),
275
+ noTimestamp: !this.config.appAuth.verifyTimestamp,
276
+ keyid: this.config.appAuth.keyID,
277
+ };
278
+ var keyParams = {
279
+ key: this.config.appAuth.privateKey,
280
+ passphrase: this.config.appAuth.passphrase,
281
+ };
282
+ var assertion;
283
+ try {
284
+ assertion = jsonwebtoken_1.default.sign(claims, keyParams, jwtOptions);
285
+ }
286
+ catch (jwtErr) {
287
+ return bluebird_1.default.reject(jwtErr);
288
+ }
289
+ var params = {
290
+ grant_type: grantTypes.JWT,
291
+ assertion: assertion,
292
+ };
293
+ // Start the request timer immediately before executing the async request
294
+ asyncRequestTimer = process.hrtime();
295
+ return this.getTokens(params, options).catch(function (err) {
296
+ return _this.retryJWTGrant(claims, jwtOptions, keyParams, params, options, err, 0);
297
+ });
298
+ };
299
+ /**
300
+ * Attempt a retry if possible and create a new JTI claim. If the request hasn't exceeded it's maximum number of retries,
301
+ * re-execute the request (after the retry interval). Otherwise, propagate a new error.
302
+ *
303
+ * @param {Object} claims - JTI claims object
304
+ * @param {Object} [jwtOptions] - JWT options for the signature
305
+ * @param {Object} keyParams - Key JWT parameters object that contains the private key and the passphrase
306
+ * @param {Object} params - Should contain all params expected by Box OAuth2 token endpoint
307
+ * @param {TokenRequestOptions} [options] - Sets optional behavior for the token grant
308
+ * @param {Error} error - Error from the previous JWT request
309
+ * @param {int} numRetries - Number of retries attempted
310
+ * @returns {Promise<TokenInfo>} Promise resolving to the token info
311
+ */
312
+ // eslint-disable-next-line max-params
313
+ TokenManager.prototype.retryJWTGrant = function (claims /* FIXME */, jwtOptions /* FIXME */, keyParams /* FIXME */, params /* FIXME */, options, error /* FIXME */, numRetries) {
314
+ var _this = this;
315
+ if (numRetries < this.config.numMaxRetries &&
316
+ isJWTAuthErrorRetryable(error)) {
317
+ var retryTimeout;
318
+ numRetries += 1;
319
+ // If the retry strategy is defined, then use it to determine the time (in ms) until the next retry or to
320
+ // propagate an error to the user.
321
+ if (this.config.retryStrategy) {
322
+ // Get the total elapsed time so far since the request was executed
323
+ var totalElapsedTime = process.hrtime(asyncRequestTimer);
324
+ var totalElapsedTimeMS = totalElapsedTime[0] * 1000 + totalElapsedTime[1] / 1000000;
325
+ var retryOptions = {
326
+ error: error,
327
+ numRetryAttempts: numRetries,
328
+ numMaxRetries: this.config.numMaxRetries,
329
+ retryIntervalMS: this.config.retryIntervalMS,
330
+ totalElapsedTimeMS: totalElapsedTimeMS,
331
+ };
332
+ retryTimeout = this.config.retryStrategy(retryOptions);
333
+ // If the retry strategy doesn't return a number/time in ms, then propagate the response error to the user.
334
+ // However, if the retry strategy returns its own error, this will be propagated to the user instead.
335
+ if (typeof retryTimeout !== 'number') {
336
+ if (retryTimeout instanceof Error) {
337
+ error = retryTimeout;
338
+ }
339
+ throw error;
340
+ }
341
+ }
342
+ else if (error.hasOwnProperty('response') &&
343
+ error.response.hasOwnProperty('headers') &&
344
+ error.response.headers.hasOwnProperty('retry-after')) {
345
+ retryTimeout = error.response.headers['retry-after'] * 1000;
346
+ }
347
+ else {
348
+ retryTimeout = exponential_backoff_1.default(numRetries, this.config.retryIntervalMS);
349
+ }
350
+ var time = Math.floor(Date.now() / 1000);
351
+ if (error.response.headers.date) {
352
+ time = Math.floor(Date.parse(error.response.headers.date) / 1000);
353
+ }
354
+ // Add length of retry timeout to current expiration time to calculate the expiration time for the JTI claim.
355
+ claims.exp =
356
+ time + this.config.appAuth.expirationTime + retryTimeout / 1000;
357
+ jwtOptions.jwtid = uuid_1.default.v4();
358
+ try {
359
+ params.assertion = jsonwebtoken_1.default.sign(claims, keyParams, jwtOptions);
360
+ }
361
+ catch (jwtErr) {
362
+ throw jwtErr;
363
+ }
364
+ return bluebird_1.default.delay(retryTimeout).then(function () {
365
+ // Start the request timer immediately before executing the async request
366
+ asyncRequestTimer = process.hrtime();
367
+ return _this.getTokens(params, options).catch(function (err) {
368
+ return _this.retryJWTGrant(claims, jwtOptions, keyParams, params, options, err, numRetries);
369
+ });
370
+ });
371
+ }
372
+ else if (numRetries >= this.config.numMaxRetries) {
373
+ error.maxRetriesExceeded = true;
374
+ }
375
+ throw error;
376
+ };
377
+ /**
378
+ * Exchange a valid access token for one with a lower scope, or delegated to
379
+ * an external user identifier.
380
+ *
381
+ * @param {string} accessToken - The valid access token to exchange
382
+ * @param {string|string[]} scopes - The scope(s) of the new access token
383
+ * @param {string} [resource] - The absolute URL of an API resource to restrict the new token to
384
+ * @param {Object} [options] - Optional parameters
385
+ * @param {TokenRequestOptions} [options.tokenRequestOptions] - Sets optional behavior for the token grant
386
+ * @param {ActorParams} [options.actor] - Optional actor parameters for creating annotator tokens
387
+ * @param {SharedLinkParams} [options.sharedLink] - Optional shared link parameters for creating tokens using shared links
388
+ * @returns {Promise<TokenInfo>} Promise resolving to the new token info
389
+ */
390
+ TokenManager.prototype.exchangeToken = function (accessToken, scopes, resource, options) {
391
+ var params = {
392
+ grant_type: grantTypes.TOKEN_EXCHANGE,
393
+ subject_token_type: ACCESS_TOKEN_TYPE,
394
+ subject_token: accessToken,
395
+ scope: typeof scopes === 'string' ? scopes : scopes.join(' '),
396
+ };
397
+ if (resource) {
398
+ params.resource = resource;
399
+ }
400
+ if (options && options.sharedLink) {
401
+ params.box_shared_link = options.sharedLink.url;
402
+ }
403
+ if (options && options.actor) {
404
+ var payload = {
405
+ iss: this.config.clientID,
406
+ sub: options.actor.id,
407
+ aud: BOX_JWT_AUDIENCE,
408
+ box_sub_type: 'external',
409
+ name: options.actor.name,
410
+ };
411
+ var jwtOptions = {
412
+ algorithm: 'none',
413
+ expiresIn: '1m',
414
+ noTimestamp: true,
415
+ jwtid: uuid_1.default.v4(),
416
+ };
417
+ var token;
418
+ try {
419
+ token = jsonwebtoken_1.default.sign(payload, 'UNUSED', jwtOptions /* FIXME */);
420
+ }
421
+ catch (jwtError) {
422
+ return bluebird_1.default.reject(jwtError);
423
+ }
424
+ params.actor_token = token;
425
+ params.actor_token_type = ACTOR_TOKEN_TYPE;
426
+ }
427
+ return this.getTokens(params, options && options.tokenRequestOptions
428
+ ? options.tokenRequestOptions
429
+ : null);
430
+ };
431
+ /**
432
+ * Revokes a token pair associated with a given access or refresh token.
433
+ *
434
+ * @param {string} token - A valid access or refresh token to revoke
435
+ * @param {TokenRequestOptions} [options] - Sets optional behavior for the token grant
436
+ * @returns {Promise} Promise resolving if the revoke succeeds
437
+ */
438
+ TokenManager.prototype.revokeTokens = function (token, options) {
439
+ var params = {
440
+ method: 'POST',
441
+ url: this.oauthBaseURL + tokenPaths.REVOKE,
442
+ form: {
443
+ token: token,
444
+ client_id: this.config.clientID,
445
+ client_secret: this.config.clientSecret,
446
+ },
447
+ };
448
+ if (options && options.ip) {
449
+ params.headers = {};
450
+ params.headers[HEADER_XFF] = options.ip;
451
+ }
452
+ return this.requestManager.makeRequest(params);
453
+ };
454
+ return TokenManager;
455
+ }());
532
456
  module.exports = TokenManager;
457
+ //# sourceMappingURL=token-manager.js.map