Registration process consumes the token so that it can only be used once

This commit is contained in:
Clement Michaud 2017-01-22 18:06:12 +01:00
parent d3db94105e
commit 804039b6aa
4 changed files with 36 additions and 9 deletions

View File

@ -26,8 +26,8 @@ function register_handler_get(req, res) {
var user_data_store = req.app.get('user data store'); var user_data_store = req.app.get('user data store');
logger.debug('U2F register_handler: verify token validity'); logger.debug('U2F register_handler: verify token validity and consume it');
user_data_store.verify_u2f_registration_token(registration_token) user_data_store.consume_u2f_registration_token(registration_token)
.then(function() { .then(function() {
res.render('u2f_register'); res.render('u2f_register');
}) })

View File

@ -51,9 +51,10 @@ UserDataStore.prototype.save_u2f_registration_token = function(userid, token, ma
return this._u2f_registration_tokens_collection.insertAsync(newDocument); return this._u2f_registration_tokens_collection.insertAsync(newDocument);
} }
UserDataStore.prototype.verify_u2f_registration_token = function(token) { UserDataStore.prototype.consume_u2f_registration_token = function(token) {
var query = {}; var query = {};
query.token = token; query.token = token;
var that = this;
return this._u2f_registration_tokens_collection.findOneAsync(query) return this._u2f_registration_tokens_collection.findOneAsync(query)
.then(function(doc) { .then(function(doc) {
@ -68,5 +69,8 @@ UserDataStore.prototype.verify_u2f_registration_token = function(token) {
} }
return Promise.resolve(); return Promise.resolve();
})
.then(function() {
return that._u2f_registration_tokens_collection.removeAsync(query);
}); });
} }

View File

@ -29,7 +29,7 @@ describe('test register handle', function() {
user_data_store.set_u2f_meta = sinon.stub().returns(Promise.resolve({})); user_data_store.set_u2f_meta = sinon.stub().returns(Promise.resolve({}));
user_data_store.get_u2f_meta = sinon.stub().returns(Promise.resolve({})); user_data_store.get_u2f_meta = sinon.stub().returns(Promise.resolve({}));
user_data_store.save_u2f_registration_token = sinon.stub().returns(Promise.resolve({})); user_data_store.save_u2f_registration_token = sinon.stub().returns(Promise.resolve({}));
user_data_store.verify_u2f_registration_token = sinon.stub().returns(Promise.resolve({})); user_data_store.consume_u2f_registration_token = sinon.stub().returns(Promise.resolve({}));
req.app.get.withArgs('user data store').returns(user_data_store); req.app.get.withArgs('user data store').returns(user_data_store);
res = {}; res = {};
@ -107,7 +107,7 @@ describe('test register handle', function() {
req.params = {}; req.params = {};
req.params.registration_token = 'token'; req.params.registration_token = 'token';
user_data_store.verify_u2f_registration_token = sinon.stub().returns(Promise.reject('Not valid anymore')); user_data_store.consume_u2f_registration_token = sinon.stub().returns(Promise.reject('Not valid anymore'));
u2f_register.register_handler_get(req, res); u2f_register.register_handler_get(req, res);
}); });

View File

@ -99,7 +99,7 @@ function test_u2f_registration_token() {
}); });
}); });
it('should save u2f registration token and verify it', function(done) { it('should save u2f registration token and consume it', function(done) {
var options = {}; var options = {};
options.inMemoryOnly = true; options.inMemoryOnly = true;
@ -111,7 +111,7 @@ function test_u2f_registration_token() {
data_store.save_u2f_registration_token(userid, token, max_age) data_store.save_u2f_registration_token(userid, token, max_age)
.then(function(document) { .then(function(document) {
return data_store.verify_u2f_registration_token(token); return data_store.consume_u2f_registration_token(token);
}) })
.then(function() { .then(function() {
done(); done();
@ -121,6 +121,29 @@ function test_u2f_registration_token() {
}); });
}); });
it('should not be able to consume registration token twice', function(done) {
var options = {};
options.inMemoryOnly = true;
var data_store = new UserDataStore(DataStore, options);
var userid = 'user';
var token = 'token';
var max_age = 50;
data_store.save_u2f_registration_token(userid, token, max_age)
.then(function(document) {
return data_store.consume_u2f_registration_token(token);
})
.then(function(document) {
return data_store.consume_u2f_registration_token(token);
})
.catch(function(err) {
console.error(err);
done();
});
});
it('should fail when token does not exist', function() { it('should fail when token does not exist', function() {
var options = {}; var options = {};
options.inMemoryOnly = true; options.inMemoryOnly = true;
@ -129,7 +152,7 @@ function test_u2f_registration_token() {
var token = 'token'; var token = 'token';
return data_store.verify_u2f_registration_token(token) return data_store.consume_u2f_registration_token(token)
.then(function(document) { .then(function(document) {
return Promise.reject(); return Promise.reject();
}) })
@ -152,7 +175,7 @@ function test_u2f_registration_token() {
data_store.save_u2f_registration_token(userid, token, max_age) data_store.save_u2f_registration_token(userid, token, max_age)
.then(function() { .then(function() {
MockDate.set('1/2/2000'); MockDate.set('1/2/2000');
return data_store.verify_u2f_registration_token(token); return data_store.consume_u2f_registration_token(token);
}) })
.catch(function(err) { .catch(function(err) {
MockDate.reset(); MockDate.reset();