2017-01-21 16:41:06 +00:00
|
|
|
|
|
|
|
|
|
var sinon = require('sinon');
|
|
|
|
|
var Promise = require('bluebird');
|
|
|
|
|
var assert = require('assert');
|
|
|
|
|
var u2f = require('../../../src/lib/routes/u2f');
|
|
|
|
|
var winston = require('winston');
|
|
|
|
|
|
|
|
|
|
describe('test u2f routes', function() {
|
|
|
|
|
var req, res;
|
2017-01-21 19:24:35 +00:00
|
|
|
|
var user_data_store;
|
2017-01-21 16:41:06 +00:00
|
|
|
|
|
|
|
|
|
beforeEach(function() {
|
|
|
|
|
req = {}
|
|
|
|
|
req.app = {};
|
|
|
|
|
req.app.get = sinon.stub();
|
|
|
|
|
req.app.get.withArgs('logger').returns(winston);
|
|
|
|
|
req.session = {};
|
|
|
|
|
req.session.auth_session = {};
|
|
|
|
|
req.session.auth_session.userid = 'user';
|
|
|
|
|
req.session.auth_session.first_factor = true;
|
|
|
|
|
req.session.auth_session.second_factor = false;
|
2017-01-27 00:20:03 +00:00
|
|
|
|
req.session.auth_session.identity_check = {};
|
|
|
|
|
req.session.auth_session.identity_check.challenge = 'u2f-register';
|
|
|
|
|
req.session.auth_session.register_request = {};
|
2017-01-21 16:41:06 +00:00
|
|
|
|
req.headers = {};
|
|
|
|
|
req.headers.host = 'localhost';
|
|
|
|
|
|
2017-01-21 19:24:35 +00:00
|
|
|
|
var options = {};
|
|
|
|
|
options.inMemoryOnly = true;
|
|
|
|
|
|
|
|
|
|
user_data_store = {};
|
|
|
|
|
user_data_store.set_u2f_meta = sinon.stub().returns(Promise.resolve({}));
|
|
|
|
|
user_data_store.get_u2f_meta = sinon.stub().returns(Promise.resolve({}));
|
|
|
|
|
req.app.get.withArgs('user data store').returns(user_data_store);
|
|
|
|
|
|
2017-01-21 16:41:06 +00:00
|
|
|
|
res = {};
|
|
|
|
|
res.send = sinon.spy();
|
2017-01-21 19:24:35 +00:00
|
|
|
|
res.json = sinon.spy();
|
2017-01-21 16:41:06 +00:00
|
|
|
|
res.status = sinon.spy();
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
describe('test registration request', test_registration_request);
|
|
|
|
|
describe('test registration', test_registration);
|
|
|
|
|
describe('test signing request', test_signing_request);
|
|
|
|
|
describe('test signing', test_signing);
|
|
|
|
|
|
|
|
|
|
function test_registration_request() {
|
|
|
|
|
it('should send back the registration request and save it in the session', function(done) {
|
|
|
|
|
var expectedRequest = {
|
|
|
|
|
test: 'abc'
|
|
|
|
|
};
|
|
|
|
|
res.json = sinon.spy(function(data) {
|
|
|
|
|
assert.equal(200, res.status.getCall(0).args[0]);
|
|
|
|
|
assert.deepEqual(expectedRequest, data);
|
|
|
|
|
done();
|
|
|
|
|
});
|
|
|
|
|
var user_key_container = {};
|
|
|
|
|
var u2f_mock = {};
|
|
|
|
|
u2f_mock.startRegistration = sinon.stub();
|
|
|
|
|
u2f_mock.startRegistration.returns(Promise.resolve(expectedRequest));
|
|
|
|
|
|
|
|
|
|
req.app.get.withArgs('u2f').returns(u2f_mock);
|
2017-01-21 19:24:35 +00:00
|
|
|
|
u2f.register_request(req, res);
|
2017-01-21 16:41:06 +00:00
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should return internal error on registration request', function(done) {
|
|
|
|
|
res.send = sinon.spy(function(data) {
|
|
|
|
|
assert.equal(500, res.status.getCall(0).args[0]);
|
|
|
|
|
done();
|
|
|
|
|
});
|
|
|
|
|
var user_key_container = {};
|
|
|
|
|
var u2f_mock = {};
|
|
|
|
|
u2f_mock.startRegistration = sinon.stub();
|
|
|
|
|
u2f_mock.startRegistration.returns(Promise.reject('Internal error'));
|
|
|
|
|
|
|
|
|
|
req.app.get.withArgs('u2f').returns(u2f_mock);
|
2017-01-21 19:24:35 +00:00
|
|
|
|
u2f.register_request(req, res);
|
2017-01-21 16:41:06 +00:00
|
|
|
|
});
|
2017-01-27 00:20:03 +00:00
|
|
|
|
|
|
|
|
|
it('should return forbidden if identity has not been verified', function(done) {
|
|
|
|
|
res.send = sinon.spy(function(data) {
|
|
|
|
|
assert.equal(403, res.status.getCall(0).args[0]);
|
|
|
|
|
done();
|
|
|
|
|
});
|
|
|
|
|
req.session.auth_session.identity_check = undefined;
|
|
|
|
|
u2f.register_request(req, res);
|
|
|
|
|
});
|
2017-01-21 16:41:06 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function test_registration() {
|
2017-01-21 19:24:35 +00:00
|
|
|
|
it('should save u2f meta and return status code 200', function(done) {
|
2017-01-21 16:41:06 +00:00
|
|
|
|
var expectedStatus = {
|
|
|
|
|
keyHandle: 'keyHandle',
|
|
|
|
|
publicKey: 'pbk',
|
|
|
|
|
certificate: 'cert'
|
|
|
|
|
};
|
|
|
|
|
res.send = sinon.spy(function(data) {
|
2017-01-28 00:32:25 +00:00
|
|
|
|
assert.equal('user', user_data_store.set_u2f_meta.getCall(0).args[0])
|
|
|
|
|
assert.equal(req.session.auth_session.identity_check, undefined);
|
2017-01-21 16:41:06 +00:00
|
|
|
|
done();
|
|
|
|
|
});
|
|
|
|
|
var u2f_mock = {};
|
|
|
|
|
u2f_mock.finishRegistration = sinon.stub();
|
|
|
|
|
u2f_mock.finishRegistration.returns(Promise.resolve(expectedStatus));
|
|
|
|
|
|
|
|
|
|
req.session.auth_session.register_request = {};
|
|
|
|
|
req.app.get.withArgs('u2f').returns(u2f_mock);
|
2017-01-21 19:24:35 +00:00
|
|
|
|
u2f.register(req, res);
|
2017-01-21 16:41:06 +00:00
|
|
|
|
});
|
|
|
|
|
|
2017-01-22 16:54:45 +00:00
|
|
|
|
it('should return unauthorized on finishRegistration error', function(done) {
|
2017-01-21 16:41:06 +00:00
|
|
|
|
res.send = sinon.spy(function(data) {
|
2017-01-27 00:20:03 +00:00
|
|
|
|
assert.equal(500, res.status.getCall(0).args[0]);
|
2017-01-21 16:41:06 +00:00
|
|
|
|
done();
|
|
|
|
|
});
|
|
|
|
|
var user_key_container = {};
|
|
|
|
|
var u2f_mock = {};
|
|
|
|
|
u2f_mock.finishRegistration = sinon.stub();
|
|
|
|
|
u2f_mock.finishRegistration.returns(Promise.reject('Internal error'));
|
|
|
|
|
|
2017-01-22 16:54:45 +00:00
|
|
|
|
req.session.auth_session.register_request = 'abc';
|
2017-01-21 16:41:06 +00:00
|
|
|
|
req.app.get.withArgs('u2f').returns(u2f_mock);
|
2017-01-21 19:24:35 +00:00
|
|
|
|
u2f.register(req, res);
|
2017-01-21 16:41:06 +00:00
|
|
|
|
});
|
|
|
|
|
|
2017-01-29 00:33:48 +00:00
|
|
|
|
it('should return 403 when register_request is not provided', function(done) {
|
|
|
|
|
res.send = sinon.spy(function(data) {
|
|
|
|
|
assert.equal(403, res.status.getCall(0).args[0]);
|
|
|
|
|
done();
|
|
|
|
|
});
|
|
|
|
|
var user_key_container = {};
|
|
|
|
|
var u2f_mock = {};
|
|
|
|
|
u2f_mock.finishRegistration = sinon.stub();
|
|
|
|
|
u2f_mock.finishRegistration.returns(Promise.resolve());
|
|
|
|
|
|
|
|
|
|
req.session.auth_session.register_request = undefined;
|
|
|
|
|
req.app.get.withArgs('u2f').returns(u2f_mock);
|
|
|
|
|
u2f.register(req, res);
|
|
|
|
|
});
|
|
|
|
|
|
2017-01-27 00:20:03 +00:00
|
|
|
|
it('should return forbidden error when no auth request has been initiated', function(done) {
|
2017-01-21 16:41:06 +00:00
|
|
|
|
res.send = sinon.spy(function(data) {
|
2017-01-27 00:20:03 +00:00
|
|
|
|
assert.equal(403, res.status.getCall(0).args[0]);
|
2017-01-21 16:41:06 +00:00
|
|
|
|
done();
|
|
|
|
|
});
|
|
|
|
|
var user_key_container = {};
|
|
|
|
|
var u2f_mock = {};
|
|
|
|
|
u2f_mock.finishRegistration = sinon.stub();
|
|
|
|
|
u2f_mock.finishRegistration.returns(Promise.resolve());
|
|
|
|
|
|
2017-01-27 00:20:03 +00:00
|
|
|
|
req.session.auth_session.register_request = undefined;
|
2017-01-21 16:41:06 +00:00
|
|
|
|
req.app.get.withArgs('u2f').returns(u2f_mock);
|
2017-01-21 19:24:35 +00:00
|
|
|
|
u2f.register(req, res);
|
2017-01-21 16:41:06 +00:00
|
|
|
|
});
|
2017-01-27 00:20:03 +00:00
|
|
|
|
|
|
|
|
|
it('should return forbidden error when identity has not been verified', function(done) {
|
|
|
|
|
res.send = sinon.spy(function(data) {
|
|
|
|
|
assert.equal(403, res.status.getCall(0).args[0]);
|
|
|
|
|
done();
|
|
|
|
|
});
|
|
|
|
|
req.session.auth_session.identity_check = undefined;
|
|
|
|
|
u2f.register(req, res);
|
|
|
|
|
});
|
2017-01-21 16:41:06 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function test_signing_request() {
|
|
|
|
|
it('should send back the sign request and save it in the session', function(done) {
|
|
|
|
|
var expectedRequest = {
|
|
|
|
|
test: 'abc'
|
|
|
|
|
};
|
|
|
|
|
res.json = sinon.spy(function(data) {
|
|
|
|
|
assert.deepEqual(expectedRequest, req.session.auth_session.sign_request);
|
|
|
|
|
assert.equal(200, res.status.getCall(0).args[0]);
|
|
|
|
|
assert.deepEqual(expectedRequest, data);
|
|
|
|
|
done();
|
|
|
|
|
});
|
|
|
|
|
var user_key_container = {};
|
|
|
|
|
user_key_container['user'] = {}; // simulate a registration
|
|
|
|
|
var u2f_mock = {};
|
|
|
|
|
u2f_mock.startAuthentication = sinon.stub();
|
|
|
|
|
u2f_mock.startAuthentication.returns(Promise.resolve(expectedRequest));
|
|
|
|
|
|
|
|
|
|
req.app.get.withArgs('u2f').returns(u2f_mock);
|
2017-01-21 19:24:35 +00:00
|
|
|
|
u2f.sign_request(req, res);
|
2017-01-21 16:41:06 +00:00
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should return unauthorized error on registration request error', function(done) {
|
|
|
|
|
res.send = sinon.spy(function(data) {
|
2017-01-27 00:20:03 +00:00
|
|
|
|
assert.equal(500, res.status.getCall(0).args[0]);
|
2017-01-21 16:41:06 +00:00
|
|
|
|
done();
|
|
|
|
|
});
|
|
|
|
|
var user_key_container = {};
|
|
|
|
|
user_key_container['user'] = {}; // simulate a registration
|
|
|
|
|
var u2f_mock = {};
|
|
|
|
|
u2f_mock.startAuthentication = sinon.stub();
|
|
|
|
|
u2f_mock.startAuthentication.returns(Promise.reject('Internal error'));
|
|
|
|
|
|
|
|
|
|
req.app.get.withArgs('u2f').returns(u2f_mock);
|
2017-01-21 19:24:35 +00:00
|
|
|
|
u2f.sign_request(req, res);
|
2017-01-21 16:41:06 +00:00
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should send unauthorized error when no registration exists', function(done) {
|
|
|
|
|
var expectedRequest = {
|
|
|
|
|
test: 'abc'
|
|
|
|
|
};
|
|
|
|
|
res.send = sinon.spy(function(data) {
|
|
|
|
|
assert.equal(401, res.status.getCall(0).args[0]);
|
|
|
|
|
done();
|
|
|
|
|
});
|
|
|
|
|
var user_key_container = {}; // no entry means no registration
|
|
|
|
|
var u2f_mock = {};
|
|
|
|
|
u2f_mock.startAuthentication = sinon.stub();
|
|
|
|
|
u2f_mock.startAuthentication.returns(Promise.resolve(expectedRequest));
|
|
|
|
|
|
2017-01-21 19:24:35 +00:00
|
|
|
|
user_data_store.get_u2f_meta = sinon.stub().returns(Promise.resolve());
|
|
|
|
|
|
|
|
|
|
req.app.get = sinon.stub();
|
|
|
|
|
req.app.get.withArgs('logger').returns(winston);
|
|
|
|
|
req.app.get.withArgs('user data store').returns(user_data_store);
|
2017-01-21 16:41:06 +00:00
|
|
|
|
req.app.get.withArgs('u2f').returns(u2f_mock);
|
2017-01-21 19:24:35 +00:00
|
|
|
|
u2f.sign_request(req, res);
|
2017-01-21 16:41:06 +00:00
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function test_signing() {
|
|
|
|
|
it('should return status code 204', function(done) {
|
|
|
|
|
var user_key_container = {};
|
|
|
|
|
user_key_container['user'] = {};
|
|
|
|
|
var expectedStatus = {
|
|
|
|
|
keyHandle: 'keyHandle',
|
|
|
|
|
publicKey: 'pbk',
|
|
|
|
|
certificate: 'cert'
|
|
|
|
|
};
|
|
|
|
|
res.send = sinon.spy(function(data) {
|
|
|
|
|
assert(204, res.status.getCall(0).args[0]);
|
|
|
|
|
assert(req.session.auth_session.second_factor);
|
|
|
|
|
done();
|
|
|
|
|
});
|
|
|
|
|
var u2f_mock = {};
|
|
|
|
|
u2f_mock.finishAuthentication = sinon.stub();
|
|
|
|
|
u2f_mock.finishAuthentication.returns(Promise.resolve(expectedStatus));
|
|
|
|
|
|
|
|
|
|
req.session.auth_session.sign_request = {};
|
|
|
|
|
req.app.get.withArgs('u2f').returns(u2f_mock);
|
2017-01-21 19:24:35 +00:00
|
|
|
|
u2f.sign(req, res);
|
2017-01-21 16:41:06 +00:00
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should return unauthorized error on registration request internal error', function(done) {
|
|
|
|
|
res.send = sinon.spy(function(data) {
|
2017-01-27 00:20:03 +00:00
|
|
|
|
assert.equal(500, res.status.getCall(0).args[0]);
|
2017-01-21 16:41:06 +00:00
|
|
|
|
done();
|
|
|
|
|
});
|
|
|
|
|
var user_key_container = {};
|
|
|
|
|
user_key_container['user'] = {};
|
|
|
|
|
|
|
|
|
|
var u2f_mock = {};
|
|
|
|
|
u2f_mock.finishAuthentication = sinon.stub();
|
|
|
|
|
u2f_mock.finishAuthentication.returns(Promise.reject('Internal error'));
|
|
|
|
|
|
|
|
|
|
req.session.auth_session.sign_request = {};
|
|
|
|
|
req.app.get.withArgs('u2f').returns(u2f_mock);
|
2017-01-21 20:57:48 +00:00
|
|
|
|
u2f.sign(req, res);
|
2017-01-21 16:41:06 +00:00
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should return unauthorized error when no sign request has been initiated', function(done) {
|
|
|
|
|
res.send = sinon.spy(function(data) {
|
|
|
|
|
assert.equal(401, res.status.getCall(0).args[0]);
|
|
|
|
|
done();
|
|
|
|
|
});
|
|
|
|
|
var user_key_container = {};
|
|
|
|
|
var u2f_mock = {};
|
|
|
|
|
u2f_mock.finishAuthentication = sinon.stub();
|
|
|
|
|
u2f_mock.finishAuthentication.returns(Promise.resolve());
|
|
|
|
|
|
|
|
|
|
req.app.get.withArgs('u2f').returns(u2f_mock);
|
2017-01-21 20:57:48 +00:00
|
|
|
|
u2f.sign(req, res);
|
2017-01-21 16:41:06 +00:00
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|