diff --git a/resources/static/common/js/user.js b/resources/static/common/js/user.js index be52ee35266f6b908a78941a889ba4200239336c..b1be1696d9d8cddb49f66ba00eaa51f88060a168 100644 --- a/resources/static/common/js/user.js +++ b/resources/static/common/js/user.js @@ -965,8 +965,14 @@ BrowserID.User = (function() { */ syncEmailKeypair: function(email, onComplete, onFailure) { prepareDeps(); - jwcrypto.generateKeypair({algorithm: "DS", keysize: bid.KEY_LENGTH}, function(err, keypair) { - certifyEmailKeypair(email, keypair, onComplete, onFailure); + // jwcrypto depends on a random seed being set to generate a keypair. + // The seed is set with a call to network.withContext. Ensure the + // random seed is set before continuing or else the seed may not be set, + // the key never created, and the onComplete callback never called. + network.withContext(function() { + jwcrypto.generateKeypair({algorithm: "DS", keysize: bid.KEY_LENGTH}, function(err, keypair) { + certifyEmailKeypair(email, keypair, onComplete, onFailure); + }); }); }, diff --git a/resources/static/test/cases/common/js/user.js b/resources/static/test/cases/common/js/user.js index fe0d5c491a5f7779179d96eb7a8e1d3ac67015b8..8713e750ffe2d67d86d74d2de0362bb43db82a2d 100644 --- a/resources/static/test/cases/common/js/user.js +++ b/resources/static/test/cases/common/js/user.js @@ -175,15 +175,14 @@ var jwcrypto = require("./lib/jwcrypto"); asyncTest("createPrimaryUser with primary, user verified with primary - expect 'primary.verified'", function() { xhr.useResult("primary"); - provisioning.setStatus(provisioning.AUTHENTICATED, function() { - lib.createPrimaryUser({email: "unregistered@testuser.com"}, function(status) { - equal(status, "primary.verified", "primary user is already verified, correct status"); - network.checkAuth(function(authenticated) { - equal(authenticated, "assertion", "after provisioning user, user should be automatically authenticated to Persona"); - start(); - }); - }, testHelpers.unexpectedXHRFailure); - }); + provisioning.setStatus(provisioning.AUTHENTICATED); + lib.createPrimaryUser({email: "unregistered@testuser.com"}, function(status) { + equal(status, "primary.verified", "primary user is already verified, correct status"); + network.checkAuth(function(authenticated) { + equal(authenticated, "assertion", "after provisioning user, user should be automatically authenticated to Persona"); + start(); + }); + }, testHelpers.unexpectedXHRFailure); }); asyncTest("createPrimaryUser with primary, user must authenticate with primary - expect 'primary.verify'", function() { diff --git a/resources/static/test/cases/dialog/js/modules/provision_primary_user.js b/resources/static/test/cases/dialog/js/modules/provision_primary_user.js index 9a54c32b07747888a71f216ea96d1ec011e62dfa..d5c540849802c80b10796e8efd7677491cb51645 100644 --- a/resources/static/test/cases/dialog/js/modules/provision_primary_user.js +++ b/resources/static/test/cases/dialog/js/modules/provision_primary_user.js @@ -56,53 +56,49 @@ }); asyncTest("create controller with all fields specified, user authenticated with primary - expected user provisioned", function() { - network.withContext(function() { - provisioning.setStatus(provisioning.AUTHENTICATED); + provisioning.setStatus(provisioning.AUTHENTICATED); + xhr.useResult("primary"); - mediator.subscribe("primary_user_provisioned", function(msg, info) { - ok(info.assertion, "assertion available"); - equal(info.email, "unregistered@testuser.com", "email available"); - start(); - }); + mediator.subscribe("primary_user_provisioned", function(msg, info) { + ok(info.assertion, "assertion available"); + equal(info.email, "unregistered@testuser.com", "email available"); + start(); + }); - createController({ - email: "unregistered@testuser.com", - auth: "https://auth_url", - prov: "https://prov_url" - }); + createController({ + email: "unregistered@testuser.com", + auth: "https://auth_url", + prov: "https://prov_url" }); }); asyncTest("create controller with all fields specified, user not authenticated with primary - expected user must authenticate", function() { - network.withContext(function() { - provisioning.setStatus(provisioning.NOT_AUTHENTICATED); + provisioning.setStatus(provisioning.NOT_AUTHENTICATED); + xhr.useResult("primary"); - mediator.subscribe("primary_user_unauthenticated", function(msg, info) { - equal(info.auth_url, "https://auth_url", "primary information fetched"); - start(); - }); + mediator.subscribe("primary_user_unauthenticated", function(msg, info) { + equal(info.auth_url, "https://auth_url", "primary information fetched"); + start(); + }); - createController({ - email: "unregistered@testuser.com", - auth: "https://auth_url", - prov: "https://prov_url" - }); + createController({ + email: "unregistered@testuser.com", + auth: "https://auth_url", + prov: "https://prov_url" }); }); asyncTest("create controller with missing auth/prov, user authenticated with primary - expected to request provisioning info from backend, user provisioned", function() { - network.withContext(function() { - xhr.useResult("primary"); - provisioning.setStatus(provisioning.AUTHENTICATED); + provisioning.setStatus(provisioning.AUTHENTICATED); + xhr.useResult("primary"); - mediator.subscribe("primary_user_provisioned", function(msg, info) { - equal(info.email, "unregistered@testuser.com", "user is provisioned after requesting info from backend"); - start(); - }); + mediator.subscribe("primary_user_provisioned", function(msg, info) { + equal(info.email, "unregistered@testuser.com", "user is provisioned after requesting info from backend"); + start(); + }); - createController({ - email: "unregistered@testuser.com" - }); + createController({ + email: "unregistered@testuser.com" }); }); }()); diff --git a/resources/static/test/mocks/provisioning.js b/resources/static/test/mocks/provisioning.js index c6413958b7a7a7035ced34448294ba968d9b5bf4..13907e4d7b981c59658f65268b32cec9f8cdfe8c 100644 --- a/resources/static/test/mocks/provisioning.js +++ b/resources/static/test/mocks/provisioning.js @@ -16,12 +16,26 @@ BrowserID.Mocks.Provisioning = (function() { function Provisioning(info, onsuccess, onfailure) { if(status === Provisioning.AUTHENTICATED) { - onsuccess(keypair, cert); + if (!keypair) { + // JWCrypto relies on there being a random seed. The random seed is + // gotten whenever network.withContext is called. Since this is + // supposed to mock the IdP provisioning step which will not call + // network.withContext, add a random seed to ensure that we can get our + // keypair. + jwcrypto.addEntropy("H+ZgKuhjVckv/H4i0Qvj/JGJEGDVOXSIS5RCOjY9/Bo="); + jwcrypto.generateKeypair({algorithm: "DS", keysize: 256}, function(err, kp) { + keypair = kp; + if (onsuccess) onsuccess(keypair, cert); + }); + } + else { + if (onsuccess) onsuccess(keypair, cert); + } } else onfailure(failure); } - Provisioning.setStatus = function(newStatus, cb) { + Provisioning.setStatus = function(newStatus) { failure = null; status = newStatus; @@ -31,16 +45,6 @@ BrowserID.Mocks.Provisioning = (function() { code: "primaryError", msg: "user is not authenticated as target user" }; - if (cb) cb(); - } - else if(newStatus === Provisioning.AUTHENTICATED) { - if (!keypair) { - jwcrypto.generateKeypair({algorithm: "DS", keysize: 256}, function(err, kp) { - keypair = kp; - if (cb) cb(); - }); - } - else if (cb) cb(); } };