diff --git a/browserid/static/dialog/controllers/addemail_controller.js b/browserid/static/dialog/controllers/addemail_controller.js
index 50381bc608c56b0c0021f5cc98e75e2c06bde99d..2a28c7afdc57d70a8b91d411a613e0307ba72556 100644
--- a/browserid/static/dialog/controllers/addemail_controller.js
+++ b/browserid/static/dialog/controllers/addemail_controller.js
@@ -1,5 +1,5 @@
-/*jshint brgwser:true, jQuery: true, forin: true, laxbreak:true */                                             
-/*global Channel:true, CryptoStubs:true, alert:true, errorOut:true, setupChannel:true, getEmails:true, clearEmails: true, console: true, _: true, pollTimeout: true, addEmail: true, removeEmail:true, BrowserIDNetwork: true, BrowserIDWait:true, BrowserIDErrors: true, PageController: true */ 
+/*jshint browser:true, jQuery: true, forin: true, laxbreak:true */                                             
+/*global BrowserIDIdentities: true, BrowserIDNetwork: true, BrowserIDWait:true, BrowserIDErrors: true, PageController: true */ 
 /* ***** BEGIN LICENSE BLOCK *****
  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  *
@@ -43,7 +43,7 @@
         bodyTemplate: "addemail.ejs",
         bodyVars: {
           sitename: BrowserIDNetwork.origin,
-          identities: getEmails()
+          identities: BrowserIDIdentities.getStoredIdentities()
         },
         footerTemplate: "bottom-addemail.ejs",
         footerVars: {}
diff --git a/browserid/static/dialog/controllers/authenticate_controller.js b/browserid/static/dialog/controllers/authenticate_controller.js
index edd353dcccbf23b398e4f2f3ad877c59f686f7e7..1c4a9385ae3dc9a4b4e9f1bd2ac9430e219e59fe 100644
--- a/browserid/static/dialog/controllers/authenticate_controller.js
+++ b/browserid/static/dialog/controllers/authenticate_controller.js
@@ -1,5 +1,5 @@
-/*jshint brgwser:true, jQuery: true, forin: true, laxbreak:true */
-/*global Channel:true, CryptoStubs:true, alert:true, errorOut:true, setupChannel:true, getEmails:true, clearEmails: true, console: true, _: true, pollTimeout: true, addEmail: true, removeEmail:true, BrowserIDNetwork: true, BrowserIDWait:true, BrowserIDErrors: true, PageController: true */
+/*jshint browser:true, jQuery: true, forin: true, laxbreak:true */
+/*global BrowserIDIdentities: true, BrowserIDNetwork: true, BrowserIDWait:true, BrowserIDErrors: true, PageController: true */
 /* ***** BEGIN LICENSE BLOCK *****
  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  *
diff --git a/browserid/static/dialog/controllers/checkregistration_controller.js b/browserid/static/dialog/controllers/checkregistration_controller.js
index 99842208c510da0df12f54b18ec092dc2ac0be61..99bbb405f6b6e9fa4ce475517d1374f6bfecd4d9 100644
--- a/browserid/static/dialog/controllers/checkregistration_controller.js
+++ b/browserid/static/dialog/controllers/checkregistration_controller.js
@@ -1,5 +1,5 @@
-/*jshint brgwser:true, jQuery: true, forin: true, laxbreak:true */                                             
-/*global Channel:true, CryptoStubs:true, alert:true, errorOut:true, setupChannel:true, getEmails:true, clearEmails: true, console: true, _: true, pollTimeout: true, addEmail: true, removeEmail:true, BrowserIDNetwork: true, BrowserIDWait:true, BrowserIDErrors: true, PageController: true */ 
+/*jshint browser:true, jQuery: true, forin: true, laxbreak:true */                                             
+/*global BrowserIDNetwork: true, BrowserIDWait:true, BrowserIDErrors: true, PageController: true */ 
 /* ***** BEGIN LICENSE BLOCK *****
  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  *
diff --git a/browserid/static/dialog/controllers/chooseemail_controller.js b/browserid/static/dialog/controllers/chooseemail_controller.js
index 873ffcee1ef5c5d967d07b04e23ac8b14d48e726..94a0c2cdfbc1bdb4d6d5dd44e3e6beec9f19ff89 100644
--- a/browserid/static/dialog/controllers/chooseemail_controller.js
+++ b/browserid/static/dialog/controllers/chooseemail_controller.js
@@ -1,5 +1,5 @@
-/*jshint brgwser:true, jQuery: true, forin: true, laxbreak:true */                                             
-/*global Channel:true, CryptoStubs:true, alert:true, errorOut:true, setupChannel:true, getEmails:true, clearEmails: true, console: true, _: true, pollTimeout: true, addEmail: true, removeEmail:true, BrowserIDNetwork: true, BrowserIDWait:true, BrowserIDErrors: true, PageController: true */ 
+/*jshint browser:true, jQuery: true, forin: true, laxbreak:true */                                             
+/*global BrowserIDNetwork: true, BrowserIDWait:true, BrowserIDErrors: true, PageController: true */ 
 /* ***** BEGIN LICENSE BLOCK *****
  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  *
@@ -43,7 +43,7 @@
         bodyTemplate: "signin.ejs",
         bodyVars: {
           sitename: BrowserIDNetwork.origin,
-          identities: getEmails()
+          identities: BrowserIDIdentities.getStoredIdentities()
         },
         footerTemplate: "bottom-pickemail.ejs",
         footerVars: {}
diff --git a/browserid/static/dialog/controllers/createaccount_controller.js b/browserid/static/dialog/controllers/createaccount_controller.js
index d235b80eb5d12e72d2d0285b3bb7bc6be53b86ee..93830e61bb478afae8160e272ff25d0857eeafa7 100644
--- a/browserid/static/dialog/controllers/createaccount_controller.js
+++ b/browserid/static/dialog/controllers/createaccount_controller.js
@@ -1,5 +1,5 @@
-/*jshint brgwser:true, jQuery: true, forin: true, laxbreak:true */                                             
-/*global Channel:true, CryptoStubs:true, alert:true, errorOut:true, setupChannel:true, getEmails:true, clearEmails: true, console: true, _: true, pollTimeout: true, addEmail: true, removeEmail:true, BrowserIDNetwork: true, BrowserIDWait:true, BrowserIDErrors: true, PageController: true */ 
+/*jshint browser:true, jQuery: true, forin: true, laxbreak:true */                                             
+/*global BrowserIDIdentities: true, BrowserIDNetwork: true, BrowserIDWait:true, BrowserIDErrors: true, PageController: true */ 
 /* ***** BEGIN LICENSE BLOCK *****
  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  *
diff --git a/browserid/static/dialog/controllers/dialog_controller.js b/browserid/static/dialog/controllers/dialog_controller.js
index 377b128c42dfad6a836670ac7135183505b5f4bb..5ec13480d0ebe97adb676779a311f5206a3b780e 100644
--- a/browserid/static/dialog/controllers/dialog_controller.js
+++ b/browserid/static/dialog/controllers/dialog_controller.js
@@ -1,5 +1,5 @@
-/*jshint brgwser:true, jQuery: true, forin: true, laxbreak:true */                                             
-/*global Channel:true, CryptoStubs:true, alert:true, errorOut:true, setupChannel:true, getEmails:true, clearEmails: true, console: true, _: true, pollTimeout: true, addEmail: true, removeEmail:true, BrowserIDNetwork: true, BrowserIDWait:true, BrowserIDErrors: true, PageController: true, OpenAjax: true */ 
+/*jshint browser:true, jQuery: true, forin: true, laxbreak:true */                                             
+/*global setupChannel:true, BrowserIDIdentities: true, BrowserIDNetwork: true, BrowserIDWait:true, BrowserIDErrors: true, PageController: true, OpenAjax: true */ 
 /* ***** BEGIN LICENSE BLOCK *****
  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  *
@@ -190,8 +190,7 @@ PageController.extend("Dialog", {}, {
     },
 
     doNotMe: function() {
-      clearEmails();
-      BrowserIDNetwork.logout(this.doAuthenticate.bind(this));
+      BrowserIDIdentities.logoutUser(this.doAuthenticate.bind(this));
     },
 
     syncIdentities: function() {
diff --git a/browserid/static/dialog/controllers/forgotpassword_controller.js b/browserid/static/dialog/controllers/forgotpassword_controller.js
index 33edb062c38dd0c18c84f1a2a857c4914669d192..36ab964399cc26deee336085d95d877eb5e1ce06 100644
--- a/browserid/static/dialog/controllers/forgotpassword_controller.js
+++ b/browserid/static/dialog/controllers/forgotpassword_controller.js
@@ -1,5 +1,5 @@
-/*jshint brgwser:true, jQuery: true, forin: true, laxbreak:true */                                             
-/*global Channel:true, CryptoStubs:true, alert:true, errorOut:true, setupChannel:true, getEmails:true, clearEmails: true, console: true, _: true, pollTimeout: true, addEmail: true, removeEmail:true, BrowserIDNetwork: true, BrowserIDWait:true, BrowserIDErrors: true, PageController: true */ 
+/*jshint browser:true, jQuery: true, forin: true, laxbreak:true */                                             
+/*global BrowserIDIdentities: true, BrowserIDWait:true, BrowserIDErrors: true, PageController: true */ 
 /* ***** BEGIN LICENSE BLOCK *****
  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  *
diff --git a/browserid/static/dialog/controllers/page_controller.js b/browserid/static/dialog/controllers/page_controller.js
index c52a14d5fa8e894fc6d04b4b6db8e125b3ded54a..ae63d718205dc0a41b322779740c894fe9f81261 100644
--- a/browserid/static/dialog/controllers/page_controller.js
+++ b/browserid/static/dialog/controllers/page_controller.js
@@ -1,5 +1,4 @@
-/*jshint brgwser:true, jQuery: true, forin: true, laxbreak:true */                                             
-/*global Channel:true, CryptoStubs:true, alert:true, errorOut:true, setupChannel:true, getEmails:true, clearEmails: true, console: true, _: true, pollTimeout: true, addEmail: true, removeEmail:true, BrowserIDNetwork: true, BrowserIDWait:true, BrowserIDErrors: true */ 
+/*jshint browser:true, jQuery: true, forin: true, laxbreak:true */                                             
 /* ***** BEGIN LICENSE BLOCK *****
  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  *
diff --git a/browserid/static/dialog/register_iframe.js b/browserid/static/dialog/register_iframe.js
index c72923bd10ed0e88fb49acc080a512612c1714ed..e1e89397d7fc1275f212d5f860d474f21069260e 100644
--- a/browserid/static/dialog/register_iframe.js
+++ b/browserid/static/dialog/register_iframe.js
@@ -59,7 +59,7 @@ var jwk = require("./jwk"),
     var keypair = jwk.KeyPair.generate(vep.params.algorithm, 64);
 
     // save it in a special place for now
-    storeTemporaryKeypair(keypair);
+    BrowserIDStorage.storeTemporaryKeypair(keypair);
     
     // serialize and return
     return keypair.publicKey.serialize();
@@ -67,7 +67,7 @@ var jwk = require("./jwk"),
 
   // add the cert 
   chan.bind("registerVerifiedEmailCertificate", function(trans, args) {
-    var keypair = retrieveTemporaryKeypair();
+    var keypair = BrowserIDStorage.retrieveTemporaryKeypair();
 
     // parse the cert
     var raw_cert = args.cert;
@@ -91,7 +91,7 @@ var jwk = require("./jwk"),
       isPrimary: true
     };
 
-    addEmail(email, new_email_obj);
+    BrowserIDStorage.addEmail(email, new_email_obj);
   });
   */
 
diff --git a/browserid/static/dialog/resources/browserid-identities.js b/browserid/static/dialog/resources/browserid-identities.js
index bba9f48ceac5444188a75bd6b24ab10e1730e60b..b2b4d6acfac4b7b9742337afd118a7dfe483b945 100644
--- a/browserid/static/dialog/resources/browserid-identities.js
+++ b/browserid/static/dialog/resources/browserid-identities.js
@@ -1,5 +1,5 @@
 /*jshint browsers:true, forin: true, laxbreak: true */
-/*global _: true, network: true, addEmail: true, removeEmail: true, clearEmails: true, getEmails: true, CryptoStubs: true */
+/*global _: true, BrowserIDStorage: true, BrowserIDNetwork: true */
 /* ***** BEGIN LICENSE BLOCK *****
  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  *
@@ -36,8 +36,12 @@
  * ***** END LICENSE BLOCK ***** */
 
 var BrowserIDIdentities = (function() {
-  var jwk, jwt, vep, jwcert;
-  
+  "use strict";
+
+  var jwk, jwt, vep, jwcert,
+      network = BrowserIDNetwork, 
+      storage = BrowserIDStorage;
+    
   function prepareDeps() {
     if (!jwk) {
       jwk= require("./jwk");
@@ -47,9 +51,8 @@ var BrowserIDIdentities = (function() {
     }
   }
 
-  "use strict";
   function getIssuedIdentities() {
-      var emails = getEmails();
+      var emails = storage.getEmails();
       var issued_identities = {};
       prepareDeps();
       _(emails).each(function(email_obj, email_address) {
@@ -81,13 +84,11 @@ var BrowserIDIdentities = (function() {
     // first remove idenitites that the server doesn't know about
     if (unknown_emails) {
       _(unknown_emails).each(function(email_address) {
-        removeEmail(email_address);
+        storage.removeEmail(email_address);
       });
     }
   }
 
-  var network = BrowserIDNetwork;
-
   var Identities = {
     /**
      * Set the interface to use for networking.  Used for unit testing.
@@ -133,7 +134,7 @@ var BrowserIDIdentities = (function() {
         _.each(emails_to_remove, function(email) {
           // if it's not a primary
           if (!issued_identities[email].isPrimary)
-            removeEmail(email);
+            storage.removeEmail(email);
         });
 
         // keygen for new emails
@@ -339,7 +340,7 @@ var BrowserIDIdentities = (function() {
         cert: cert
       };
 
-      addEmail(email, new_email_obj);
+      storage.addEmail(email, new_email_obj);
 
       if (onSuccess) {
         onSuccess();
@@ -355,7 +356,7 @@ var BrowserIDIdentities = (function() {
      */
     removeIdentity: function(email, onSuccess, onFailure) {
       network.removeEmail(email, function() {
-        removeEmail(email);
+        storage.removeEmail(email);
         if (onSuccess) {
           onSuccess();
         }
@@ -393,7 +394,7 @@ var BrowserIDIdentities = (function() {
      * @return {object} identities.
      */
     getStoredIdentities: function() {
-      return getEmails();
+      return storage.getEmails();
     },
 
     /**
@@ -401,7 +402,40 @@ var BrowserIDIdentities = (function() {
      * @method clearStoredIdentities
      */
     clearStoredIdentities: function() {
-      clearEmails();
+      storage.clearEmails();
+    },
+
+
+    /**
+     * Cancel the current user's account.  Remove last traces of their 
+     * identity.
+     * @method cancelUser
+     * @param {function} [onSuccess] - Called whenever complete.
+     * @param {function} [onFailure] - called on failure.
+     */
+    cancelUser: function(onSuccess, onFailure) {
+      network.cancelUser(function() {
+        storage.clearEmails();
+        if (onSuccess) {
+          onSuccess();
+        }
+      });
+
+    },
+
+    /**
+     * Log the current user out.
+     * @method logoutUser
+     * @param {function} [onSuccess] - Called whenever complete.
+     * @param {function} [onFailure] - called on failure.
+     */
+    logoutUser: function(onSuccess, onFailure) {
+      network.logout(function() {
+        storage.clearEmails();
+        if (onSuccess) {
+          onSuccess();
+        }
+      });
     }
 
 
diff --git a/browserid/static/dialog/resources/browserid-network.js b/browserid/static/dialog/resources/browserid-network.js
index f363220e1e2d33d03898f5a90d118bfed6b2910e..059c529e1ee77781314151b0fdfe02104865c662 100644
--- a/browserid/static/dialog/resources/browserid-network.js
+++ b/browserid/static/dialog/resources/browserid-network.js
@@ -1,5 +1,5 @@
 /*jshint browsers:true, forin: true, laxbreak: true */
-/*global _: true, console: true, addEmail: true, removeEmail: true, clearEmails: true, CryptoStubs: true */
+/*global BrowserIDStorage: true */
 /* ***** BEGIN LICENSE BLOCK *****
  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  *
@@ -37,7 +37,7 @@
 var BrowserIDNetwork = (function() {
   "use strict";
 
-  var csrf_token = undefined;
+  var csrf_token;
 
   function withCSRF(cb) {
     if (csrf_token) setTimeout(cb, 0);
@@ -82,7 +82,7 @@ var BrowserIDNetwork = (function() {
             csrf: csrf_token
           },
           success: function(status, textStatus, jqXHR) {
-            if(onSuccess) {
+            if (onSuccess) {
               var authenticated = JSON.parse(status);
               onSuccess(authenticated);
             }
@@ -123,7 +123,7 @@ var BrowserIDNetwork = (function() {
         }, function() {
           csrf_token = undefined;
           withCSRF(function() {
-            if(onSuccess) {
+            if (onSuccess) {
               onSuccess();
             }
           });
@@ -191,10 +191,7 @@ var BrowserIDNetwork = (function() {
     cancelUser: function(onSuccess) {
       withCSRF(function() {
         $.post("/wsapi/account_cancel", {"csrf": csrf_token}, function(result) {
-          // XXX move this out of here, we now have 
-          // BrowserIDIdentities.clearStoredIdentities
-          clearEmails();
-          if(onSuccess) {
+          if (onSuccess) {
             onSuccess();
           }
         });
@@ -237,7 +234,7 @@ var BrowserIDNetwork = (function() {
       $.ajax({
         url: '/wsapi/have_email?email=' + encodeURIComponent(email),
         success: function(data, textStatus, xhr) {
-          if(onSuccess) {
+          if (onSuccess) {
             var success = !JSON.parse(data);
             onSuccess(success);
           }
@@ -278,7 +275,7 @@ var BrowserIDNetwork = (function() {
       $.ajax({
           url: '/wsapi/registration_status',
           success: function(status, textStatus, jqXHR) {
-            if(onSuccess) {
+            if (onSuccess) {
               onSuccess(status);
             }
           },
diff --git a/browserid/static/dialog/resources/channel.js b/browserid/static/dialog/resources/channel.js
index 7de7a87351268f2beb782310dd376b62e3d7e2a9..b926fd948830f397ef3c24ba878bf546a94af246 100644
--- a/browserid/static/dialog/resources/channel.js
+++ b/browserid/static/dialog/resources/channel.js
@@ -1,3 +1,4 @@
+/*jshint browsers:true, forin: true, laxbreak: true */
 /*global alert:true, setupNativeChannel:true, setupIFrameChannel:true*/
 /* ***** BEGIN LICENSE BLOCK *****
  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
@@ -51,20 +52,6 @@
 
 
 (function() {
-  // Read a page's GET URL variables and return them as an associative array.
-  /*
-  function getUrlVars() {
-    var hashes = {},
-        hash,
-        pairs = window.location.href.slice(window.location.href.indexOf('#') + 1).split('&');
-
-    for(var i = 0, pair; pair=pairs[i]; ++i) {
-      hash = pair.split('=');
-      hashes[hash[0]] = hash[1];
-    }
-    return hashes;
-  }
-*/
   function getRelayWindow() {
     var frameWindow = window.opener.frames['browserid_relay'];
     return frameWindow;
@@ -114,9 +101,6 @@
   };
 
   var setupIFrameChannel = function(controller) {
-    //var hash = getUrlVars();
-    //var origin = hash['host'];
-
     // TODO - Add a check for whether the dialog was opened by another window
     // (has window.opener) as well as whether the relay function exists.
     // If these conditions are not met, then print an appropriate message.
diff --git a/browserid/static/dialog/resources/crypto-api.js b/browserid/static/dialog/resources/crypto-api.js
index 76b39ff1e86f7508060c4b07b791436a951f1d5e..2f0ac365d8accf3af87a6b25c5db6f193a2d95f1 100644
--- a/browserid/static/dialog/resources/crypto-api.js
+++ b/browserid/static/dialog/resources/crypto-api.js
@@ -1,3 +1,5 @@
+/*jshint browsers:true, forin: true, laxbreak: true */
+/*global RSAKey: true, jwt: true */
 /* ***** BEGIN LICENSE BLOCK *****
  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  *
diff --git a/browserid/static/dialog/resources/storage.js b/browserid/static/dialog/resources/storage.js
index e27f80da7e2701ee03c6790905d84d5bd15cdb40..5664c8b34e2cf2b6b5a404135031fe96d419a46d 100644
--- a/browserid/static/dialog/resources/storage.js
+++ b/browserid/static/dialog/resources/storage.js
@@ -33,20 +33,28 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
-(function() {
+var BrowserIDStorage = (function() {
   
   var jwk;
   
   function prepareDeps() {
-   if (!jwk) {
-     jwk = require("./jwk");
-   }
+    if (!jwk) {
+      jwk = require("./jwk");
+    }
+  }
+
+  function storeEmails(emails) {
+    window.localStorage.emails = JSON.stringify(emails);
+  }
+
+  function clearEmails() {
+    storeEmails({});
   }
 
-  window.getEmails = function() {
+  function getEmails() {
     try {
       var emails = JSON.parse(window.localStorage.emails);
-      if (emails != null)
+      if (emails !== null)
         return emails;
     } catch(e) {
     }
@@ -54,36 +62,28 @@
     // if we had a problem parsing or the emails are null
     clearEmails();
     return {};
-  };
-
-  var _storeEmails = function(emails) {
-    window.localStorage.emails = JSON.stringify(emails);
-  };
+  }
 
-  window.addEmail = function(email, obj) {
+  function addEmail(email, obj) {
     var emails = getEmails();
     emails[email] = obj;
-    _storeEmails(emails);
-  };
+    storeEmails(emails);
+  }
 
-  window.removeEmail = function(email) {
+  function removeEmail(email) {
     var emails = getEmails();
     delete emails[email];
-    _storeEmails(emails);
-  };
-
-  window.clearEmails = function() {
-    _storeEmails({});
-  };
+    storeEmails(emails);
+  }
 
-  window.storeTemporaryKeypair = function(keypair) {
+  function storeTemporaryKeypair(keypair) {
     window.localStorage.tempKeypair = JSON.stringify({
       publicKey: keypair.publicKey.toSimpleObject(),
       secretKey: keypair.secretKey.toSimpleObject()
     });
-  };
+  }
 
-  window.retrieveTemporaryKeypair = function() {
+  function retrieveTemporaryKeypair() {
     var raw_kp = JSON.parse(window.localStorage.tempKeypair);
     window.localStorage.tempKeypair = null;
     if (raw_kp) {
@@ -95,5 +95,14 @@
     } else {
       return null;
     }
+  }
+
+  return {
+    getEmails: getEmails,
+    addEmail: addEmail,
+    removeEmail: removeEmail,
+    clearEmails: clearEmails,
+    storeTemporaryKeypair: storeTemporaryKeypair,
+    retrieveTemporaryKeypair: retrieveTemporaryKeypair
   };
 }());
diff --git a/browserid/static/dialog/test/qunit/browserid-identities_functional_test.js b/browserid/static/dialog/test/qunit/browserid-identities_functional_test.js
index 0511572abf8276b972435686d6a7825faa69d5e0..4148b6b8a4022d99722af8a1efe7922e7c0c4101 100644
--- a/browserid/static/dialog/test/qunit/browserid-identities_functional_test.js
+++ b/browserid/static/dialog/test/qunit/browserid-identities_functional_test.js
@@ -1,5 +1,5 @@
 /*jshint browsers:true, forin: true, laxbreak: true */
-/*global steal: true, test: true, start: true, stop: true, module: true, ok: true, equal: true, clearEmails: true, BrowserIDNetwork: true , BrowserIDIdentities: true */
+/*global steal: true, test: true, start: true, stop: true, module: true, ok: true, equal: true, BrowserIDStorage.clearEmails: true, BrowserIDNetwork: true , BrowserIDIdentities: true */
 /* ***** BEGIN LICENSE BLOCK *****
  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  *
@@ -85,7 +85,7 @@ steal.plugins("jquery", "funcunit/qunit").then("/dialog/resources/browserid-iden
   });
 
   test("authenticateAndSync", function() {
-    clearEmails();
+    BrowserIDStorage.clearEmails();
     BrowserIDIdentities.authenticateAndSync("testuser@testuser.com", "testuser", function() {
     }, function() {
       var identities = BrowserIDIdentities.getStoredIdentities();
@@ -99,7 +99,7 @@ steal.plugins("jquery", "funcunit/qunit").then("/dialog/resources/browserid-iden
 
   test("checkAuthenticationAndSync", function() {
     BrowserIDNetwork.authenticate("testuser@testuser.com", "testuser", function() {
-      clearEmails();
+      BrowserIDStorage.clearEmails();
       BrowserIDIdentities.checkAuthenticationAndSync(function() {
         var identities = BrowserIDIdentities.getStoredIdentities();
         ok("testuser@testuser.com" in identities, "checkAuthenticationAndSync syncs email addresses");
@@ -166,7 +166,7 @@ steal.plugins("jquery", "funcunit/qunit").then("/dialog/resources/browserid-iden
   });
   */
   test("syncIdentities with no identities", function() {
-    clearEmails();
+    BrowserIDStorage.clearEmails();
     BrowserIDNetwork.authenticate("testuser@testuser.com", "testuser", function() {
       BrowserIDIdentities.syncIdentities(function onSuccess() {
         ok(true, "we have synced identities");
@@ -201,7 +201,7 @@ steal.plugins("jquery", "funcunit/qunit").then("/dialog/resources/browserid-iden
 
   /*
   test("syncIdentity on non-confirmed email address", function() {
-    clearEmails();
+    BrowserIDStorage.clearEmails();
     BrowserIDNetwork.authenticate("testuser@testuser.com", "testuser", function() {
       BrowserIDIdentities.removeIdentity("testemail@testemail.com", function() {
         BrowserIDIdentities.syncIdentity("testemail@testemail.com", "issuer", function(keypair) {
@@ -227,7 +227,7 @@ steal.plugins("jquery", "funcunit/qunit").then("/dialog/resources/browserid-iden
       // First, force removal that way we know it is not part of our list.
       BrowserIDIdentities.removeIdentity("unvalidated@unvalidated.com", function() {
 
-        clearEmails();
+        BrowserIDStorage.clearEmails();
         BrowserIDIdentities.syncIdentities(function onSuccess() {
 
           var identities = BrowserIDIdentities.getStoredIdentities();
@@ -239,7 +239,7 @@ steal.plugins("jquery", "funcunit/qunit").then("/dialog/resources/browserid-iden
           BrowserIDIdentities.syncIdentity("unvalidated@unvalidated.com", "issuer", function(keypair) {
             // Clear all the local emails, then refetch the list from the server
             // just to be sure we are seeing what the server sees.
-            clearEmails();
+            BrowserIDStorage.clearEmails();
             BrowserIDIdentities.syncIdentities(function onSuccess() {
 
               var identities = BrowserIDIdentities.getStoredIdentities();
diff --git a/browserid/static/dialog/test/qunit/browserid-identities_unit_test.js b/browserid/static/dialog/test/qunit/browserid-identities_unit_test.js
index 61c1623c927215c1a53ef1016eb5c51e3bc07afd..660ff67a75c0a027c57c565126e5249d21ced899 100644
--- a/browserid/static/dialog/test/qunit/browserid-identities_unit_test.js
+++ b/browserid/static/dialog/test/qunit/browserid-identities_unit_test.js
@@ -1,5 +1,5 @@
 /*jshint browsers:true, forin: true, laxbreak: true */
-/*global steal: true, test: true, start: true, stop: true, module: true, ok: true, equal: true, clearEmails: true, BrowserIDNetwork: true , BrowserIDIdentities: true */
+/*global steal: true, test: true, start: true, stop: true, module: true, ok: true, equal: true, BrowserIDStorage:true, BrowserIDNetwork: true , BrowserIDIdentities: true */
 /* ***** BEGIN LICENSE BLOCK *****
  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  *
@@ -102,6 +102,15 @@ steal.plugins("jquery", "funcunit/qunit").then("/dialog/resources/browserid-iden
       else {
         onFailure();
       }
+    },
+
+    cancelUser: function(onSuccess) {
+      onSuccess();
+    },
+
+    logout: function(onSuccess) {
+      credentialsValid = false;
+      onSuccess();
     }
   };
 
@@ -254,7 +263,7 @@ steal.plugins("jquery", "funcunit/qunit").then("/dialog/resources/browserid-iden
   test("authenticateAndSync with valid authentication", function() {
     credentialsValid = true;
     keyRefresh = ["testuser@testuser.com"]; 
-    clearEmails();
+    BrowserIDStorage.clearEmails();
 
     BrowserIDIdentities.authenticateAndSync("testuser@testuser.com", "testuser", function() {
     }, function(authenticated) {
@@ -272,7 +281,7 @@ steal.plugins("jquery", "funcunit/qunit").then("/dialog/resources/browserid-iden
   test("authenticateAndSync with invalid authentication", function() {
     credentialsValid = false;
     keyRefresh = ["testuser@testuser.com"]; 
-    clearEmails();
+    BrowserIDStorage.clearEmails();
 
     BrowserIDIdentities.authenticateAndSync("testuser@testuser.com", "testuser", function() {
     }, function(authenticated) {
@@ -303,7 +312,7 @@ steal.plugins("jquery", "funcunit/qunit").then("/dialog/resources/browserid-iden
 
 
   test("syncIdentity with successful sync", function() {
-    clearEmails();
+    BrowserIDStorage.clearEmails();
 
     syncValid = true;
     BrowserIDIdentities.syncIdentity("testemail@testemail.com", function(keypair) {
@@ -318,7 +327,7 @@ steal.plugins("jquery", "funcunit/qunit").then("/dialog/resources/browserid-iden
 
 
   test("syncIdentity with invalid sync", function() {
-    clearEmails();
+    BrowserIDStorage.clearEmails();
 
     syncValid = false;
     BrowserIDIdentities.syncIdentity("testemail@testemail.com", function(keypair) {
@@ -350,7 +359,7 @@ steal.plugins("jquery", "funcunit/qunit").then("/dialog/resources/browserid-iden
 
 
   test("removeIdentity that is added", function() {
-    addEmail("testemail@testemail.com", {pub: "pub", priv: "priv"});
+    BrowserIDStorage.addEmail("testemail@testemail.com", {pub: "pub", priv: "priv"});
 
     BrowserIDIdentities.removeIdentity("testemail@testemail.com", function() {
       var identities = BrowserIDIdentities.getStoredIdentities();
@@ -364,7 +373,7 @@ steal.plugins("jquery", "funcunit/qunit").then("/dialog/resources/browserid-iden
 
 
   test("removeIdentity that is not added", function() {
-    clearEmails();
+    BrowserIDStorage.clearEmails();
 
     BrowserIDIdentities.removeIdentity("testemail@testemail.com", function() {
       var identities = BrowserIDIdentities.getStoredIdentities();
@@ -378,7 +387,7 @@ steal.plugins("jquery", "funcunit/qunit").then("/dialog/resources/browserid-iden
 
 
   test("syncIdentities with no pre-loaded identities and no identities to add", function() {
-    clearEmails();
+    BrowserIDStorage.clearEmails();
     userEmails = {};
 
     BrowserIDIdentities.syncIdentities(function onSuccess() {
@@ -392,7 +401,7 @@ steal.plugins("jquery", "funcunit/qunit").then("/dialog/resources/browserid-iden
   });
 
   test("syncIdentities with no pre-loaded identities and identities to add", function() {
-    clearEmails();
+    BrowserIDStorage.clearEmails();
     userEmails = {"testuser@testuser.com": {}};
 
     BrowserIDIdentities.syncIdentities(function onSuccess() {
@@ -406,9 +415,9 @@ steal.plugins("jquery", "funcunit/qunit").then("/dialog/resources/browserid-iden
   });
 
   test("syncIdentities with identities preloaded and none to add", function() {
-    clearEmails();
+    BrowserIDStorage.clearEmails();
     userEmails = {"testuser@testuser.com": {}};
-    addEmail("testuser@testuser.com", {});
+    BrowserIDStorage.addEmail("testuser@testuser.com", {});
 
     BrowserIDIdentities.syncIdentities(function onSuccess() {
       var identities = BrowserIDIdentities.getStoredIdentities();
@@ -422,8 +431,8 @@ steal.plugins("jquery", "funcunit/qunit").then("/dialog/resources/browserid-iden
 
 
   test("syncIdentities with identities preloaded and one to add", function() {
-    clearEmails();
-    addEmail("testuser@testuser.com", {pubkey: pubkey, cert: "1234"});
+    BrowserIDStorage.clearEmails();
+    BrowserIDStorage.addEmail("testuser@testuser.com", {pubkey: pubkey, cert: "1234"});
     userEmails = {"testuser@testuser.com": {pubkey: pubkey, cert: "1234"},
                   "testuser2@testuser.com": {pubkey: pubkey, cert: "1234"}};
 
@@ -440,9 +449,9 @@ steal.plugins("jquery", "funcunit/qunit").then("/dialog/resources/browserid-iden
 
 
   test("syncIdentities with identities preloaded and one to remove", function() {
-    clearEmails();
-    addEmail("testuser@testuser.com", {pub: pubkey, cert: "1234"});
-    addEmail("testuser2@testuser.com", {pub: pubkey, cert: "1234"});
+    BrowserIDStorage.clearEmails();
+    BrowserIDStorage.addEmail("testuser@testuser.com", {pub: pubkey, cert: "1234"});
+    BrowserIDStorage.addEmail("testuser2@testuser.com", {pub: pubkey, cert: "1234"});
     userEmails = {"testuser@testuser.com":  { pub: pubkey, cert: "1234"}};
     
     BrowserIDIdentities.syncIdentities(function onSuccess() {
@@ -458,7 +467,7 @@ steal.plugins("jquery", "funcunit/qunit").then("/dialog/resources/browserid-iden
 
 
   test("getIdentityAssertion with known email", function() {
-    clearEmails();
+    BrowserIDStorage.clearEmails();
     var keypair = jwk.KeyPair.generate("RS",64);
     BrowserIDIdentities.certifyIdentity("testuser@testuser.com", keypair, function() {
       BrowserIDIdentities.getIdentityAssertion("testuser@testuser.com", function onSuccess(assertion) {
@@ -472,7 +481,7 @@ steal.plugins("jquery", "funcunit/qunit").then("/dialog/resources/browserid-iden
 
 
   test("getIdentityAssertion with unknown email", function() {
-    clearEmails();
+    BrowserIDStorage.clearEmails();
     var keypair = jwk.KeyPair.generate("RS",64);
     BrowserIDIdentities.certifyIdentity("testuser@testuser.com", keypair, function() {
       BrowserIDIdentities.getIdentityAssertion("testuser2@testuser.com", function onSuccess(assertion) {
@@ -484,4 +493,36 @@ steal.plugins("jquery", "funcunit/qunit").then("/dialog/resources/browserid-iden
     stop();
   });
 
+  test("logoutUser", function(onSuccess) {
+    credentialsValid = true;
+    keyRefresh = ["testuser@testuser.com"]; 
+    BrowserIDStorage.clearEmails();
+
+    BrowserIDIdentities.authenticateAndSync("testuser@testuser.com", "testuser", function() {
+    }, function(authenticated) {
+      var storedIdentities = BrowserIDStorage.getEmails();
+      equal(_.size(storedIdentities), 1, "one identity");
+
+      BrowserIDIdentities.logoutUser(function() {
+        storedIdentities = BrowserIDStorage.getEmails();
+        equal(_.size(storedIdentities), 0, "All items have been removed on logout");
+
+        equal(credentialsValid, false, "credentials were invalidated in logout");
+        start();
+      });
+    });
+
+    stop();
+  });
+
+  test("cancelUser", function(onSuccess) {
+    BrowserIDIdentities.cancelUser(function() {
+      var storedIdentities = BrowserIDStorage.getEmails();
+      equal(_.size(storedIdentities), 0, "All items have been removed");
+      start();
+    });
+
+    stop();
+  });
+
 });
diff --git a/browserid/static/dialog/test/qunit/browserid-network_test.js b/browserid/static/dialog/test/qunit/browserid-network_test.js
index 96f9aa2bdec9218bcf08dfe87caa49b75c3efca6..df81ca10b0ca464b824c514050c9ecc66402a436 100644
--- a/browserid/static/dialog/test/qunit/browserid-network_test.js
+++ b/browserid/static/dialog/test/qunit/browserid-network_test.js
@@ -147,4 +147,8 @@ steal.plugins("jquery", "funcunit/qunit").then("/dialog/resources/browserid-netw
   test("syncEmails", function() {
     ok(true, "syncEmails");
   });
+
+  test("cancelUser", function() {
+    equal(typeof BrowserIDNetwork.cancelUser, "function", "what a ridiculously stupid test");
+  });
 });
diff --git a/browserid/static/js/browserid.js b/browserid/static/js/browserid.js
index d7bdecf0b6f2162b869f4ca0550224aef2e0426e..944ef1b58749b6b0a7c6fab61669ad0af0e7c2bd 100644
--- a/browserid/static/js/browserid.js
+++ b/browserid/static/js/browserid.js
@@ -1,4 +1,4 @@
-/*globals BrowserIDNetwork: true, BrowserIDIdentities: true, _: true, confirm: true, getEmails: true, display_saved_ids: true, displayEmails: true, removeEmail: true*/
+/*globals BrowserIDNetwork: true, BrowserIDIdentities: true, _: true, confirm: true, getEmails: true, display_saved_ids: true, removeEmail: true*/
 /* ***** BEGIN LICENSE BLOCK *****
  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  *
@@ -37,82 +37,75 @@
   "use strict";
 
   $(function() {
-    BrowserIDNetwork.checkAuth(function(authenticated) {
+    BrowserIDIdentities.checkAuthenticationAndSync(function onSuccess(authenticated) {
       if (authenticated) {
         $("body").addClass("authenticated");
-        if ($('#emailList').length) {
-          display_saved_ids();
-        }
       }
+    }, function onComplete(authenticated) {
+      if (authenticated && $('#emailList').length) {
+        display_saved_ids();
+      } 
     });
   });
 
   function display_saved_ids()
   {
-    var emails = {};
-    BrowserIDIdentities.syncIdentities(function() {
-      emails = getEmails();
-      displayEmails();
+    $('#cancellink').click(function() {
+      if (confirm('Are you sure you want to cancel your account?')) {
+        BrowserIDIdentities.cancelUser(function() {
+          document.location="/";
+        });
+      }
     });
 
+    $("#emailList").empty();
+    var emails = BrowserIDIdentities.getStoredIdentities();
+    _(emails).each(function(data, e) {
+      var block = $("<div>").addClass("emailblock");
+      var label = $("<div>").addClass("email").text(e);
+      var meta = $("<div>").addClass("meta");
 
-    function displayEmails() {
-      $('#cancellink').click(function() {
-        if (confirm('Are you sure you want to cancel your account?')) {
-          BrowserIDNetwork.cancelUser(function() {
-            document.location="/";
-          });
-        }
-      });
-
-      $("#emailList").empty();
-        _(emails).each(function(data, e) {
-          var block = $("<div>").addClass("emailblock");
-          var label = $("<div>").addClass("email").text(e);
-          var meta = $("<div>").addClass("meta");
-
-          var pub = $("<div class='keyblock'>").hide();
-          
-          var keyText = data.pub.value;
-          pub.text(keyText);
+      var pub = $("<div class='keyblock'>").hide();
+      
+      var keyText = data.pub.value;
+      pub.text(keyText);
 
-          var linkblock = $("<div>");
-          var puba = $("<a>").text("[show public key]");
-          // var priva = $("<a>").text("[show private key]");
-          puba.click(function() {pub.show();});
-          // priva.click(function() {priv.show()});
-          linkblock.append(puba);
-          // linkblock.append(" / ");
-          // linkblock.append(priva);
-          
-          var deauth = $("<button>").text("Forget this Email");
-          meta.append(deauth);
-          deauth.click(function(data) {
-            // If it is a primary, we do not have to go back to the server.
-            // XXX put this into the BrowserIDIdentities abstraction
-            if (data.isPrimary) {
-              removeEmail(e);
-              display_saved_ids();
-            }
-            else {
-              // remove email from server
-              BrowserIDNetwork.removeEmail(e, display_saved_ids);
-            }
-          }.bind(null, data));
-        
-          var d = new Date(data.created);
-          var datestamp = $("<div class='date'>").text("Signed in at " + d.toLocaleString());
+      var linkblock = $("<div>");
+      var puba = $("<a>").text("[show public key]");
+      // var priva = $("<a>").text("[show private key]");
+      puba.click(function() {pub.show();});
+      // priva.click(function() {priv.show()});
+      linkblock.append(puba);
+      // linkblock.append(" / ");
+      // linkblock.append(priva);
+      
+      var deauth = $("<button>").text("Forget this Email");
+      meta.append(deauth);
+      deauth.click(function(data) {
+        // If it is a primary, we do not have to go back to the server.
+        // XXX put this into the BrowserIDIdentities abstraction
+        if (data.isPrimary) {
+          BrowserIDStorage.removeEmail(e);
+          display_saved_ids();
+        }
+        else {
+          // remove email from server
+          BrowserIDIdentities.removeIdentity(e, display_saved_ids);
+        }
+      }.bind(null, data));
+    
+      var d = new Date(data.created);
+      var datestamp = $("<div class='date'>").text("Signed in at " + d.toLocaleString());
 
-          meta.append(datestamp);
-          meta.append(linkblock);
-                      
-          block.append(label);
-          block.append(meta);
-          // block.append(priv);
-          block.append(pub);
-          
-          $("#emailList").append(block);
-      });
-    }
+      meta.append(datestamp);
+      meta.append(linkblock);
+                  
+      block.append(label);
+      block.append(meta);
+      // block.append(priv);
+      block.append(pub);
+      
+      $("#emailList").append(block);
+    });
   }
 }());