diff --git a/lib/middleware/token.js b/lib/middleware/token.js index c642c84a..6b9a76e4 100644 --- a/lib/middleware/token.js +++ b/lib/middleware/token.js @@ -11,18 +11,22 @@ var RemoteObjects = require('strong-remoting'); module.exports = token; -/** - * - */ - function token(app, options) { options = options || {}; - var tokenModelName = options.tokenModelName || 'Token'; - var TokenModel = app.getModel(tokenModelName); - var tokenHeaderName = options.tokenHeaderName || 'X-Access-Token'; + var tokenModelName = options.tokenModelName || 'AccessToken'; + var TokenModel = options.model; + assert(TokenModel, 'loopback.token() middleware requires a AccessToken model'); return function (req, res, next) { - next(); + TokenModel.findForRequest(req, options, function(err, token) { + if(err) return next(err); + if(token) { + req.accessToken = token; + next(); + } else { + return next(); + } + }); } } diff --git a/lib/models/access-token.js b/lib/models/access-token.js index df8a95ab..65211d66 100644 --- a/lib/models/access-token.js +++ b/lib/models/access-token.js @@ -4,7 +4,8 @@ var Model = require('../loopback').Model , loopback = require('../loopback') - , crypto = require('crypto'); + , crypto = require('crypto') + , uid = require('uid2'); /** * Default AccessToken properties. @@ -20,7 +21,7 @@ var properties = { * Extends from the built in `loopback.Model` type. */ -var AccessToken = module.exports = Model.extend('access-token', properties); +var AccessToken = module.exports = Model.extend('AccessToken', properties); /** * Create a cryptographically random access token id. @@ -29,7 +30,7 @@ var AccessToken = module.exports = Model.extend('access-token', properties); */ AccessToken.createAccessTokenId = function (fn) { - crypto.randomBytes(this.settings.accessTokenIdLength || 64, function(err, buf) { + uid(this.settings.accessTokenIdLength || 64, function(err, buf) { if(err) { fn(err); } else { @@ -54,3 +55,64 @@ AccessToken.beforeCreate = function (next, data) { } }); } + +/** + * Find a token for the given `ServerRequest`. + * + * @param {ServerRequest} req + * @param {Object} [options] Options for finding the token + * @param {Function} callback Calls back with a token if one exists otherwise null or an error. + */ + +AccessToken.findForRequest = function(req, options, cb) { + var id = tokenIdForRequest(req, options); + + if(id) { + this.findById(id, cb); + } else { + process.nextTick(function() { + cb(); + }); + } +} + +function tokenIdForRequest(req, options) { + var params = options.params || []; + var headers = options.headers || []; + var cookies = options.cookies || []; + var i = 0; + var length; + var id; + + params.push('access_token'); + headers.push('X-Access-Token'); + headers.push('authorization'); + cookies.push('access_token'); + cookies.push('authorization'); + + for(length = params.length; i < length; i++) { + id = req.param(params[i]); + + if(typeof id === 'string') { + return id; + } + } + + for(length = headers.length; i < length; i++) { + id = req.header(params[i]); + + if(typeof id === 'string') { + return id; + } + } + + for(length = headers.length; i < length; i++) { + id = req.signedCookies(cookies[i]); + + if(typeof id === 'string') { + return id; + } + } + + return null; +} diff --git a/package.json b/package.json index d8978bb0..7883e8de 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,8 @@ "ejs": "~0.8.4", "bcryptjs": "~0.7.10", "underscore.string": "~2.3.3", - "underscore": "~1.5.2" + "underscore": "~1.5.2", + "uid2": "0.0.3" }, "devDependencies": { "blanket": "~1.1.5", diff --git a/test/access-token.test.js b/test/access-token.test.js index f65a30e1..468d6c58 100644 --- a/test/access-token.test.js +++ b/test/access-token.test.js @@ -10,12 +10,17 @@ describe('loopback.token(app, options)', function() { it('should populate req.token from the query string', function (done) { var app = loopback(); var options = {}; + options.model = Token; var testToken = this.token; app.use(loopback.token(app, options)); app.get('/', function (req, res) { - assert(req.token === testToken); + try { + assert(req.accessToken, 'req should have accessToken'); + assert(req.accessToken.id === testToken.id); + } catch(e) { + return done(e); + } res.send('ok'); - done(); }); request(app) @@ -32,4 +37,4 @@ function createTestingToken(done) { test.token = token; done(); }); -} \ No newline at end of file +} diff --git a/test/user.test.js b/test/user.test.js index a70c0047..24a7f7b9 100644 --- a/test/user.test.js +++ b/test/user.test.js @@ -103,7 +103,7 @@ describe('User', function(){ User.login({email: 'foo@bar.com', password: 'bar'}, function (err, accessToken) { assert(accessToken.uid); assert(accessToken.id); - assert.equal((new Buffer(accessToken.id, 'base64')).length, 64); + assert.equal(accessToken.id.length, 64); done(); }); @@ -121,7 +121,7 @@ describe('User', function(){ assert(accessToken.uid); assert(accessToken.id); - assert.equal((new Buffer(accessToken.id, 'base64')).length, 64); + assert.equal(accessToken.id.length, 64); done(); });