Skip to content

Commit

Permalink
Merge pull request #2 from mjsalinger/98-Client-Specific-Timeouts
Browse files Browse the repository at this point in the history
98 client specific timeouts
  • Loading branch information
mjsalinger committed May 24, 2016
2 parents 617de8d + 8b4f7b1 commit f8851c1
Show file tree
Hide file tree
Showing 4 changed files with 126 additions and 15 deletions.
7 changes: 6 additions & 1 deletion lib/authCodeGrant.js
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ function checkClient (done) {
return done(error('invalid_request', 'redirect_uri does not match'));
}
client.redirectUri = self.redirectUri;

} else if (client.redirectUri !== self.redirectUri) {
return done(error('invalid_request', 'redirect_uri does not match'));
}
Expand Down Expand Up @@ -172,7 +173,11 @@ function generateCode (done) {
*/
function saveAuthCode (done) {
var expires = new Date();
expires.setSeconds(expires.getSeconds() + this.config.authCodeLifetime);

var ttl = !isNaN(parseFloat(this.client.authCodeLifetime)) && isFinite(this.client.authCodeLifetime) ?
this.client.authCodeLifetime : this.config.authCodeLifetime;

expires.setSeconds(expires.getSeconds() + ttl);

this.model.saveAuthCode(this.authCode, this.client.clientId, expires,
this.user, function (err) {
Expand Down
36 changes: 23 additions & 13 deletions lib/grant.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,20 @@ function Grant (config, req, res, next) {
runner(fns, this, next);
}

Grant.prototype.setExpires = function (key) {

var expires = null;

this.ttl = !isNaN(parseFloat(this.client[key])) && isFinite(this.client[key]) ? this.client[key]: this.config[key];

if (this.ttl !== null) {
expires = new Date(this.now);
expires.setSeconds(expires.getSeconds() + this.ttl);
}

return expires;
};

/**
* Basic request validation and extraction of grant_type and client creds
*
Expand Down Expand Up @@ -132,14 +146,18 @@ function credsFromBody (req) {
* @this OAuth
*/
function checkClient (done) {
this.model.getClient(this.client.clientId, this.client.clientSecret,
var self = this;
self.model.getClient(self.client.clientId, self.client.clientSecret,
function (err, client) {
if (err) return done(error('server_error', false, err));

if (!client) {
return done(error('invalid_client', 'Client credentials are invalid'));
}

self.client.accessTokenLifetime = client.accessTokenLifetime;
self.client.refreshTokenLifetime = client.refreshTokenLifetime;

done();
});
}
Expand Down Expand Up @@ -389,11 +407,7 @@ function saveAccessToken (done) {
return done();
}

var expires = null;
if (this.config.accessTokenLifetime !== null) {
expires = new Date(this.now);
expires.setSeconds(expires.getSeconds() + this.config.accessTokenLifetime);
}
var expires = this.setExpires("accessTokenLifetime");

this.model.saveAccessToken(accessToken, this.client.clientId, expires,
this.user, function (err) {
Expand Down Expand Up @@ -435,11 +449,7 @@ function saveRefreshToken (done) {
return done();
}

var expires = null;
if (this.config.refreshTokenLifetime !== null) {
expires = new Date(this.now);
expires.setSeconds(expires.getSeconds() + this.config.refreshTokenLifetime);
}
var expires = this.setExpires("refreshTokenLifetime");

this.model.saveRefreshToken(refreshToken, this.client.clientId, expires,
this.user, function (err) {
Expand All @@ -460,8 +470,8 @@ function sendResponse (done) {
access_token: this.accessToken
};

if (this.config.accessTokenLifetime !== null) {
response.expires_in = this.config.accessTokenLifetime;
if (this.config.accessTokenLifetime !== null || this.ttl !== null) {
response.expires_in = this.ttl || this.config.accessTokenLifetime;
}

if (this.refreshToken) response.refresh_token = this.refreshToken;
Expand Down
28 changes: 28 additions & 0 deletions test/authCodeGrant.js
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,34 @@ describe('AuthCodeGrant', function() {
.end();
});

it('should try to save auth code with a client-specific timeout', function (done) {
var app = bootstrap({
getClient: function (clientId, clientSecret, callback) {
callback(false, {
clientId: 'thom',
redirectUri: 'http://nightworld.com',
authCodeLifetime: 3600
});
},
saveAuthCode: function (authCode, clientId, expires, user, callback) {
should.exist(authCode);
authCode.should.have.lengthOf(40);
clientId.should.equal('thom');
(+expires).should.be.approximately((+new Date()) + (3600 * 1000), 100);
done();
}
}, [false, true]);

request(app)
.post('/authorise')
.send({
response_type: 'code',
client_id: 'thom',
redirect_uri: 'http://nightworld.com'
})
.end();
});

it('should accept valid request and return code using POST', function (done) {
var code;

Expand Down
70 changes: 69 additions & 1 deletion test/grant.js
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,74 @@ describe('Grant', function() {
.expect(200, done);

});

it('should pass a client-specific token expiration to model.saveAccessToken', function (done) {
var app = bootstrap({
model: {
getClient: function (id, secret, callback) {
callback(false, { client_id: 'thom', accessTokenLifetime: 86400 });
},
grantTypeAllowed: function (clientId, grantType, callback) {
callback(false, true);
},
getUser: function (uname, pword, callback) {
callback(false, { id: 1 });
},
saveAccessToken: function (token, clientId, expires, user, cb) {
token.should.be.instanceOf(String);
token.should.have.length(40);
clientId.should.equal('thom');
user.id.should.equal(1);
(+expires).should.be.approximately((+new Date()) + 86400000, 100);
cb();
}
},
grants: ['password']
});

request(app)
.post('/oauth/token')
.set('Content-Type', 'application/x-www-form-urlencoded')
.send(validBody)
.expect(200, done);

});

it('should pass a client-specific refresh token expiration to model.saveRefreshToken', function (done) {
var app = bootstrap({
model: {
getClient: function (id, secret, callback) {
callback(false, { client_id: 'thom', refreshTokenLifetime: 129600 });
},
grantTypeAllowed: function (clientId, grantType, callback) {
callback(false, true);
},
getUser: function (uname, pword, callback) {
callback(false, { id: 1 });
},
saveAccessToken: function (token, clientId, expires, user, cb) {
cb();
},
saveRefreshToken: function (token, clientId, expires, user, cb) {
token.should.be.instanceOf(String);
token.should.have.length(40);
clientId.should.equal('thom');
user.id.should.equal(1);
(+expires).should.be.within(10, (+new Date()) + 129600000);
cb();
}
},
grants: ['password', 'refresh_token']
});

request(app)
.post('/oauth/token')
.set('Content-Type', 'application/x-www-form-urlencoded')
.send(validBody)
.expect(200, done);

});

});

describe('issue access token', function () {
Expand Down Expand Up @@ -462,7 +530,7 @@ describe('Grant', function() {
res.body.refresh_token.should.be.instanceOf(String);
res.body.refresh_token.should.have.length(40);
res.body.token_type.should.equal('bearer');
res.body.expires_in.should.equal(3600);
res.body.expires_in.should.equal(1209600);

done();
});
Expand Down

0 comments on commit f8851c1

Please sign in to comment.