Skip to content

Commit

Permalink
Merge pull request #5963 from ErisDS/auth-strategy-refactor
Browse files Browse the repository at this point in the history
Auth strategy refactor
  • Loading branch information
sebgie committed Oct 18, 2015
2 parents 0a1e17a + 2c51a89 commit c6b5055
Show file tree
Hide file tree
Showing 2 changed files with 106 additions and 68 deletions.
9 changes: 3 additions & 6 deletions core/server/middleware/auth-strategies.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@ strategies = {
* Use of the client password strategy is implemented to support ember-simple-auth.
*/
clientPasswordStrategy: function clientPasswordStrategy(clientId, clientSecret, done) {
return models.Client.forge({slug: clientId})
.fetch()
return models.Client.findOne({slug: clientId})
.then(function then(model) {
if (model) {
var client = model.toJSON();
Expand All @@ -35,14 +34,12 @@ strategies = {
* the authorizing user.
*/
bearerStrategy: function bearerStrategy(accessToken, done) {
return models.Accesstoken.forge({token: accessToken})
.fetch()
return models.Accesstoken.findOne({token: accessToken})
.then(function then(model) {
if (model) {
var token = model.toJSON();
if (token.expires > Date.now()) {
return models.User.forge({id: token.user_id})
.fetch()
return models.User.findOne({id: token.user_id})
.then(function then(model) {
if (model) {
var user = model.toJSON(),
Expand Down
165 changes: 103 additions & 62 deletions core/test/unit/middleware/auth-strategies_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,138 +3,179 @@
var should = require('should'),
sinon = require('sinon'),
Promise = require('bluebird'),
testUtils = require('../../utils'),

authStrategies = require('../../../server/middleware/auth-strategies'),
models = require('../../../server/models'),
globalUtils = require('../../../server/utils');
Models = require('../../../server/models'),
globalUtils = require('../../../server/utils'),

sandbox = sinon.sandbox.create(),

fakeClient = {
slug: 'ghost-admin',
secret: 'not_available'
},

fakeValidToken = {
user_id: 3,
token: 'valid-token',
client_id: 1,
expires: Date.now() + globalUtils.ONE_DAY_MS
},
fakeInvalidToken = {
user_id: 3,
token: 'expired-token',
client_id: 1,
expires: Date.now() - globalUtils.ONE_DAY_MS
};

// To stop jshint complaining
should.equal(true, true);

describe('Auth Strategies', function () {
var next, sandbox;
var next;

before(testUtils.teardown);
before(function (done) {
// Loads all the models
Models.init().then(done).catch(done);
});

beforeEach(function () {
sandbox = sinon.sandbox.create();
next = sandbox.spy();
});

afterEach(function () {
sandbox.restore();
});
afterEach(testUtils.teardown);

describe('Client Password Strategy', function () {
beforeEach(testUtils.setup('clients'));
var clientStub;

beforeEach(function () {
clientStub = sandbox.stub(Models.Client, 'findOne');
clientStub.returns(new Promise.resolve());
clientStub.withArgs({slug: fakeClient.slug}).returns(new Promise.resolve({
toJSON: function () { return fakeClient; }
}));
});

it('should find client', function (done) {
var clientId = 'ghost-admin',
clientSecret = 'not_available';

authStrategies.clientPasswordStrategy(clientId, clientSecret, function () {
arguments.length.should.eql(2);
should.equal(arguments[0], null);
arguments[1].slug.should.eql('ghost-admin');
authStrategies.clientPasswordStrategy(clientId, clientSecret, next).then(function () {
clientStub.calledOnce.should.be.true;
clientStub.calledWith({slug: clientId}).should.be.true;
next.called.should.be.true;
next.firstCall.args.length.should.eql(2);
should.equal(next.firstCall.args[0], null);
next.firstCall.args[1].slug.should.eql(clientId);
done();
});
}).catch(done);
});

it('shouldn\'t find client with invalid id', function (done) {
var clientId = 'invalid_id',
clientSecret = 'not_available';
authStrategies.clientPasswordStrategy(clientId, clientSecret, next).then(function () {
clientStub.calledOnce.should.be.true;
clientStub.calledWith({slug: clientId}).should.be.true;
next.called.should.be.true;
next.calledWith(null, false).should.be.true;
done();
});
}).catch(done);
});

it('shouldn\'t find client with invalid secret', function (done) {
var clientId = 'ghost-admin',
clientSecret = 'invalid_secret';
authStrategies.clientPasswordStrategy(clientId, clientSecret, next).then(function () {
clientStub.calledOnce.should.be.true;
clientStub.calledWith({slug: clientId}).should.be.true;
next.called.should.be.true;
next.calledWith(null, false).should.be.true;
done();
});
}).catch(done);
});
});

describe('Bearer Strategy', function () {
beforeEach(testUtils.setup('users:roles', 'users', 'clients'));
var tokenStub, userStub;

beforeEach(function () {
tokenStub = sandbox.stub(Models.Accesstoken, 'findOne');
tokenStub.returns(new Promise.resolve());
tokenStub.withArgs({token: fakeValidToken.token}).returns(new Promise.resolve({
toJSON: function () { return fakeValidToken; }
}));
tokenStub.withArgs({token: fakeInvalidToken.token}).returns(new Promise.resolve({
toJSON: function () { return fakeInvalidToken; }
}));

userStub = sandbox.stub(Models.User, 'findOne');
userStub.returns(new Promise.resolve());
userStub.withArgs({id: 3}).returns(new Promise.resolve({
toJSON: function () { return {id: 3}; }
}));
});

it('should find user with valid token', function (done) {
var accessToken = 'valid-token';

testUtils.fixtures.insertAccessToken({
user_id: 3,
token: accessToken,
client_id: 1,
expires: Date.now() + globalUtils.ONE_DAY_MS
}).then(function () {
authStrategies.bearerStrategy(accessToken, function () {
should.equal(arguments[0], null);
arguments[1].id.should.eql(3);
arguments[2].scope.should.eql('*');
done();
});
});
var accessToken = 'valid-token',
userId = 3;

authStrategies.bearerStrategy(accessToken, next).then(function () {
tokenStub.calledOnce.should.be.true;
tokenStub.calledWith({token: accessToken}).should.be.true;
userStub.calledOnce.should.be.true;
userStub.calledWith({id: userId}).should.be.true;
next.calledOnce.should.be.true;
next.firstCall.args.length.should.eql(3);
next.calledWith(null, {id: userId}, {scope: '*'}).should.be.true;
done();
}).catch(done);
});

it('shouldn\'t find user with invalid token', function (done) {
var accessToken = 'invalid_token';

authStrategies.bearerStrategy(accessToken, next).then(function () {
tokenStub.calledOnce.should.be.true;
tokenStub.calledWith({token: accessToken}).should.be.true;
userStub.called.should.be.false;
next.called.should.be.true;
next.calledWith(null, false).should.be.true;
done();
});
}).catch(done);
});

it('should find user that doesn\'t exist', function (done) {
var accessToken = 'valid-token';

// stub needed for mysql, pg
// this case could only happen in sqlite
sandbox.stub(models.User, 'forge', function () {
return {
fetch: function () {
return Promise.resolve();
}
};
});

testUtils.fixtures.insertAccessToken({
user_id: 3,
token: accessToken,
client_id: 1,
expires: Date.now() + globalUtils.ONE_DAY_MS
}).then(function () {
return authStrategies.bearerStrategy(accessToken, next);
}).then(function () {
var accessToken = 'valid-token',
userId = 2;

// override user
fakeValidToken.user_id = userId;

authStrategies.bearerStrategy(accessToken, next).then(function () {
tokenStub.calledOnce.should.be.true;
tokenStub.calledWith({token: accessToken}).should.be.true;
userStub.calledOnce.should.be.true;
userStub.calledWith({id: userId}).should.be.true;
next.called.should.be.true;
next.calledWith(null, false).should.be.true;
done();
});
}).catch(done);
});

it('should find user with expired token', function (done) {
var accessToken = 'expired-token';

testUtils.fixtures.insertAccessToken({
user_id: 3,
token: accessToken,
client_id: 1,
expires: Date.now() - globalUtils.ONE_DAY_MS
}).then(function () {
return authStrategies.bearerStrategy(accessToken, next);
}).then(function () {
authStrategies.bearerStrategy(accessToken, next).then(function () {
tokenStub.calledOnce.should.be.true;
tokenStub.calledWith({token: accessToken}).should.be.true;
userStub.calledOnce.should.be.false;
next.called.should.be.true;
next.calledWith(null, false).should.be.true;
done();
});
}).catch(done);
});
});
});

0 comments on commit c6b5055

Please sign in to comment.