0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-03-11 02:12:21 -05:00

Auth tests

- added tests for authentication middleware
- changed use of auth strategies
This commit is contained in:
Sebastian Gierlinger 2015-08-09 12:50:05 +02:00
parent c1a2601514
commit a993f80a51
3 changed files with 176 additions and 84 deletions

View file

@ -1,66 +1,70 @@
var passport = require('passport'),
BearerStrategy = require('passport-http-bearer').Strategy,
ClientPasswordStrategy = require('passport-oauth2-client-password').Strategy,
models = require('../models');
var BearerStrategy = require('passport-http-bearer').Strategy,
ClientPasswordStrategy = require('passport-oauth2-client-password').Strategy,
models = require('../models'),
strategies;
/**
* ClientPasswordStrategy
*
* This strategy is used to authenticate registered OAuth clients. It is
* employed to protect the `token` endpoint, which consumers use to obtain
* access tokens. The OAuth 2.0 specification suggests that clients use the
* HTTP Basic scheme to authenticate (not implemented yet).
strategies = {
* Use of the client password strategy is implemented to support ember-simple-auth.
*/
passport.use(new ClientPasswordStrategy(
function strategy(clientId, clientSecret, done) {
models.Client.forge({slug: clientId})
.fetch()
.then(function then(model) {
if (model) {
var client = model.toJSON();
if (client.secret === clientSecret) {
return done(null, client);
/**
* ClientPasswordStrategy
*
* This strategy is used to authenticate registered OAuth clients. It is
* employed to protect the `token` endpoint, which consumers use to obtain
* access tokens. The OAuth 2.0 specification suggests that clients use the
* HTTP Basic scheme to authenticate (not implemented yet).
* Use of the client password strategy is implemented to support ember-simple-auth.
*/
clientPasswordStrategy: new ClientPasswordStrategy(
function strategy(clientId, clientSecret, done) {
models.Client.forge({slug: clientId})
.fetch()
.then(function then(model) {
if (model) {
var client = model.toJSON();
if (client.secret === clientSecret) {
return done(null, client);
}
}
}
return done(null, false);
});
}
));
return done(null, false);
});
}
),
/**
* BearerStrategy
*
* This strategy is used to authenticate users based on an access token (aka a
* bearer token). The user must have previously authorized a client
* application, which is issued an access token to make requests on behalf of
* the authorizing user.
*/
passport.use(new BearerStrategy(
function strategy(accessToken, done) {
models.Accesstoken.forge({token: accessToken})
.fetch()
.then(function then(model) {
if (model) {
var token = model.toJSON();
if (token.expires > Date.now()) {
models.User.forge({id: token.user_id})
.fetch()
.then(function then(model) {
if (model) {
var user = model.toJSON(),
info = {scope: '*'};
return done(null, {id: user.id}, info);
}
/**
* BearerStrategy
*
* This strategy is used to authenticate users based on an access token (aka a
* bearer token). The user must have previously authorized a client
* application, which is issued an access token to make requests on behalf of
* the authorizing user.
*/
bearerStrategy: new BearerStrategy(
function strategy(accessToken, done) {
models.Accesstoken.forge({token: accessToken})
.fetch()
.then(function then(model) {
if (model) {
var token = model.toJSON();
if (token.expires > Date.now()) {
models.User.forge({id: token.user_id})
.fetch()
.then(function then(model) {
if (model) {
var user = model.toJSON(),
info = {scope: '*'};
return done(null, {id: user.id}, info);
}
return done(null, false);
});
} else {
return done(null, false);
});
}
} else {
return done(null, false);
}
} else {
return done(null, false);
}
});
}
));
});
}
)
};
module.exports = strategies;

View file

@ -45,7 +45,6 @@ middleware = {
cacheOauthServer: clientAuth.cacheOauthServer,
authenticateClient: clientAuth.authenticateClient,
generateAccessToken: clientAuth.generateAccessToken,
methodNotAllowed: apiErrorHandlers.methodNotAllowed,
errorHandler: apiErrorHandlers.errorHandler
}
};
@ -56,7 +55,8 @@ setupMiddleware = function setupMiddleware(blogAppInstance, adminApp) {
oauthServer = oauth2orize.createServer();
// silence JSHint without disabling unused check for the whole file
authStrategies = authStrategies;
passport.use(authStrategies.clientPasswordStrategy);
passport.use(authStrategies.bearerStrategy);
// Cache express server instance
blogApp = blogAppInstance;

View file

@ -1,57 +1,145 @@
/*globals describe, it, beforeEach, afterEach */
/*jshint expr:true*/
var sinon = require('sinon'),
should = require('should'),
passport = require('passport'),
authenticate = require('../../../server/middleware/authenticate');
var sinon = require('sinon'),
should = require('should'),
passport = require('passport'),
authenticate = require('../../../server/middleware/authenticate'),
BearerStrategy = require('passport-http-bearer').Strategy,
user = {id: 1},
info = {scope: '*'},
token = 'test_token';
should.equal(true, true);
function registerSuccessfulBearerStrategy() {
// register fake BearerStrategy which always authenticates
passport.use(new BearerStrategy(
function strategy(accessToken, done) {
accessToken.should.eql(token);
return done(null, user, info);
}
));
}
function registerUnsuccessfulBearerStrategy() {
// register fake BearerStrategy which always authenticates
passport.use(new BearerStrategy(
function strategy(accessToken, done) {
accessToken.should.eql(token);
return done(null, false);
}
));
}
function registerSuccessfulBearerStrategy() {
// register fake BearerStrategy which always authenticates
passport.use(new BearerStrategy(
function strategy(accessToken, done) {
accessToken.should.eql(token);
return done(null, user, info);
}
));
}
describe('authenticate', function () {
var res, req, next, sandbox;
beforeEach(function () {
sandbox = sinon.sandbox.create();
res = sinon.spy();
req = sinon.spy();
next = sinon.spy();
req = {};
res = {};
next = sandbox.spy();
});
afterEach(function () {
sandbox.restore();
});
it('should skip authentication if not hitting /ghost', function () {
req.path = '/tag/foo';
it('should skip authentication if not hitting /ghost', function (done) {
req.path = '/tag/foo/';
req.method = 'GET';
registerSuccessfulBearerStrategy();
authenticate(req, res, next);
next.called.should.be.true;
next.calledWith().should.be.true;
done();
});
it('should authenticate if hitting /ghost/ auth endpoint', function (done) {
it('should skip authentication if hitting /ghost/api/v0.1/authenticaton/', function (done) {
req.path = '/ghost/api/v0.1/authentication/';
req.method = 'GET';
registerSuccessfulBearerStrategy();
authenticate(req, res, next);
next.called.should.be.true;
next.calledWith().should.be.true;
done();
});
it('should skip authentication if hitting GET /ghost/api/v0.1/authenticaton/setup/', function (done) {
req.path = '/ghost/api/v0.1/authentication/setup/';
req.method = 'GET';
registerSuccessfulBearerStrategy();
authenticate(req, res, next);
next.called.should.be.true;
next.calledWith().should.be.true;
done();
});
it('should authentication if hitting PUT /ghost/api/v0.1/authenticaton/setup/', function (done) {
req.path = '/ghost/api/v0.1/authentication/setup/';
req.method = 'PUT';
req.headers = {};
req.headers.authorization = 'Bearer ' + token;
sandbox.stub(passport, 'authenticate', function (method, options, cb) {
var user = {slug: 'user'},
info = {info: 'some'};
registerSuccessfulBearerStrategy();
authenticate(req, res, next);
method.should.equal('bearer');
options.session.should.be.false;
options.failWithError.should.be.true;
next.called.should.be.true;
next.calledWith(null, user, info).should.be.true;
done();
});
return function (req, res, next) {
cb(null, user, info);
next.called.should.be.true;
next.calledWith(null, user, info).should.be.true;
req.authInfo.should.equal(info);
req.user.should.equal(user);
done();
it('should authenticate if hitting /ghost/api/ endpoint', function (done) {
req.path = '/ghost/api/v0.1/test/';
req.method = 'PUT';
req.headers = {};
req.headers.authorization = 'Bearer ' + token;
registerSuccessfulBearerStrategy();
authenticate(req, res, next);
next.called.should.be.true;
next.calledWith(null, user, info).should.be.true;
done();
});
it('shouldn\'t authenticate if hitting /ghost/ auth endpoint with invalid credentials', function (done) {
res.status = {};
req.path = '/ghost/api/v0.1/test/';
req.method = 'PUT';
req.headers = {};
req.headers.authorization = 'Bearer ' + token;
registerUnsuccessfulBearerStrategy();
// stub res.status for error handling
sandbox.stub(res, 'status', function (statusCode) {
statusCode.should.eql(401);
return {
json: function (err) {
err.errors[0].errorType.should.eql('NoPermissionError');
}
};
});
authenticate(req, res, next);
next.called.should.be.false;
done();
});
});