From fa772f432684357c80a8d7662b448bf1eb655454 Mon Sep 17 00:00:00 2001 From: Shane Tomlinson <stomlinson@mozilla.com> Date: Sun, 1 Jul 2012 17:48:07 +0100 Subject: [PATCH] Removing @benadida's change to make the provisioning mock's setStatus asynchronous. Instead of generating the key whenever the status is set, generate the key whenever the user is being provisioned. Since the mock uses jwcrypto which must be seeded, seed jwcrypto with some bits. This more closely matches what a real RP would do. In the unit tests, any asynchronous calls to provisioningMock.setStatus have been make synchronous. In user.js, syncEmailKeypair, since jwcrypto depends on there being a seed to generate a keypair, call network.withContext which ensures there is a seed. --- resources/static/common/js/user.js | 10 ++- resources/static/test/cases/common/js/user.js | 17 +++-- .../js/modules/provision_primary_user.js | 62 +++++++++---------- resources/static/test/mocks/provisioning.js | 28 +++++---- 4 files changed, 61 insertions(+), 56 deletions(-) diff --git a/resources/static/common/js/user.js b/resources/static/common/js/user.js index be52ee352..b1be1696d 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 fe0d5c491..8713e750f 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 9a54c32b0..d5c540849 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 c6413958b..13907e4d7 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(); } }; -- GitLab