From 9bcb7e2d68331a1d7fbab6e0c06f88ddf1362d5d Mon Sep 17 00:00:00 2001
From: Lloyd Hilaiel <lloyd@hilaiel.com>
Date: Wed, 22 Jun 2011 16:53:54 -0600
Subject: [PATCH] handle verification of an email address that's already
 registered, all tests passing. wooo.

---
 browserid/lib/db.js                     | 19 +++++++++++++++++--
 browserid/tests/forgotten-email-test.js |  6 +++---
 2 files changed, 20 insertions(+), 5 deletions(-)

diff --git a/browserid/lib/db.js b/browserid/lib/db.js
index e3aa128dc..a3ec73301 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 d54a76e0e..ebecf4ae6 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": {
-- 
GitLab