box / box-node-sdk Goto Github PK
View Code? Open in Web Editor NEWA Javascript interface for interacting with the Box API. You can find the node package at
Home Page: https://www.npmjs.com/package/box-node-sdk
License: Apache License 2.0
A Javascript interface for interacting with the Box API. You can find the node package at
Home Page: https://www.npmjs.com/package/box-node-sdk
License: Apache License 2.0
I can't see it in the docs, but does the SDK do this: https://docs.box.com/reference#get-embed-link ??
If not, can I add functions to the client to make that possible??
Thanks
We have some old code using node 0.12.7, and I needed this library there. I patched it and made all the tests pass. I'll submit a pull request if you like, but I assume you want to continue with ECMA6.
https://github.com/MobileDay/box-node-sdk/tree/node_v0.12.7
Here are some of the errors I saw:
SyntaxError: Unexpected token =>
box-client.js:238-239 undefined is not a function (Object.assign)
We're experiencing cases with payload returning from search.query
endpoint looking like this (total_count
is not zero but the entries
array is empty):
{
total_count: 10,
entries:
[],
limit: 1,
offset: 0
}
90% of the time we receive this:
{
total_count: 1,
entries:
[
{
type: 'file',
id: '126793694652',
// rest of the payload
}
],
limit: 1,
offset: 0
}
Our use case: a script hits a Box folder programmatically and uploads a CSV file to it (filename is always the same). Before uploading, it performs a search to check whether a file with that name already exists; if it does - we upload a new version. If it does not - we upload a new file. This action may sometimes repeatedly run within the span of 10 minutes.
Could this be somehow related to the below note in the documentation?
If an item is added to Box then it becomes accessible through the search endpoint after ten minutes.
Using the Persistent Client in the box-node-sdk v1.7.0 library.
We can authorize successfully and the majority of requests succeed, however we sometimes get 401 Expired Auth errors thrown for api calls in production on GCP.
It seems to happen at random, and we haven't been able to reproduce it locally.
The error does not affect any specific files or users. Retrying at a later time usually succeeds.
Here is a copy of the error being thrown when we try to get folder id 0:
{
authExpired: true
cause: {
authExpired: true
response: {
headers: {
age: "0"
connection: "keep-alive"
content-length: "0"
date: "Mon, 24 Jul 2017 09:10:24 GMT"
server: "ATS"
strict-transport-security: "max-age=31536000; includeSubDomains"
vary: "Accept-Encoding"
www-authenticate: "Bearer realm="Service", error="invalid_token", error_description="The access token provided is invalid.""
}
request: {
headers: {
Authorization: "[REMOVED BY SDK]"
User-Agent: "Box Node.js SDK v1.7.0"
accept: "application/json"
}
method: "GET"
uri: {
auth: null
hash: null
host: "api.box.com"
hostname: "api.box.com"
href: "https://api.box.com/2.0/folders/0"
path: "/2.0/folders/0"
pathname: "/2.0/folders/0"
port: 443
protocol: "https:"
query: null
search: null
slashes: true
}
}
statusCode: 401
}
statusCode: 401
}
isOperational: true
response: {
$ref: "$["err"]["cause"]["response"]"
}
statusCode: 401
}
This is from our production logs. response: { $ref }
is actually just a duplicate reference detected by cycles.decycle to the object at err.cause.response.
the README.md states that the persistent client should handle refreshing and retrying, so i don't see why it is throwing a 401 back up to our application.
Sorry for posting this question here instead of support but last time I contacted them it took 2.5 months (no joke...) to answer.
My question:
Are id
provided by the api unique across all types? (aka files/folders/web_links, etc?)
Thanks
When i change the config.js and token-manager.js files still it throwws error like please check the exp claim
can you help me to get out this error
Hello all
I am just running the 'app-auth' sample app and uploaded a file onto box.
However, when I go back to the original box web interface, I couldn't see the file and can't search for it anywhere.
However, in the node js app, its able to find it and return the image.
I am very confused as to where is the file actually stored, please help!! ><
Using example from:
https://github.com/box/box-node-sdk/blob/master/docs/files.md#upload-a-file
My simple upload function below will always fail with ETIMEDOUT. Can you clarify the reason for this failure? I passed authentication steps, even created a folder. This error seems to happen in the core, not in the API. Is it a problem with auth? Windows issue?
var stream = fs.createReadStream(path.normalize('./public/img/icons.png'));
client.files.uploadFile(folder_id, 'icons.png', stream, function(err, data){
if (err) {
console.log("Error sending a zipfile into " + folder_id + " to Box, Reason: " + err);
} else {
console.log("Zip sent to Box");
}
});
Hey! Would love to add webhooks to the node sdk, thanks!
There's a small inconsistency between box's provided app settings and what the node sdk expects.
At
box-node-sdk/lib/util/config.js
Line 113 in 6f97091
keyID
field. The provided JSON from the developer console provides the following structure:
{
"boxAppSettings": {
"clientID": "",
"clientSecret": "",
"appAuth": {
"publicKeyID": "",
"privateKey": "",
"passphrase": ""
}
},
"enterpriseID": ""
}
I couldn't find it noted in any documentation, but the publicKeyID
field must be renamed to keyID
for authorization to succeed.
If I create an SDK with app auth but with an incorrect passphrase, I don't get any errors but all API calls I make return an err value of {}
.
Creating the SDK object appears to return normally.
And creating the client object appears to return normally (I used const box = sdk.getAppAuthClient('user', process.env.BOX_USER_ID);
)
But then making an API call like box.users.get(box.CURRENT_USER_ID, null, (err, currentUser) => {})
returns with err set to {}
JWT doesnt work with nodeJS SDK for Box- token is always expried even when passign ASSERTION exp and iat are valid. this was supposedly fixed in 1.4.0 but is definitrly not.
Hi guys,
when executing the following function,
client.search.query(filename, { type: 'folder' }, function (err, jsonData) { // ...do something });
and a folder with that name already exists, invalid JSON is being returned e.g.
{ Error: Unexpected API Response [409 Conflict] (item_name_in_use: "Item with the same name already exists") at Object.buildResponseError (/home/ubuntu/workspace/box-scanned-docs-uploader/node_modules/box-node-sdk/lib/util/errors.js:57:23) at Object.buildUnexpectedResponseError (/home/ubuntu/workspace/box-scanned-docs-uploader/node_modules/box-node-sdk/lib/util/errors.js:94:15) at /home/ubuntu/workspace/box-scanned-docs-uploader/node_modules/box-node-sdk/lib/box-client.js:622:19 at tryCatcher (/home/ubuntu/workspace/box-scanned-docs-uploader/node_modules/bluebird/js/release/util.js:16:23) at Promise.successAdapter [as _fulfillmentHandler0] (/home/ubuntu/workspace/box-scanned-docs-uploader/node_modules/bluebird/js/release/nodeify.js:23:30) at Promise._settlePromise (/home/ubuntu/workspace/box-scanned-docs-uploader/node_modules/bluebird/js/release/promise.js:566:21) at Promise._settlePromise0 (/home/ubuntu/workspace/box-scanned-docs-uploader/node_modules/bluebird/js/release/promise.js:614:10) at Promise._settlePromises (/home/ubuntu/workspace/box-scanned-docs-uploader/node_modules/bluebird/js/release/promise.js:693:18) at Promise._fulfill (/home/ubuntu/workspace/box-scanned-docs-uploader/node_modules/bluebird/js/release/promise.js:638:18) at Promise._settlePromise (/home/ubuntu/workspace/box-scanned-docs-uploader/node_modules/bluebird/js/release/promise.js:582:21) at Promise._settlePromise0 (/home/ubuntu/workspace/box-scanned-docs-uploader/node_modules/bluebird/js/release/promise.js:614:10) at Promise._settlePromises (/home/ubuntu/workspace/box-scanned-docs-uploader/node_modules/bluebird/js/release/promise.js:693:18) at Promise._fulfill (/home/ubuntu/workspace/box-scanned-docs-uploader/node_modules/bluebird/js/release/promise.js:638:18) at /home/ubuntu/workspace/box-scanned-docs-uploader/node_modules/bluebird/js/release/nodeback.js:42:21 at BoxClient._handleResponse (/home/ubuntu/workspace/box-scanned-docs-uploader/node_modules/box-node-sdk/lib/box-client.js:308:2) at handleResponseCallback (/home/ubuntu/workspace/box-scanned-docs-uploader/node_modules/box-node-sdk/lib/box-client.js:241:10) statusCode: 409, response: IncomingMessage { _readableState: ReadableState { objectMode: false, highWaterMark: 16384, buffer: [Object], length: 0, pipes: null, pipesCount: 0, flowing: true, ended: true, endEmitted: true, reading: false, sync: false, needReadable: false, emittedReadable: false, readableListening: false, resumeScheduled: false, defaultEncoding: 'utf8', ranOut: false, awaitDrain: 0, readingMore: false, decoder: null, encoding: null }, readable: false, domain: null, _events: { end: [Object], close: [Object], data: [Function], error: [Function] }, _eventsCount: 4, _maxListeners: undefined, socket: TLSSocket { _tlsOptions: [Object], _secureEstablished: true, _securePending: false, _newSessionPending: false, _controlReleased: true, _SNICallback: null, servername: null, npnProtocol: false, alpnProtocol: false, authorized: true, authorizationError: null, encrypted: true, _events: [Object], _eventsCount: 9, connecting: false, _hadError: false, _handle: [Object], _parent: null, _host: 'upload.box.com', _readableState: [Object], readable: true, domain: null, _maxListeners: undefined, _writableState: [Object], writable: true, allowHalfOpen: false, destroyed: false, _bytesDispatched: 701, _sockname: null, _pendingData: null, _pendingEncoding: '', server: undefined, _server: null, ssl: [Object], _requestCert: true, _rejectUnauthorized: true, parser: null, _httpMessage: null, read: [Function], _consuming: true, _idleTimeout: -1, _idleNext: null, _idlePrev: null, _idleStart: 2233 }, connection: TLSSocket { _tlsOptions: [Object], _secureEstablished: true, _securePending: false, _newSessionPending: false, _controlReleased: true, _SNICallback: null, servername: null, npnProtocol: false, alpnProtocol: false, authorized: true, authorizationError: null, encrypted: true, _events: [Object], _eventsCount: 9, connecting: false, _hadError: false, _handle: [Object], _parent: null, _host: 'upload.box.com', _readableState: [Object], readable: true, domain: null, _maxListeners: undefined, _writableState: [Object], writable: true, allowHalfOpen: false, destroyed: false, _bytesDispatched: 701, _sockname: null, _pendingData: null, _pendingEncoding: '', server: undefined, _server: null, ssl: [Object], _requestCert: true, _rejectUnauthorized: true, parser: null, _httpMessage: null, read: [Function], _consuming: true, _idleTimeout: -1, _idleNext: null, _idlePrev: null, _idleStart: 2233 }, httpVersionMajor: 1, httpVersionMinor: 1, httpVersion: '1.1', complete: true, headers: { date: 'Wed, 26 Jul 2017 09:25:43 GMT', server: 'ATS', 'content-type': 'application/json', 'cache-control': 'no-cache, no-store', 'strict-transport-security': 'max-age=31536000; includeSubDomains', vary: 'Accept-Encoding', 'content-length': '471', age: '0', connection: 'keep-alive' }, rawHeaders: [ 'Date', 'Wed, 26 Jul 2017 09:25:43 GMT', 'Server', 'ATS', 'Content-Type', 'application/json', 'Cache-Control', 'no-cache, no-store', 'Strict-Transport-Security', 'max-age=31536000; includeSubDomains', 'Vary', 'Accept-Encoding', 'Content-Length', '471', 'Age', '0', 'Connection', 'keep-alive' ], trailers: {}, rawTrailers: [], upgrade: false, url: '', method: null, statusCode: 409, statusMessage: 'Conflict', client: TLSSocket { _tlsOptions: [Object], _secureEstablished: true, _securePending: false, _newSessionPending: false, _controlReleased: true, _SNICallback: null, servername: null, npnProtocol: false, alpnProtocol: false, authorized: true, authorizationError: null, encrypted: true, _events: [Object], _eventsCount: 9, connecting: false, _hadError: false, _handle: [Object], _parent: null, _host: 'upload.box.com', _readableState: [Object], readable: true, domain: null, _maxListeners: undefined, _writableState: [Object], writable: true, allowHalfOpen: false, destroyed: false, _bytesDispatched: 701, _sockname: null, _pendingData: null, _pendingEncoding: '', server: undefined, _server: null, ssl: [Object], _requestCert: true, _rejectUnauthorized: true, parser: null, _httpMessage: null, read: [Function], _consuming: true, _idleTimeout: -1, _idleNext: null, _idlePrev: null, _idleStart: 2233 }, _consuming: true, _dumped: false, req: ClientRequest { domain: null, _events: [Object], _eventsCount: 6, _maxListeners: undefined, output: [], outputEncodings: [], outputCallbacks: [], outputSize: 0, writable: true, _last: false, upgrading: false, chunkedEncoding: false, shouldKeepAlive: true, useChunkedEncodingByDefault: true, sendDate: false, _removedHeader: [Object], _contentLength: null, _hasBody: true, _trailer: '', finished: true, _headerSent: true, socket: [Object], connection: [Object], _header: 'POST /api/2.0/files/content HTTP/1.1\r\nUser-Agent: Box Node.js SDK v1.7.0\r\nAuthorization: Bearer JSoTmeb1rjLN9KtfQERuMdRIPBxewzGS\r\nhost: upload.box.com\r\naccept: application/json\r\ncontent-type: multipart/form-data; boundary=--------------------------044794650448047235014794\r\ncontent-length: 380\r\nConnection: keep-alive\r\n\r\n', _headers: [Object], _headerNames: [Object], _onPendingData: null, agent: [Object], socketPath: undefined, timeout: undefined, method: 'POST', path: '/api/2.0/files/content', _ended: true, parser: null, timeoutCb: null, res: [Circular] }, request: Request { domain: null, _events: [Object], _eventsCount: 5, _maxListeners: undefined, strictSSL: true, agentClass: [Object], agentOptions: [Object], encoding: null, followRedirect: false, headers: [Object], method: 'POST', formData: [Object], timeout: 60000, callback: [Function], readable: true, writable: true, explicitMethod: true, _qs: [Object], _auth: [Object], _oauth: [Object], _multipart: [Object], _redirect: [Object], _tunnel: [Object], setHeader: [Function], hasHeader: [Function], getHeader: [Function], removeHeader: [Function], localAddress: undefined, pool: [Object], dests: [], __isRequestRequest: true, _callback: [Function: bound ], uri: [Object], proxy: null, tunnel: true, setHost: true, originalCookieHeader: undefined, _disableCookies: true, _jar: undefined, port: 443, host: 'upload.box.com', _form: [Object], path: '/api/2.0/files/content', _json: true, httpModule: [Object], agent: [Object], ntick: true, src: [Object], _started: true, href: 'https://upload.box.com/api/2.0/files/content', req: [Object], timeoutTimer: null, response: [Circular], originalHost: 'upload.box.com', originalHostHeaderName: 'host', responseContent: [Circular], _destdata: true, _ended: true, _callbackCalled: true }, toJSON: [Function: responseToJSON], caseless: Caseless { dict: [Object] }, read: [Function], body: { type: 'error', status: 409, code: 'item_name_in_use', context_info: [Object], help_url: 'http://developers.box.com/docs/#errors', message: 'Item with the same name already exists', request_id: '90090560459786017a5c8c' } } }
I think that the 'Error' property might need encapsulating with quotes? Can this be resolved please? Thanks.
It was discovered in the API docs that the file download URL endpoint only supported version as a query string, while Range and BoxAPI is a header (Link: https://docs.box.com/reference#download-a-file) (initially listed Range, version, and BoxAPI all as acceptable query strings).
I'm wondering if the Node SDK will support the "Range" header as a param of the getReadStream() method, as "qs" was supposed to support the documented query strings from the API docs.
Hi,
I'm using the Box Node SDK as an app user for a variety of upload use cases, and I've seen a sharp increase in socket hang up issues in the last couple of days. Could you provide some guidance on how we can best solve this?
We've been using the SDK for about 8 months now, and haven't changed anything in our underlying implementation in the last couple of weeks apart from additional error handling and logging. We're on 1.3.0 but I also don't see any changes from the PRs that refer to this issue.
Any guidance would be appreciated - thanks!
Error: socket hang up
at createHangUpError (_http_client.js:253:15)
at TLSSocket.socketOnEnd (_http_client.js:345:23)
at emitNone (events.js:91:20)
at TLSSocket.emit (events.js:185:7)
at endReadableNT (_stream_readable.js:974:12)
at _combinedTickCallback (internal/process/next_tick.js:80:11)
at process._tickDomainCallback (internal/process/next_tick.js:128:9)
I'm able to update other fields for the user but when I try to add an email alias, I get a 403 forbidden.
client.users.addEmailAlias(userId, '[email protected]', function (err, data){
console.log(err);
});
[Error: Unexpected API Response [403 Forbidden] (forbidden: "Forbidden")]
I have written up some documentation for client.asUser()
and client.asSelf()
. I will submit a pull request from my forked repo.
On this line:
https://github.com/box/box-node-sdk/blob/master/examples/app-auth/index.js#L113
The code is verifying that the 'email' form field matches the 'name' value of the response.
When I ran this code, I got 'login' as a response field, not 'name'
Changing the test to 'login' seemed to fix it.
I got the /examples/app-auth/index.js server running and homepage displayed. But when I try to login I get this error:
An error occurred during login - error:0906D06C:PEM routines:PEM_read_bio:no start line
Error: error:0906D06C:PEM routines:PEM_read_bio:no start line at Sign.sign (crypto.js:329:26) at Object.sign (C:\xampp\htdocs\node-home\projects\box-com\examples\app-auth\node_modules\jwa\index.js:55:45) at Object.jwsSign [as sign] (C:\xampp\htdocs\node-home\projects\box-com\examples\app-auth\node_modules\jws\lib\sign-stream.js:23:24) at Object.JWT.sign (C:\xampp\htdocs\node-home\projects\box-com\examples\app-auth\node_modules\jsonwebtoken\index.js:137:16) at TokenManager.getTokensJWTGrant (C:\xampp\htdocs\node-home\projects\box-com\examples\app-auth\node_modules\box-node-sdk\lib\token-manager.js:334:20) at AppAuthSession._refreshAppAuthAccessToken (C:\xampp\htdocs\node-home\projects\box-com\examples\app-auth\node_modules\box-node-sdk\lib\sessions\app-auth-session.js:77:20) at AppAuthSession.getAccessToken (C:\xampp\htdocs\node-home\projects\box-com\examples\app-auth\node_modules\box-node-sdk\lib\sessions\app-auth-session.js:110:8) at C:\xampp\htdocs\node-home\projects\box-com\examples\app-auth\node_modules\box-node-sdk\lib\box-client.js:216:17 at tryCatcher (C:\xampp\htdocs\node-home\projects\box-com\examples\app-auth\node_modules\bluebird\js\release\util.js:16:23) at Function.Promise.fromNode.Promise.fromCallback (C:\xampp\htdocs\node-home\projects\box-com\examples\app-auth\node_modules\bluebird\js\release\promise.js:180:30) at BoxClient._makeRequest (C:\xampp\htdocs\node-home\projects\box-com\examples\app-auth\node_modules\box-node-sdk\lib\box-client.js:213:24) at BoxClient.get (C:\xampp\htdocs\node-home\projects\box-com\examples\app-auth\node_modules\box-node-sdk\lib\box-client.js:480:14) at C:\xampp\htdocs\node-home\projects\box-com\examples\app-auth\index.js:100:17 at Layer.handle [as handle_request] (C:\xampp\htdocs\node-home\projects\box-com\examples\app-auth\node_modules\express\lib\router\layer.js:95:5) at next (C:\xampp\htdocs\node-home\projects\box-com\examples\app-auth\node_modules\express\lib\router\route.js:137:13) at Route.dispatch (C:\xampp\htdocs\node-home\projects\box-com\examples\app-auth\node_modules\express\lib\router\route.js:112:3)
I have no problem using a curl request to exchange a token (file_preview) for a certain file, I am however having issues with the sdk.
I have tried the token exchange authenticating as the app itself as well as a managed user
const sdkClient = sdk.getAppAuthClient('enterprise', process.env.BOX_ENTERPRISE_ID);
sdkClient.asUser(process.env.BOX_APP_WORKER_ID);
box.getEmbedToken = async (fileId) => {
try {
await sdkClient.exchangeToken('item_preview', 'https://api.box.com/2.0/files/' + fileId);
} catch (err) {
console.log(err);
}
};
the response i get back is this:
statusCode: 400
body:
{ error: 'invalid_resource',
error_description: 'The target resource is invalid.' } } }
What am I doing wrong here?
Hi,
Is there a way to use the node sdk to subscribe to web hooks.
Thanks
When using a persistent client the stream spins trying to refresh tokens even if access has been revoked for the app by the user. The behaviour seems to assume all tokens can be refreshed when they expire.
The first stream error emitted looks like:
{"statusCode":401,"response":{"statusCode":401,"headers":{"server":"ATS","date":"Thu, 15 Sep 2016 15:44:11 GMT","content-length":"0","www-authenticate":"Bearer realm="Service", error="invalid_token", error_description="The access token provided is invalid."","vary":"Accept-Encoding","age":"0","connection":"keep-alive"},"request":{"uri":{"protocol":"https:","slashes":true,"auth":null,"host":"api.box.com","port":null,"hostname":"api.box.com","hash":null,"search":"?stream_position=3942123628188338","query":"stream_position=3942123628188338","pathname":"/2.0/events","path":"/2.0/events?stream_position=3942123628188338","href":"https://api.box.com/2.0/events?stream_position=3942123628188338"},"method":"GET","headers":{"User-Agent":"Box Node.js SDK v1.0.0","Authorization":"[REMOVED BY SDK]","accept":"application/json"}}},"authExpired":true}
There doesn't appear to be a way to stop the stream and it tries to refresh once a second.
Looks like this has already been addressed in #23 but it still happens occasionally: 13/748091 uploads with wrong format since 2017-09-01
Currently, I dont have the client ID and client secret information to create SDK object.
I was wondering similiar to BOX SDK Java, where you just need BOX Token to make API call. Is it possible to do the same for Nodejs.
I am generated authentication using enterpise like the given syntax
sdk.getAppAuthClient('enterprise', id);
It works some time and some time it throws error like auth is expired and can you help me to resolve this issue i am struck in that issue
adminAPIClient.users.addEmailAlias adds an email alias but it's not confirmed so it doesn't show up in
adminAPIClient.users.getEmailAliases()
nor can I update a user's login to the new alias.
the code in users.js I think should set is_confirmed to true.
In box .net sdk, it sets is_confirmed to true.
My organization is using the Box Node SDK in a Typescript project, and we've been creating our own type definitions for all the pieces of the SDK that we use, but would benefit from a types library contributed to by Box (and any other contributors of the SDK) so we don't have to build types every time we start using a new feature of the Box API.
Are there any plans for Box to build some Typescript definitions for this SDK?
If not, I can submit a PR to either this repo or DefinitelyTyped with some of the types I've already created. Any preference there?
Using promises.
This is throwing
TypeError: Can't add property error, object is not extensible.
Any ideas? v1.4.2 works fine and will be pinning this down as my library until further notice
It looks like there is a bug in the SDK when we "search for metadata" as described in the document ( https://github.com/box/box-node-sdk/blob/144dd852bcf8e6c511b0141c08b635902dabd8db/docs/search.md). Pls see below
Code:
userAPIClient.search.query(
'',
{
'file_extensions': 'ppt,pptx',
'mdfilters': [
{
'templateKey': 'TopSecret',
'scope': 'enterprise',
'filters': {}
}
]
},
function(err,response){
console.log(err,response);
res.json(err);
});
Error:
{ type: 'error',
status: 400,
code: 'bad_request',
help_url: 'http://developers.box.com/docs/#errors',
message: 'Bad Request',
request_id: '856959801583385d32e9c2' } } }
PS: The basic SDK search works fine (code below).
userAPIClient.search.query('teamLogo1.png',null,function(err,response){
res.json(response);
});
Please help me to get refresh token, while i am accessing with expired token(developer token).
This looks like the same problem as #96, but I've seen it at v1.2.0 and v1.3.0.
This is the code that is producing the error:
sdk.folders.getItems(req.params.folderId, null, (err, data) => {
if (err) {
console.log(`An error occurred - ${err.message}`);
return res.status(500).send(err);
}
console.log(`All good - ${data.id}`);
return res.status(200).json(data);
});
This is the output I get on the console:
An error occurred - Expired Auth: Auth code or refresh token has expired.
The client that is receiveing the response from res.status(500).send(err)
receives this (certain bits omitted here for brevity):
{
"statusCode":400,
"response":{
"statusCode":400,
"body":{
"error":"invalid_grant",
"error_description":"Current date/time MUST be before the expiration date/time listed in the 'exp' claim"
},
"headers": ...,
"request":{
"uri":{
...
"href":"https://api.box.com/oauth2/token"
},
"method":"POST",
"headers": ...
}
},
"authExpired":true
}
To start with, it appeared that restarting node stopped the error occurring for a while. But now it's occurring all the time.
I would like to request a feature (or to ask for input on whether a pull request for this feature would be likely to be accepted). The feature would be this: when a token request fails with the error "Current date/time MUST be before the expiration date/time listed in the 'exp' claim
", then the SDK would take the "Date" header form the response, and generate a new exp
claim using the Date header's value as the current timestamp, in an effort to generate an exp
claim that is correct relative to the Box server's timestamp.
This is in an attempt to avoid the problem discussed in #109 when the clocks are not synchronised between the client machine and Box's server.
One downside of this is that the error keyword (invalid_grant
) is not specific to the exp
claim. So either the SDK would have to do this for all invalid_grant
errors (or at least it would check for mismatched timestamps whenever it receives an invalid_grant
error & only retry if it finds they're out of sync), or it would have to inspect the error_description
, which is probably not a reliable thing to do.
(There are alternative approaches that could be taken to address that problem, such as moving the generation of the exp
claim entirely onto Box's server, but that would be a more fundamental change in the API.)
Is this something that would make sense in this project, or would it be out of place?
Recently began receiving the error below - the issue ended up being an incorrect keyID
, privateKey
and passPhrase
. Should this error be more specific?
Stack trace:
Trace: { Error: Expired Auth: Auth code or refresh token has expired. at Object.buildResponseError (/usr/src/app/node_modules/box-node-sdk/lib/util/errors.js:57:23) at Object.buildExpiredAuthError (/usr/src/app/node_modules/box-node-sdk/lib/util/errors.js:70:28) at /usr/src/app/node_modules/box-node-sdk/lib/token-manager.js:213:21 at /usr/src/app/node_modules/box-node-sdk/lib/api-request.js:285:3 at opbeatCallbackWrapper (/usr/src/app/node_modules/opbeat/lib/instrumentation/index.js:102:27) at wrapped (/usr/src/app/node_modules/newrelic/lib/transaction/tracer/index.js:182:28) at _combinedTickCallback (internal/process/next_tick.js:67:7) {"pid":27,"hostname":"gt9j5","name":"logger","level":20,"msg":"Errors","type":"Error","stack":"Error: Expired Auth: Auth code or refresh token has expired.\n at Object.buildResponseError (/usr/src/app/node_modules/box-node-sdk/lib/util/errors.js:57:23)\n at Object.buildExpiredAuthError (/usr/src/app/node_modules/box-node-sdk/lib/util/errors.js:70:28)\n at /usr/src/app/node_modules/box-node-sdk/lib/token-manager.js:213:21\n at /usr/src/app/node_modules/box-node-sdk/lib/api-request.js:285:3\n at opbeatCallbackWrapper (/usr/src/app/node_modules/opbeat/lib/instrumentation/index.js:102:27)\n at wrapped (/usr/src/app/node_modules/newrelic/lib/transaction/tracer/index.js:182:28)\n at _combinedTickCallback (internal/process/next_tick.js:67:7)\n at process._tickCallback (internal/process/next_tick.js:98:9)","statusCode":400,"response":{"statusCode":400,"body":{"error":"invalid_grant","error_description":"OpenSSL unable to verify data: "},"headers":{"server":"ATS","date":"Mon, 07 Aug 2017 23:06:48 GMT","content-type":"application/json","content-length":"79","cache-control":"no-store","strict-transport-security":"max-age=31536000; includeSubDomains","vary":"Accept-Encoding","set-cookie":["box_visitor_id=5988f2888d3120.32446958; expires=Tue, 07-Aug-2018 23:06:48 GMT; Max-Age=31536000; path=/; domain=.box.com; secure","bv=OPS-41911; expires=Mon, 14-Aug-2017 23:06:48 GMT; Max-Age=604800; path=/; domain=.app.box.com; secure","cn=74; expires=Tue, 07-Aug-2018 23:06:48 GMT; Max-Age=31536000; path=/; domain=.app.box.com; secure","site_preference=desktop; path=/; domain=.box.com; secure"],"age":"0","connection":"keep-alive"},"request":{"uri":{"protocol":"https:","slashes":true,"auth":null,"host":"api.box.com","port":443,"hostname":"api.box.com","hash":null,"search":null,"query":null,"pathname":"/oauth2/token","path":"/oauth2/token","href":"https://api.box.com/oauth2/token"},"method":"POST","headers":{"User-Agent":"Box Node.js SDK v1.7.0","content-type":"application/x-www-form-urlencoded","accept":"application/json","content-length":860}}},"authExpired":true,"v":1}
Does this have As-User support? I can't seem to get it working using appAuth and setting the current user ID. I am getting a 403 Unauthorised error when getting the root folder for a user.
let sdk = new BoxSDK({
clientID: box.clientId,
clientSecret: box.clientSecret,
appAuth: {
keyID: box.publicKeyId,
privateKey: box.RSAPrivate,
passphrase: 000
}
});
let adminAPIClient = sdk.getAppAuthClient('enterprise', box.enterpriseUserId);
adminAPIClient.CURRENT_USER_ID = '283606869';
adminAPIClient.folders.get('0', null, (err, users) => {
logger.debug(users);
logger.error(err);
});
I have a feeling it's due to our private key not having a passphrase. As looking at line 111 in lib/util/config.js a passphrase is required.
Will groups and memberships be added at some point?
Also, is there a reason that you guys use polling over websockets for the real-time events? Slightly off-topic but intrigued to know.
Error when initializing sdk
var sdk = new BoxSDK({
clientID: config.CLIENT_ID,
clientSecret: config.CLIENT_SECRET
});
i have been using java sdk now migrating to node and facing this issue
any help is appreciated
I'd like to see support for customizing the names of items during a Copy process. The Box API allows for specifying the new item name as an optional parameter in the request (see below), but this is not currently supported in the SDK. Can an optional parameter be added to the Folder Copy and File Copy functions to support this?
Folder Copy: https://docs.box.com/reference#copy-a-folder
File Copy: https://docs.box.com/reference#copy-a-file
Thanks!
Hi there,
My application ocassionally gets this error when calling methods on the box client object that is returned when calling sdk.getAppAuthClient('user', myAppUserId);
. Is this because I need to create a persistent client? How would I create a persistent app auth client?
This error is intermittent and resolves itself in a seemingly arbitrary amount of time. But it would be more ideal to prevent this error - because until the error is resolved my application is unable to use any of the box client methods.
Hi,
Is there a limit on a number of times getTokensRefreshGrant
can be called per hour/day/etc.? We have a Grunt task that pulls files from Box, and it runs multiple times a day. Wondering if it'll ever fail due to the API refusing to provide a fresh set of tokens due to a previous request having come in too recently.
Hello,
Using getAppAuthClient
I'm having an issue with tokens using this SDK. I'm getting some 400s back after successive calls to box with the error body
{ error: 'invalid_grant',
error_description: 'Please check the \'jti\' claim.' },
Having read previous issues I thought this would be due to my computers clock being out of sync but using https://time.is/ I see my clock is accurately sync to some minute amount. To further investigate I console logged the jti claim. Here it is
{ exp: 1496157257, box_sub_type: 'user' }
Here is the response:
res { statusCode: 400,
body:
{ error: 'invalid_grant',
error_description: 'Please check the \'jti\' claim.' },
headers:
{ server: 'ATS',
date: 'Tue, 30 May 2017 15:13:20 GMT',
'content-type': 'application/json',
'content-length': '77',
'cache-control': 'no-store',
'strict-transport-security': 'max-age=31536000; includeSubDomains',
vary: 'Accept-Encoding',
'set-cookie':
[ 'box_visitor_id=592d8c0fed6377.84891543; expires=Wed, 30-May-2018 15:13:19 GMT; Max-Age=31536000; path=/; domain=.box.com; secure',
'bv=OPS-41777; expires=Tue, 06-Jun-2017 15:13:19 GMT; Max-Age=604800; path=/; domain=.app.box.com; secure',
'cn=28; expires=Wed, 30-May-2018 15:13:19 GMT; Max-Age=31536000; path=/; domain=.app.box.com; secure',
'site_preference=desktop; path=/; domain=.box.com; secure' ],
age: '2',
connection: 'keep-alive' },
request:
{ uri:
Url {
protocol: 'https:',
slashes: true,
auth: null,
host: 'api.box.com',
port: 443,
hostname: 'api.box.com',
hash: null,
search: null,
query: null,
pathname: '/oauth2/token',
path: '/oauth2/token',
href: 'https://api.box.com/oauth2/token' },
method: 'POST',
headers:
{ 'User-Agent': 'Box Node.js SDK v1.4.2',
'content-type': 'application/x-www-form-urlencoded',
accept: 'application/json',
'content-length': 816 } } }
Comparing the exp claim to to the header date in the response I see that there is a difference of 56 seconds which is below 60, the maximum so I'm confused as to what the issue is.
Any ideas?
Cheers,
G
The Object.freeze
call here only makes the top level properties immutable. The nested properties under request
(for example request.strictSSL
) are still mutable.
I'm not sure if this is intentional or not. If not, perhaps consider using the deep-freeze library or the deepFreeze example listed on the MDN website.
Here's an example test that fails to throw
var config = new Config({
clientID: 'id',
clientSecret: 'secret',
});
assert.throws(function() {
config.request.strictSSL = false;
});
So far as I can tell, when using client.files.uploadFile()
there's no way to tell the box client the size of the file you're trying to upload. This causes uploads to fail if you're using a stream that is not one of the following:
fs.ReadStream
http.IncomingMessage
request
stream(I also suspect that if either of the IncomingMessage
or request
streams have the header transfer-encoding: chunked
then uploads will similarly fail since such responses will not (should not) have the content-length
header defined, but I have not verified this.)
In particular to my case, without some additional finagling a file stream created by Busboy will not upload correctly when handed off to client.files.uploadFile()
because it is a plain Readable
, not one of the above three acceptable kinds.
For my case, passing an upload from Busboy to Box, I can (should?) probably use the chunked file uploader, but it is still surprising. (That seems to have been either a recent addition or is just not shown in the JSDoc site and I missed it initially.)
I can also understand not wanting to support uploads of unknown length using transfer-encoding: chunked
, but I didn't see any comments about that in the readme or other documentation. (I don't know if such comments truly don't exist anywhere in any Box API docs, but I don't recall seeing any.) (there is also the issue of request
currently not having any logic to handle sending with transfer-encoding: chunked
...)
I see there is an old PR that would have added another Files method Files.uploadFileWithOptions
which itself would have allowed the user to specify the expected size of the file stream, but it was never reviewed and is based on an old version anyway.
I was implementing this sdk with the previous release (1.3.x) and verified that files.uploadFile was working.
However the master branch has introduced Promises which is great so I changed my code for such but now I seem to be having issues with the files.uploadFile. Getting a 400 error with not much more context. Is this not yet ready for use?
Here is an example of the invocation:
_uploadFile (fileName) {
const absolutePath = Path.resolve(`./${fileName}`);
let fileStream = Fs.createReadStream(absolutePath);
return this._boxClient.files.uploadFile(this._folderId, fileName, fileStream)
.then((data) => {
return data
})
.catch((err) => {
console.log(err.response.toJSON());
console.log('There was a problem dude why is there a problem dude?');
return err;
})
}
Here is the response
{
statusCode: 400,
body: undefined,
headers: {
date: 'Fri, 12 May 2017 22:30:03 GMT',
'content-type': 'text/html; charset=UTF-8',
'content-length': '0',
age: '0',
server: 'ATS',
connection: 'keep-alive'
},
request: {
uri: Url {
protocol: 'https:',
slashes: true,
auth: null,
host: 'upload.box.com',
port: 443,
hostname: 'upload.box.com',
hash: null,
search: null,
query: null,
pathname: '/api/2.0/files/content',
path: '/api/2.0/files/content',
href: 'https://upload.box.com/api/2.0/files/content'
},
method: 'POST',
headers: {
'User-Agent': 'Box Node.js SDK v1.3.0',
Authorization: '[REMOVED BY SDK]',
accept: 'application/json',
'content-type': 'multipart/form-data; boundary=--------------------------043694317197156763656264',
'content-length': 0
}
}
}
I've been at this for a while now which leads me to believe there is something I'm missing
Hello together,
i am trying to do an Integration of Box into the collaboration platform IBM Connections. I am using your SDK and i am trying to authenticate on my created app, to show the content of a folder.
So i am using the following code:
sdk = new BoxSDK({
clientID: CLIENT_ID,
clientSecret: CLIENT_SECRET,
appAuth: {
keyID: PUBLIC_KEY_ID,
privateKey: PRIVATE_KEY,
passphrase: PASSPHRASE
}
});
var adminAPIClient = sdk.getAppAuthClient('enterprise', ENTERPRISE_ID);
First Question on that: my PRIVATE_KEY const is declared with the following code:
const PRIVATE_KEY = fs.readFileSync('private_key.pem');
Is that correct? I miss a part in the documentation where the variables are explained...
If you would explain it to me, i would check it in...
Now i try to get all users from my App and if there is no user, i try to create an app user (because i will need the app user to get the content of the root folder, right?):
function getUsers() {
var userCreated = false;
adminAPIClient.enterprise.getUsers(null, function(response) {
console.log("Enterprise getUsers: " + response); // return is null...
if (!response && !userCreated) {
console.log("No User found --> create AppUser");
userCreated = true;
adminAPIClient.enterprise.addAppUser('XCC AppUser',{
job_title: 'Showing Files',
},
function done (data) {
console.log("User created - Now trying to get the Users!");
console.log("Return of addAppUser: " + data);
getUsers();
}
);
}
});
}
Nodejs is throwing an error: adminAPIClient.enterprise.addAppUser is not a function
i was looking at the following documentation:
https://github.com/box/box-node-sdk/blob/master/docs/enterprise.md
So what am i doing wrong and can you get me into the right direction?
That would be great, thanks!
getAllFileVersionRetentions is unable to determine paging strategy:
Unable to determine paging strategy for response!
at new PagingIterator (/Developer/Code/box-governance-center/server/node_modules/box-node-sdk/lib/util/paging-iterator.js:84:10)
at ret.then.response (/Developer/Code/box-governance-center/server/node_modules/box-node-sdk/lib/box-client.js:654:14)
at tryCatcher (/Developer/Code/box-governance-center/server/node_modules/bluebird/js/release/util.js:16:23)
at Promise._settlePromiseFromHandler (/Developer/Code/box-governance-center/server/node_modules/bluebird/js/release/promise.js:512:31)
at Promise._settlePromise (/Developer/Code/box-governance-center/server/node_modules/bluebird/js/release/promise.js:569:18)
at Promise._settlePromise0 (/Developer/Code/box-governance-center/server/node_modules/bluebird/js/release/promise.js:614:10)
at Promise._settlePromises (/Developer/Code/box-governance-center/server/node_modules/bluebird/js/release/promise.js:693:18)
at Promise._fulfill (/Developer/Code/box-governance-center/server/node_modules/bluebird/js/release/promise.js:638:18)
at Promise._settlePromise (/Developer/Code/box-governance-center/server/node_modules/bluebird/js/release/promise.js:582:21)
at Promise._settlePromise0 (/Developer/Code/box-governance-center/server/node_modules/bluebird/js/release/promise.js:614:10)
at Promise._settlePromises (/Developer/Code/box-governance-center/server/node_modules/bluebird/js/release/promise.js:693:18)
at Promise._fulfill (/Developer/Code/box-governance-center/server/node_modules/bluebird/js/release/promise.js:638:18)
at /Developer/Code/box-governance-center/server/node_modules/bluebird/js/release/nodeback.js:42:21
at BoxClient._handleResponse (/Developer/Code/box-governance-center/server/node_modules/box-node-sdk/lib/box-client.js:308:2)
at handleResponseCallback (/Developer/Code/box-governance-center/server/node_modules/box-node-sdk/lib/box-client.js:241:10)
at /Developer/Code/box-governance-center/server/node_modules/box-node-sdk/lib/api-request.js:285:3
I've been trying to build a server which uses Box Content to support file uploads, and I'm handling multipart/form-data
requests using busboy
, but when I hand off the file stream created by busboy
to boxClient.files.uploadFile(...)
, the latter errors out with a 500 status code.
As another data point, when I test it using a file read through fs.createReadStream
it works fine. However, if I pipe that stream through a PassThrough (fs.createReadStream(...).pipe(new PassThrough())
) then it displays the above error behavior. Creating a Readable stream which merely reads out the contents of a Buffer also fails similarly.
As an aside, I looked at api-rquest.js
and saw this project is using request
, which has given me erroneous behavior like above when trying to post files using streams other than those created by fs.createReadStream
, and also erroring out when piping fs.createReadStream
through a PassThrough
. Using a different library such as got
did not have this issue in my testing.
Currently, I am getting around this by buffering files to disk, but doing even this in an efficient manner is impossible as I have to write the entire file to disk so that I can use fs.createReadStream
to pass it off to the sdk.
I'm working on a monkeypatch of api-request.js
as a quick test case to see if replacing request
resolves this stream issue. Hopefully I will be able to report back on that soon.
Edit: As an update, I'm going to note that efforts to make other libraries work across corporate proxies is making me consider strategies other than replacing request
. There're reasons request
is so widely used, and some amount of proxy support seems to be one of them.
I get the following error when I try and use the example app:
An error occurred during login - Unexpected API Response [400 Bad Request]
It gives me no information further than that.
I've added all the app credentials in the examples/app-auth/index.js
file.
In token-manager.js, the exchangeToken manager does work with multiple scopes.
The reason is because of this line of code:
scope: (typeof scopes === 'string' ? scopes : scopes.join(','))
Needs to be changed to:
scope: (typeof scopes === 'string' ? scopes : scopes.join(' '))
scope parameter needs to be in space separated rather than comma separated for exchange.
I have written a fix. I am about to push fix from my forked SDK.
Promise support was added to all the BoxClients which is absolutely awesome, but it looks like some methods were missed on the BoxSDK object itself, they still require callbacks:
Would you consider adding Promise support to these methods too?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.