Skip to content

Commit 76aa1cf

Browse files
naeimsCary Cheng
authored andcommitted
Add support for token exchange using shared links (#398)
1 parent 811fa4e commit 76aa1cf

File tree

4 files changed

+64
-1
lines changed

4 files changed

+64
-1
lines changed

lib/box-client.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -492,6 +492,7 @@ BoxClient.prototype.revokeTokens = function(callback) {
492492
* @param {string} [resource] The absolute URL of an API resource to scope the new token to
493493
* @param {Object} [options] - Optional parameters
494494
* @param {ActorParams} [options.actor] - Optional actor parameters for creating annotator tokens with Token Auth client
495+
* @param {SharedLinkParams} [options.sharedLink] - Optional shared link parameters for creating tokens using shared links
495496
* @param {Function} [callback] Called with the new token
496497
* @returns {Promise<TokenInfo>} A promise resolving to the exchanged token info
497498
*/

lib/token-manager.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,12 @@
1818
* server requesting the tokens.
1919
*/
2020

21+
/**
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+
2127
/**
2228
* Parameters for creating an actor token via token exchange
2329
* @typedef {Object} ActorParams
@@ -382,6 +388,7 @@ TokenManager.prototype = {
382388
* @param {Object} [options] - Optional parameters
383389
* @param {TokenRequestOptions} [options.tokenRequestOptions] - Sets optional behavior for the token grant
384390
* @param {ActorParams} [options.actor] - Optional actor parameters for creating annotator tokens
391+
* @param {SharedLinkParams} [options.sharedLink] - Optional shared link parameters for creating tokens using shared links
385392
* @returns {Promise<TokenInfo>} Promise resolving to the new token info
386393
*/
387394
exchangeToken(accessToken, scopes, resource, options) {
@@ -396,6 +403,10 @@ TokenManager.prototype = {
396403
params.resource = resource;
397404
}
398405

406+
if (options && options.sharedLink) {
407+
params.box_shared_link = options.sharedLink.url;
408+
}
409+
399410
if (options && options.actor) {
400411

401412
var payload = {

tests/lib/box-client-test.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1149,6 +1149,29 @@ describe('box-client', function() {
11491149
});
11501150
});
11511151

1152+
it('should call session to exchange token with shared link params when shared link params are passed', function() {
1153+
1154+
var sharedLink = {
1155+
url: 'https://app.box.com/s/xyz'
1156+
};
1157+
1158+
var expectedOptions = {
1159+
sharedLink,
1160+
tokenRequestOptions: null
1161+
};
1162+
1163+
var exchangedTokenInfo = {accessToken: 'qqwjnfldkjfhksedrg'};
1164+
1165+
sandbox.mock(apiSessionFake).expects('exchangeToken')
1166+
.withArgs(TEST_SCOPE, TEST_RESOURCE, expectedOptions)
1167+
.returns(Promise.resolve(exchangedTokenInfo));
1168+
1169+
return basicClient.exchangeToken(TEST_SCOPE, TEST_RESOURCE, { sharedLink })
1170+
.then(data => {
1171+
assert.equal(data, exchangedTokenInfo);
1172+
});
1173+
});
1174+
11521175
it('should call callback with error when token exchange fails', function(done) {
11531176

11541177
var error = new Error('Failure');

tests/lib/token-manager-test.js

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -652,7 +652,8 @@ describe('token-manager', function() {
652652
var TEST_ACCESS_TOKEN = 'poiudafjdbfjygsdfg',
653653
TEST_SCOPE = 'item_preview',
654654
TEST_JTI = '630aab1e-912e-468d-b052-fd53a41925ed',
655-
TEST_RESOURCE = 'https://api.box.com/2.0/files/12345';
655+
TEST_RESOURCE = 'https://api.box.com/2.0/files/12345',
656+
TEST_SHARED_LINK_URL = 'https://app.box.com/s/xyz';
656657

657658
it('should exchange access token for lower scope when only scope is passed', function() {
658659

@@ -850,6 +851,33 @@ describe('token-manager', function() {
850851
assert.equal(err, jwtError);
851852
});
852853
});
854+
855+
it('should exchange token when shared link params are passed', function() {
856+
var sharedLink = {
857+
url: TEST_SHARED_LINK_URL
858+
};
859+
860+
var expectedTokenParams = {
861+
grant_type: 'urn:ietf:params:oauth:grant-type:token-exchange',
862+
subject_token_type: 'urn:ietf:params:oauth:token-type:access_token',
863+
subject_token: TEST_ACCESS_TOKEN,
864+
scope: TEST_SCOPE,
865+
box_shared_link: TEST_SHARED_LINK_URL
866+
};
867+
868+
var tokenInfo = {
869+
accessToken: 'lsdjhgo87w3h4tbd87fg54'
870+
};
871+
872+
sandbox.mock(tokenManager).expects('getTokens')
873+
.withArgs(expectedTokenParams, null)
874+
.returns(Promise.resolve(tokenInfo));
875+
876+
return tokenManager.exchangeToken(TEST_ACCESS_TOKEN, TEST_SCOPE, null, { sharedLink })
877+
.then(tokens => {
878+
assert.equal(tokens, tokenInfo);
879+
});
880+
});
853881
});
854882

855883
describe('revokeTokens()', function() {

0 commit comments

Comments
 (0)