Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 9589be1

Browse files
Merge pull request #301 from mjsalinger/252-Allow-optional-properties-in-token-response
252-Allow optional properties in token response by setting 'allowExtended...
2 parents 237646e + b1ebe17 commit 9589be1

File tree

6 files changed

+99
-37
lines changed

6 files changed

+99
-37
lines changed

‎lib/handlers/token-handler.js‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ function TokenHandler(options) {
5959
this.grantTypes = _.assign({}, grantTypes, options.extendedGrantTypes);
6060
this.model = options.model;
6161
this.refreshTokenLifetime = options.refreshTokenLifetime;
62+
this.allowExtendedTokenAttributes = options.allowExtendedTokenAttributes;
6263
}
6364

6465
/**
@@ -90,7 +91,7 @@ TokenHandler.prototype.handle = function(request, response) {
9091
return this.handleGrantType(request, client);
9192
})
9293
.tap(function(data) {
93-
var model = new TokenModel(data);
94+
var model = new TokenModel(data,{allowExtendedTokenAttributes: this.allowExtendedTokenAttributes});
9495
var tokenType = this.getTokenType(model);
9596

9697
this.updateSuccessResponse(response, tokenType);
@@ -240,7 +241,7 @@ TokenHandler.prototype.getRefreshTokenLifetime = function(client) {
240241
*/
241242

242243
TokenHandler.prototype.getTokenType = function(model) {
243-
return new BearerTokenType(model.accessToken, model.accessTokenLifetime, model.refreshToken, model.scope);
244+
return new BearerTokenType(model.accessToken, model.accessTokenLifetime, model.refreshToken, model.scope,model.customAttributes);
244245
};
245246

246247
/**

‎lib/models/token-model.js‎

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@ var InvalidArgumentError = require('../errors/invalid-argument-error');
1010
* Constructor.
1111
*/
1212

13-
function TokenModel(data) {
13+
var modelAttributes = ['accessToken', 'accessTokenExpiresAt', 'refreshToken', 'refreshTokenExpiresAt', 'scope', 'client', 'user'];
14+
15+
function TokenModel(data, options) {
1416
data = data || {};
1517

1618
if (!data.accessToken) {
@@ -41,6 +43,16 @@ function TokenModel(data) {
4143
this.scope = data.scope;
4244
this.user = data.user;
4345

46+
if (options && options.allowExtendedTokenAttributes) {
47+
this.customAttributes = {};
48+
49+
for (var key in data) {
50+
if (data.hasOwnProperty(key) && (modelAttributes.indexOf(key) < 0)) {
51+
this.customAttributes[key] = data[key];
52+
}
53+
}
54+
}
55+
4456
if(this.accessTokenExpiresAt) {
4557
this.accessTokenLifetime = Math.floor((this.accessTokenExpiresAt - new Date()) / 1000);
4658
}

‎lib/server.js‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,8 @@ OAuth2Server.prototype.authorize = function(request, response, options, callback
6262
OAuth2Server.prototype.token = function(request, response, options, callback) {
6363
options = _.assign({
6464
accessTokenLifetime: 60 * 60, // 1 hour.
65-
refreshTokenLifetime: 60 * 60 * 24 * 14 // 2 weeks.
65+
refreshTokenLifetime: 60 * 60 * 24 * 14, // 2 weeks.
66+
allowExtendedTokenAttributes: false
6667
}, this.options, options);
6768

6869
return new TokenHandler(options)

‎lib/token-types/bearer-token-type.js‎

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ var InvalidArgumentError = require('../errors/invalid-argument-error');
1010
* Constructor.
1111
*/
1212

13-
function BearerTokenType(accessToken, accessTokenLifetime, refreshToken, scope) {
13+
function BearerTokenType(accessToken, accessTokenLifetime, refreshToken, scope,customAttributes) {
1414
if (!accessToken) {
1515
throw new InvalidArgumentError('Missing parameter: `accessToken`');
1616
}
@@ -19,6 +19,10 @@ function BearerTokenType(accessToken, accessTokenLifetime, refreshToken, scope)
1919
this.accessTokenLifetime = accessTokenLifetime;
2020
this.refreshToken = refreshToken;
2121
this.scope = scope;
22+
23+
if (customAttributes) {
24+
this.customAttributes = customAttributes;
25+
}
2226
}
2327

2428
/**
@@ -43,6 +47,11 @@ BearerTokenType.prototype.valueOf = function() {
4347
object.scope = this.scope;
4448
}
4549

50+
for (var key in this.customAttributes) {
51+
if (this.customAttributes.hasOwnProperty(key)) {
52+
object[key] = this.customAttributes[key];
53+
}
54+
}
4655
return object;
4756
};
4857

‎test/integration/grant-types/refresh-token-grant-type_test.js‎

Lines changed: 0 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -449,38 +449,6 @@ describe('RefreshTokenGrantType integration', function() {
449449
});
450450
});
451451

452-
it('should throw an error if the `token.refreshTokenExpiresAt` is invalid', function() {
453-
var model = {
454-
getRefreshToken: function() {},
455-
revokeToken: function() { return { refreshTokenExpiresAt: [] }; },
456-
saveToken: function() {}
457-
};
458-
var grantType = new RefreshTokenGrantType({ accessTokenLifetime: 120, model: model });
459-
460-
grantType.revokeToken({})
461-
.then(should.fail)
462-
.catch(function (e) {
463-
e.should.be.an.instanceOf(ServerError);
464-
e.message.should.equal('Server error: `refreshTokenExpiresAt` must be a Date instance');
465-
});
466-
});
467-
468-
it('should throw an error if the `token.refreshTokenExpiresAt` is not expired', function() {
469-
var model = {
470-
getRefreshToken: function() {},
471-
revokeToken: function() { return { refreshTokenExpiresAt: new Date(new Date() * 2) }; },
472-
saveToken: function() {}
473-
};
474-
var grantType = new RefreshTokenGrantType({ accessTokenLifetime: 120, model: model });
475-
476-
grantType.revokeToken({})
477-
.then(should.fail)
478-
.catch(function (e) {
479-
e.should.be.an.instanceOf(ServerError);
480-
e.message.should.equal('Server error: refresh token should be expired');
481-
});
482-
});
483-
484452
it('should revoke the token', function() {
485453
var token = { accessToken: 'foo', client: {}, refreshTokenExpiresAt: new Date(new Date() / 2), user: {} };
486454
var model = {

‎test/integration/handlers/token-handler_test.js‎

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,8 +295,79 @@ describe('TokenHandler integration', function() {
295295
})
296296
.catch(should.fail);
297297
});
298+
299+
it('should not return custom attributes in a bearer token if the allowExtendedTokenAttributes is not set', function() {
300+
var token = { accessToken: 'foo', client: {}, refreshToken: 'bar', scope: 'foobar', user: {}, foo: 'bar' };
301+
var model = {
302+
getClient: function() { return { grants: ['password'] }; },
303+
getUser: function() { return {}; },
304+
saveToken: function() { return token; },
305+
validateScope: function() { return 'baz'; }
306+
};
307+
var handler = new TokenHandler({ accessTokenLifetime: 120, model: model, refreshTokenLifetime: 120 });
308+
var request = new Request({
309+
body: {
310+
client_id: 12345,
311+
client_secret: 'secret',
312+
username: 'foo',
313+
password: 'bar',
314+
grant_type: 'password',
315+
scope: 'baz'
316+
},
317+
headers: { 'content-type': 'application/x-www-form-urlencoded', 'transfer-encoding': 'chunked' },
318+
method: 'POST',
319+
query: {}
320+
});
321+
var response = new Response({ body: {}, headers: {} });
322+
323+
return handler.handle(request, response)
324+
.then(function() {
325+
should.exist(response.body.access_token);
326+
should.exist(response.body.refresh_token);
327+
should.exist(response.body.token_type);
328+
should.exist(response.body.scope);
329+
should.not.exist(response.body.foo);
330+
})
331+
.catch(should.fail);
332+
});
333+
334+
it('should return custom attributes in a bearer token if the allowExtendedTokenAttributes is set', function() {
335+
var token = { accessToken: 'foo', client: {}, refreshToken: 'bar', scope: 'foobar', user: {}, foo: 'bar' };
336+
var model = {
337+
getClient: function() { return { grants: ['password'] }; },
338+
getUser: function() { return {}; },
339+
saveToken: function() { return token; },
340+
validateScope: function() { return 'baz'; }
341+
};
342+
var handler = new TokenHandler({ accessTokenLifetime: 120, model: model, refreshTokenLifetime: 120, allowExtendedTokenAttributes: true });
343+
var request = new Request({
344+
body: {
345+
client_id: 12345,
346+
client_secret: 'secret',
347+
username: 'foo',
348+
password: 'bar',
349+
grant_type: 'password',
350+
scope: 'baz'
351+
},
352+
headers: { 'content-type': 'application/x-www-form-urlencoded', 'transfer-encoding': 'chunked' },
353+
method: 'POST',
354+
query: {}
355+
});
356+
var response = new Response({ body: {}, headers: {} });
357+
358+
return handler.handle(request, response)
359+
.then(function() {
360+
should.exist(response.body.access_token);
361+
should.exist(response.body.refresh_token);
362+
should.exist(response.body.token_type);
363+
should.exist(response.body.scope);
364+
should.exist(response.body.foo);
365+
})
366+
.catch(should.fail);
367+
});
298368
});
299369

370+
300371
describe('getClient()', function() {
301372
it('should throw an error if `clientId` is invalid', function() {
302373
var model = {

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /