Add loopback.token() middleware
This commit is contained in:
parent
77a137eca6
commit
64d8ff986b
|
@ -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();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue