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); }