Skip to content

Commit

Permalink
Allow any valid URI for extension grants
Browse files Browse the repository at this point in the history
  • Loading branch information
thomseddon committed Jan 26, 2015
1 parent 4d4f248 commit c169c1b
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 7 deletions.
2 changes: 1 addition & 1 deletion Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ The spec does not actually require that you revoke the old token - hence this is

## Extension Grants
You can support extension/custom grants by implementing the extendedGrant method as outlined above.
Any requests that begin with http(s):// (as [defined in the spec](http://tools.ietf.org/html/rfc6749#section-4.5)) will be passed to it for you to handle.
Any grant type that is a valid URI will be passed to it for you to handle (as [defined in the spec](http://tools.ietf.org/html/rfc6749#section-4.5)).
You can access the grant type via the first argument and you should pass back supported as `false` if you do not support it to ensure a consistent (and compliant) response.

## Example using the `password` grant type
Expand Down
3 changes: 2 additions & 1 deletion lib/grant.js
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,8 @@ function checkClient (done) {
* @this OAuth
*/
function checkGrantType (done) {
if (this.grantType.match(/^http(s|):\/\//) && this.model.extendedGrant) {
if (this.grantType.match(/^[a-zA-Z][a-zA-Z0-9+.-]+:/)
&& this.model.extendedGrant) {
return useExtendedGrant.call(this, done);
}

Expand Down
6 changes: 4 additions & 2 deletions lib/oauth2server.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ OAuth2Server.prototype.authorise = function () {
var self = this;

return function (req, res, next) {
new Authorise(self, req, next);
return new Authorise(self, req, next);
};
};

Expand Down Expand Up @@ -213,7 +213,9 @@ OAuth2Server.prototype.lockdown = function (app) {

if (app.routes) {
for (var method in app.routes) {
app.routes[method].callbacks.forEach(lockdownExpress3);
app.routes[method].forEach(function (route) {
lockdownExpress3(route.callbacks);
});
}
} else {
app._router.stack.forEach(lockdownExpress4);
Expand Down
36 changes: 33 additions & 3 deletions test/grant.extended.js
Original file line number Diff line number Diff line change
Expand Up @@ -129,9 +129,9 @@ describe('Granting with extended grant type', function () {
extendedGrant: function (grantType, req, callback) {
callback(false, true, { id: 3 });
},
saveAccessToken: function () {
done(); // That's enough
}
saveAccessToken: function (token, clientId, expires, user, cb) {
cb();
},
},
grants: ['http://custom.com']
});
Expand All @@ -146,4 +146,34 @@ describe('Granting with extended grant type', function () {
})
.expect(200, done);
});

it('should allow any valid URI valid request', function (done) {
var app = bootstrap({
model: {
getClient: function (id, secret, callback) {
callback(false, true);
},
grantTypeAllowed: function (clientId, grantType, callback) {
callback(false, true);
},
extendedGrant: function (grantType, req, callback) {
callback(false, true, { id: 3 });
},
saveAccessToken: function (token, clientId, expires, user, cb) {
cb();
},
},
grants: ['urn:custom:grant']
});

request(app)
.post('/oauth/token')
.set('Content-Type', 'application/x-www-form-urlencoded')
.send({
grant_type: 'urn:custom:grant',
client_id: 'thom',
client_secret: 'nightworld'
})
.expect(200, done);
});
});
45 changes: 45 additions & 0 deletions test/lockdown.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ var express = require('express'),
should = require('should');

var oauth2server = require('../');
var Authorise = require('../lib/authorise');

var bootstrap = function (oauthConfig) {
var app = express();
Expand Down Expand Up @@ -86,4 +87,48 @@ describe('Lockdown pattern', function() {
.get('/public')
.expect(200, /hello/i, done);
});

describe('in express 3', function () {
var app, privateAction, publicAction;

beforeEach(function () {
privateAction = function () {};
publicAction = function () {};

// mock express 3 app
app = {
routes: { get: [] }
};

app.oauth = oauth2server({ model: {} });
app.routes.get.push({ callbacks: [ privateAction ] });
app.routes.get.push({ callbacks: [ app.oauth.bypass, publicAction ] })
app.oauth.lockdown(app);
});

function mockRequest(authoriseFactory) {
var req = {
get: function () {},
query: { access_token: { expires: null } }
};
var next = function () {};

app.oauth.model.getAccessToken = function (t, c) { c(null, t); };

return authoriseFactory(req, null, next);
}

it('adds authorise to non-bypassed routes', function () {
var authorise = mockRequest(app.routes.get[0].callbacks[0]);
authorise.should.be.an.instanceOf(Authorise);
});

it('runs non-bypassed routes after authorise', function () {
app.routes.get[0].callbacks[1].should.equal(privateAction);
});

it('removes oauth.bypass from bypassed routes', function () {
app.routes.get[1].callbacks[0].should.equal(publicAction);
});
});
});

0 comments on commit c169c1b

Please sign in to comment.