diff --git a/src/lib/routes/u2f_register_handler.js b/src/lib/routes/u2f_register_handler.js index 3e99c8fa..a60c550c 100644 --- a/src/lib/routes/u2f_register_handler.js +++ b/src/lib/routes/u2f_register_handler.js @@ -26,8 +26,8 @@ function register_handler_get(req, res) { var user_data_store = req.app.get('user data store'); - logger.debug('U2F register_handler: verify token validity'); - user_data_store.verify_u2f_registration_token(registration_token) + logger.debug('U2F register_handler: verify token validity and consume it'); + user_data_store.consume_u2f_registration_token(registration_token) .then(function() { res.render('u2f_register'); }) diff --git a/src/lib/user_data_store.js b/src/lib/user_data_store.js index b44e00af..3a2c357f 100644 --- a/src/lib/user_data_store.js +++ b/src/lib/user_data_store.js @@ -51,9 +51,10 @@ UserDataStore.prototype.save_u2f_registration_token = function(userid, token, ma 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 = {}; query.token = token; + var that = this; return this._u2f_registration_tokens_collection.findOneAsync(query) .then(function(doc) { @@ -68,5 +69,8 @@ UserDataStore.prototype.verify_u2f_registration_token = function(token) { } return Promise.resolve(); + }) + .then(function() { + return that._u2f_registration_tokens_collection.removeAsync(query); }); } diff --git a/test/unitary/routes/test_u2f_register.js b/test/unitary/routes/test_u2f_register.js index d2c6b295..86a904dc 100644 --- a/test/unitary/routes/test_u2f_register.js +++ b/test/unitary/routes/test_u2f_register.js @@ -29,7 +29,7 @@ describe('test register handle', function() { 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.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); res = {}; @@ -107,7 +107,7 @@ describe('test register handle', function() { req.params = {}; 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); }); diff --git a/test/unitary/test_user_data_store.js b/test/unitary/test_user_data_store.js index f1b4750c..a30e7f11 100644 --- a/test/unitary/test_user_data_store.js +++ b/test/unitary/test_user_data_store.js @@ -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 = {}; options.inMemoryOnly = true; @@ -111,7 +111,7 @@ function test_u2f_registration_token() { data_store.save_u2f_registration_token(userid, token, max_age) .then(function(document) { - return data_store.verify_u2f_registration_token(token); + return data_store.consume_u2f_registration_token(token); }) .then(function() { 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() { var options = {}; options.inMemoryOnly = true; @@ -129,7 +152,7 @@ function test_u2f_registration_token() { var token = 'token'; - return data_store.verify_u2f_registration_token(token) + return data_store.consume_u2f_registration_token(token) .then(function(document) { return Promise.reject(); }) @@ -152,7 +175,7 @@ function test_u2f_registration_token() { data_store.save_u2f_registration_token(userid, token, max_age) .then(function() { MockDate.set('1/2/2000'); - return data_store.verify_u2f_registration_token(token); + return data_store.consume_u2f_registration_token(token); }) .catch(function(err) { MockDate.reset();