diff --git a/README.md b/README.md
index f8b50acfd64bd121463057a05bb5559137c0d544..c8ba8292e56384459978577f53d27f10c3de4502 100644
--- a/README.md
+++ b/README.md
@@ -49,13 +49,13 @@ Here's the software you'll need installed:
 ## Getting started:
 
 1. install node and npm
-3. run `./prepare_deps` to install 3rd party libraries and generate keys
-3. run the top level *run.js* script: `node ./run.js`
+3. run `npm install` to install 3rd party libraries and generate keys
+3. run `npm start` to start the servers locally
 4. visit the demo application ('rp') in your web browser (url output on the console at runtime)
 
 ## Testing
 
-Unit tests can be run by invoking `test.sh` at the top level, and you
+Unit tests can be run by invoking `npm test` at the top level, and you
 should run them often.  Like before committing code.  To fully test
 the code you should install mysql and have a well permissions `test`
 user (can create and drop databases).  If you don't have mysql installed,
diff --git a/browserid/lib/ca.js b/browserid/lib/ca.js
index 9aee7cacf8965fb8591b4bb81153bcf3b3a79b28..2c4cee8d34d0a911708026cea5f65d21eeb72fe0 100644
--- a/browserid/lib/ca.js
+++ b/browserid/lib/ca.js
@@ -57,18 +57,22 @@ function parseCert(serializedCert) {
 }
 
 function certify(email, publicKey, expiration) {
-  return new jwcert.JWCert(HOSTNAME, new Date(), publicKey, {email: email}).sign(secrets.SECRET_KEY);
+  if (expiration == null)
+    throw "expiration cannot be null";
+  return new jwcert.JWCert(HOSTNAME, expiration, publicKey, {email: email}).sign(secrets.SECRET_KEY);
 }
 
 function verifyChain(certChain, cb) {
   // raw certs
-  return jwcert.JWCert.verifyChain(certChain, function(issuer, next) {
-    // for now we only do browserid.org issued keys
-    if (issuer != HOSTNAME)
-      return next(null);
-
-    next(secrets.PUBLIC_KEY);
-  }, cb);
+  return jwcert.JWCert.verifyChain(
+    certChain, new Date(),
+    function(issuer, next) {
+      // for now we only do browserid.org issued keys
+      if (issuer != HOSTNAME)
+        return next(null);
+      
+      next(secrets.PUBLIC_KEY);
+    }, cb);
 }
 
 // exports, not the key stuff
diff --git a/browserid/lib/wsapi.js b/browserid/lib/wsapi.js
index c52ca320957397e05d0e2a4c6ac2c20a2afe1c3e..f26ea4822e0664e21a89e6337348877d79abffce 100644
--- a/browserid/lib/wsapi.js
+++ b/browserid/lib/wsapi.js
@@ -303,7 +303,11 @@ function setup(app) {
       var pk = ca.parsePublicKey(req.body.pubkey);
 
       // same account, we certify the key
-      var cert = ca.certify(req.body.email, pk);
+      // we certify it for a day for now
+      var expiration = new Date();
+      expiration.setTime(new Date().valueOf() + (24*3600*1000));
+      var cert = ca.certify(req.body.email, pk, expiration);
+      
       resp.writeHead(200, {'Content-Type': 'text/plain'});
       resp.write(cert);
       resp.end();
diff --git a/browserid/static/dialog/resources/browserid-identities.js b/browserid/static/dialog/resources/browserid-identities.js
index 186a650002a4982f2266f91c21959dea225216f5..b2b4d6acfac4b7b9742337afd118a7dfe483b945 100644
--- a/browserid/static/dialog/resources/browserid-identities.js
+++ b/browserid/static/dialog/resources/browserid-identities.js
@@ -38,7 +38,7 @@
 var BrowserIDIdentities = (function() {
   "use strict";
 
-  var jwk, jwt, vep, 
+  var jwk, jwt, vep, jwcert,
       network = BrowserIDNetwork, 
       storage = BrowserIDStorage;
     
@@ -47,6 +47,7 @@ var BrowserIDIdentities = (function() {
       jwk= require("./jwk");
       jwt = require("./jwt");
       vep = require("./vep");
+      jwcert = require("./jwcert");
     }
   }
 
@@ -61,8 +62,19 @@ var BrowserIDIdentities = (function() {
           delete emails[email_address];
         }
 
-        if (!email_obj.cert)
+        // no cert? reset
+        if (!email_obj.cert) {
           delete emails[email_address];
+        } else {
+          // parse the cert
+          var cert = new jwcert.JWCert();
+          cert.parse(emails[email_address].cert);
+
+          // check if needs to be reset, if it expires in 5 minutes
+          var diff = cert.expires.valueOf() - new Date().valueOf();
+          if (diff < 300000)
+            delete emails[email_address];
+        }
       });
 
       return emails;
diff --git a/browserid/tests/ca-test.js b/browserid/tests/ca-test.js
index 2e9bdcd54722e8c52da458090bd8a5a508c2b795..58841957aec1115a1c305b9ac466caf5fef61523 100755
--- a/browserid/tests/ca-test.js
+++ b/browserid/tests/ca-test.js
@@ -61,7 +61,9 @@ var email_addr = "foo@foo.com";
 suite.addBatch({
   "certify a public key": {
     topic: function() {
-      return ca.certify(email_addr, kp.publicKey);
+      var expiration = new Date();
+      expiration.setTime(new Date().valueOf() + 5000);
+      return ca.certify(email_addr, kp.publicKey, expiration);
     },
     "parses" : function(cert_raw, err) {
       var cert = ca.parseCert(cert_raw);
diff --git a/package.json b/package.json
index a3837e83c641eb7912e60c46e21917c67d29cba2..284bd3ab2db44be387375abb6801834704e179c9 100644
--- a/package.json
+++ b/package.json
@@ -25,10 +25,11 @@
     , "colors" : "0.5.0"
     , "sax" : "0.2.3"
     , "mimelib-noiconv" : "0.1.3"
-    , "jwcrypto": "https://github.com/mozilla/jwcrypto/tarball/defe9b"
+    , "jwcrypto": "https://github.com/mozilla/jwcrypto/tarball/e8b4e91"
   }
   , "scripts": {
     "postinstall": "./scripts/generate_ephemeral_keys.sh",
-    "test": "./scripts/run_all_tests.sh"
+    "test": "./scripts/run_all_tests.sh",
+    "start": "node ./run.js"
   }
 }
diff --git a/verifier/lib/certassertion.js b/verifier/lib/certassertion.js
index c2f88a1b81da46ea78c74687149cce1840a45451..0443b534726573cce9ba7e2becb80095ad2186b2 100644
--- a/verifier/lib/certassertion.js
+++ b/verifier/lib/certassertion.js
@@ -59,9 +59,6 @@ var publicKeys = {};
 // set up some default public keys
 publicKeys[configuration.get('hostname')] = secrets.PUBLIC_KEY;
 
-// FIXME: hard-wired key for mozilla.com
-publicKeys['mozilla.com'] = jwk.PublicKey.fromSimpleObject({"algorithm":"RS","value":"-----BEGIN PUBLIC KEY-----\nMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAIkB8pmT0Zf2gLW5oplYL22vjj6UIuXx\n9CfosFDy8DYTOVA6Z0wBBfQyaUcAdcQ4BzkV2zb7ik+f4WKdch2nwWkCAwEAAQ==\n-----END PUBLIC KEY-----\n"});
-
 function https_complete_get(host, url, successCB, errorCB) {
   https.get({host: host,path: url}, function(res) {
     var allData = "";
@@ -142,34 +139,37 @@ function verify(assertion, audience, successCB, errorCB, pkRetriever) {
   var bundle = vep.unbundleCertsAndAssertion(assertion);
 
   var theIssuer;
-  jwcert.JWCert.verifyChain(bundle.certificates, function(issuer, next) {
-    theIssuer = issuer;
-    // allow other retrievers for testing
-    if (pkRetriever)
-      pkRetriever(issuer, next);
-    else
-      retrieveHostPublicKey(issuer, next, function(err) {next(null);});
-  }, function(pk, principal) {
-    // primary?
-    if (theIssuer != configuration.get('hostname')) {
-      // then the email better match the issuer
-      if (!principal.email.match("@" + theIssuer + "$"))
+  jwcert.JWCert.verifyChain(
+    bundle.certificates,
+    new Date(), function(issuer, next) {
+      theIssuer = issuer;
+      // allow other retrievers for testing
+      if (pkRetriever)
+        pkRetriever(issuer, next);
+      else
+        retrieveHostPublicKey(issuer, next, function(err) {next(null);});
+    }, function(pk, principal) {
+      // primary?
+      if (theIssuer != configuration.get('hostname')) {
+        // then the email better match the issuer
+        console.log(principal);
+        if (!principal.email.match("@" + theIssuer + "$"))
+          return errorCB();
+      }
+      
+      var tok = new jwt.JWT();
+      tok.parse(bundle.assertion);
+      
+      // audience must match!
+      if (tok.audience != audience)
         return errorCB();
-    }
-
-    var tok = new jwt.JWT();
-    tok.parse(bundle.assertion);
-
-    // audience must match!
-    if (tok.audience != audience)
-      return errorCB();
-    
-    if (tok.verify(pk)) {
-      successCB(principal.email, tok.audience, tok.expires);
-    } else {
-      errorCB();
-    }
-  }, errorCB);
+      
+      if (tok.verify(pk)) {
+        successCB(principal.email, tok.audience, tok.expires);
+      } else {
+        errorCB();
+      }
+    }, errorCB);
 }