diff --git a/authority/server/run.js b/authority/server/run.js
index 3d793f26de294b73aa3b6ac6b998d631841e7927..7a625172044dd5425f551f489a186877aa65a009 100644
--- a/authority/server/run.js
+++ b/authority/server/run.js
@@ -17,6 +17,8 @@ exports.handler = function(request, response, serveFile) {
 
   if (urlpath === '/sign_in') {
     serveFile(path.join(STATIC_DIR, "dialog", "index.html"), response);
+  } else if (urlpath === '/register_iframe') {
+    serveFile(path.join(STATIC_DIR, "dialog", "register_iframe.html"), response);
   } else if (/^\/wsapi\/\w+$/.test(urlpath)) {
     try {
       var method = path.basename(urlpath);
diff --git a/authority/static/dialog/register_iframe.html b/authority/static/dialog/register_iframe.html
new file mode 100644
index 0000000000000000000000000000000000000000..d9a2f96ebb6248046d5be286ec1c4362588c3931
--- /dev/null
+++ b/authority/static/dialog/register_iframe.html
@@ -0,0 +1,3 @@
+<script src="../dialog/jschannel.js"></script>
+<script src="../dialog/crypto-stubs.js"></script>
+<script src="../dialog/register_iframe.js"></script>
diff --git a/authority/static/dialog/register_iframe.js b/authority/static/dialog/register_iframe.js
new file mode 100644
index 0000000000000000000000000000000000000000..4d5c82c405d569d0eebb2629ef630b2f9c659822
--- /dev/null
+++ b/authority/static/dialog/register_iframe.js
@@ -0,0 +1,37 @@
+// this is the picker code!  it runs in the identity provider's domain, and
+// fiddles the dom expressed by picker.html
+(function() {
+  var chan = Channel.build(
+    {
+      window: window.parent,
+      origin: "*",
+      scope: "mozid"
+    });
+
+    function persistAddressAndKeyPair(email, keypair, issuer)
+    {
+        var emails = {};
+        if (window.localStorage.emails) {
+            emails = JSON.parse(window.localStorage.emails);
+        }
+
+        emails[email] = {
+            created: new Date(),
+            pub: keypair.pub,
+            priv: keypair.priv
+        };
+        if (issuer) {
+            emails[email].issuer = issuer;
+        }
+        window.localStorage.emails = JSON.stringify(emails);
+    }
+
+    chan.bind("registerVerifiedEmail", function(trans, args) {
+        // This is a primary registration - the persisted
+        // identity does not have an issuer because it 
+        // was directly asserted by the controlling domain.
+
+        var keypair = CryptoStubs.genKeyPair();
+        persistAddressAndKeyPair(args.email, keypair);
+    });
+})();
diff --git a/authority/static/include.js b/authority/static/include.js
index 96f96791de6bee0dc50cafb9259efde94d88dbae..c2de1f7009e36ec04835ae87dbb2cdcd327f6700 100644
--- a/authority/static/include.js
+++ b/authority/static/include.js
@@ -580,26 +580,26 @@ if (!navigator.id.getVerifiedEmail || navigator.id._getVerifiedEmailIsShimmed)
       }
     });
   };
-  
+
   navigator.id.registerVerifiedEmail = function(email, onsuccess, onerror) {
 
     // TODO: We really don't need to display a dialog for this.
     // I'm showing one just because it's easier than figuring out
     // how to embed an iframe in this case.
-  
+
     var doc = window.document;
     iframe = document.createElement("iframe");
     var ipServer = "http://authority.mozilla.org"
     iframe.style.display = "none";
     doc.body.appendChild(iframe);
-    iframe.src = ipServer + "/sign_in";
+    iframe.src = ipServer + "/register_iframe";
     if (chan) chan.destroy();
     chan = Channel.build({window: iframe.contentWindow, origin: ipServer, scope: "mozid"});
 
     function cleanup() {
       chan.destroy();
       chan = undefined;
-      w.close();
+      doc.body.removeChild(iframe);
     }
 
     chan.call({