diff --git a/browserid/lib/db.js b/browserid/lib/db.js index e3aa128dc1ee7256291ea487d15698150ac01ac8..a3ec73301f1e11f240ead55dd7642122c7d6194f 100644 --- a/browserid/lib/db.js +++ b/browserid/lib/db.js @@ -194,8 +194,7 @@ exports.gotVerificationSecret = function(secret, cb) { delete g_stagedEmails[o.email]; if (o.type === 'add_account') { exports.emailKnown(o.email, function(known) { - if (known) cb("email already exists!"); - else { + function createAccount() { executeTransaction([ [ "INSERT INTO users (password) VALUES(?)", [ o.pass ] ] , [ "INSERT INTO emails (user, address) VALUES(last_insert_rowid(),?)", [ o.email ] ], @@ -207,6 +206,21 @@ exports.gotVerificationSecret = function(secret, cb) { else cb(); }); } + + // if this email address is known and a user has completed a re-verification of this email + // address, remove the email from the old account that it was associated with, and then + // create a brand new account with only this email. + // NOTE: this might be sub-optimal, but it's a dead simple approach that mitigates many attacks + // and gives us reasonable behavior (without explicitly supporting) in the face of shared email + // addresses. + if (known) { + exports.removeEmail(o.email, o.email, function (err) { + if (err) cb(err); + else createAccount(); + }); + } else { + createAccount(); + } }); } else if (o.type === 'add_email') { exports.addEmailToAccount(o.existing_email, o.email, o.pubkey, cb); @@ -305,6 +319,7 @@ exports.removeEmail = function(authenticated_email, email, cb) { }); }); }; + exports.cancelAccount = function(authenticated_email, cb) { emailToUserID(authenticated_email, function(user_id) { executeTransaction([ diff --git a/browserid/tests/forgotten-email-test.js b/browserid/tests/forgotten-email-test.js index d54a76e0eae11aecc487604ac3c135e06857187a..ebecf4ae689281a84fe034ab6db9d66e5be8fecb 100755 --- a/browserid/tests/forgotten-email-test.js +++ b/browserid/tests/forgotten-email-test.js @@ -278,10 +278,10 @@ suite.addBatch({ assert.strictEqual(JSON.parse(r.body), true); } }, - "second email, first pass bad": { + "second email, first pass good": { topic: wsapi.get('/wsapi/authenticate_user', { email: 'second@fakeemail.com', pass: 'firstfakepass' }), - "shouldn't work": function(r, err) { - assert.strictEqual(JSON.parse(r.body), false); + "should work": function(r, err) { + assert.strictEqual(JSON.parse(r.body), true); } }, "second email, second pass bad": {