diff --git a/resources/static/pages/signup.js b/resources/static/pages/signup.js
index 15c6f16830a2fa883a4ff7ef1b436d42ab848371..fda1de0e63a143bb7c367b017764099729a359b9 100644
--- a/resources/static/pages/signup.js
+++ b/resources/static/pages/signup.js
@@ -87,7 +87,7 @@ BrowserID.signUp = (function() {
               alert("shane!  provisioning was a success " + JSON.stringify(r));
             }, function(e) {
               // XXX: implement me
-              alert("shane!  provisioning was a failure: " + e);
+              alert("shane!  provisioning was a failure: " + JSON.stringify(e));
             });
           }
         }, pageHelpers.getFailure(errors.isEmailRegistered, oncomplete));
diff --git a/resources/static/shared/provisioning.js b/resources/static/shared/provisioning.js
index 388f9120b6b8f7727426838d1a4714b4edbb1b78..e241e915681070cb3fcdf160ac25daaff9ac8d27 100644
--- a/resources/static/shared/provisioning.js
+++ b/resources/static/shared/provisioning.js
@@ -38,10 +38,48 @@ BrowserID.Provisioning = (function() {
   "use strict";
 
   var Provisioning = function(args, successCB, failureCB) {
-    if (!args || !args.email || !args.url) throw "missing required arguments";
-    setTimeout(function() {
-      failureCB("not implemented");
-    }, 0);
+    function fail(code, msg) {
+      return setTimeout(function() {
+        failureCB({
+          code: code,
+          msg: msg
+        });
+      }, 0);
+    }
+
+    if (!failureCB) throw "missing required failure callback";
+
+    if (!args || !args.email || !args.url) {
+      return fail('internal', 'missing required arguments');
+    }
+
+    // extract the expected origin from the provisioning url
+    // (this may be a different domain than the email domain part, if the
+    //  domain delates authority)
+    try {
+      var origin = /^(https:\/\/[^/]+)\//.exec(args.url)[1];
+    } catch(e) { alert(e); }
+    if (!origin) {
+      return fail('internal', 'bad provisioning url, can\'t extract origin');
+    }
+
+    // time to attempt to provision the user.  we'll embed a hidden iframe from the
+    // primary
+    var iframe = document.createElement("iframe");
+    iframe.setAttribute('src', args.url);
+    iframe.style.display = "none";
+    document.body.appendChild(iframe);
+
+    var chan = Channel.build({
+      window: iframe.contentWindow,
+      origin: origin,
+      scope: "vep_prov"
+    });
+
+    // XXX: register handlers for different messages that the provisioning iframe will send
+
+
+    // XXX: set a timeout for the amount of time that provisioning is allowed to take
   };
 
   return Provisioning;
diff --git a/resources/views/dialog_layout.ejs b/resources/views/dialog_layout.ejs
index 3228246bf158f6f047d948bf87111cc3d943384e..fb7412ef13a561e9eefa87e4dd3cc1f29e042749 100644
--- a/resources/views/dialog_layout.ejs
+++ b/resources/views/dialog_layout.ejs
@@ -58,6 +58,7 @@
           <script type="text/javascript" src="/lib/hub.js"></script>
           <script type="text/javascript" src="/lib/dom-jquery.js"></script>
           <script type="text/javascript" src="/lib/module.js"></script>
+          <script type="text/javascript" src="/lib/jschannel.js"></script>
           <script type="text/javascript" src="/shared/javascript-extensions.js"></script>
           <script type="text/javascript" src="/shared/mediator.js"></script>
           <script type="text/javascript" src="/shared/class.js"></script>
diff --git a/resources/views/layout.ejs b/resources/views/layout.ejs
index 0aa7b9c1fb6ad98cfe749bf3863a3ae97532f6c4..3f0724e050322250295e3b29ed2d42828e3161ca 100644
--- a/resources/views/layout.ejs
+++ b/resources/views/layout.ejs
@@ -23,6 +23,7 @@
     <script src="/shared/javascript-extensions.js" type="text/javascript"></script>
     <script src="/shared/browserid.js" type="text/javascript"></script>
     <script src="/lib/dom-jquery.js" type="text/javascript"></script>
+    <script src="/lib/jschannel.js" type="text/javascript"></script>
 
     <script src="/shared/templates.js" type="text/javascript"></script>
     <script src="/shared/renderer.js" type="text/javascript"></script>