From b129bf9f4091fae57ee40419ed80343446bfd712 Mon Sep 17 00:00:00 2001 From: Shane Tomlinson <stomlinson@mozilla.com> Date: Mon, 9 Jan 2012 20:55:02 +0000 Subject: [PATCH] Starting to hook up two level auth in the front end. * Update network/user to handle two level auth. * Update tests that check authentication status to check for correct status. * State machine checks for the correct authentication level for an email address. --- .../dialog/controllers/required_email.js | 1 + .../static/dialog/resources/internal_api.js | 2 +- .../static/dialog/resources/state_machine.js | 23 ++++++++++++-- .../static/dialog/views/required_email.ejs | 8 ++++- resources/static/shared/network.js | 12 ++++---- .../primary_user_provisioned_unit_test.js | 2 +- .../resources/state_machine_unit_test.js | 30 +++++++++++++++---- .../test/qunit/shared/user_unit_test.js | 2 +- .../static/test/qunit/testHelpers/helpers.js | 1 + 9 files changed, 63 insertions(+), 18 deletions(-) diff --git a/resources/static/dialog/controllers/required_email.js b/resources/static/dialog/controllers/required_email.js index 59b4f351d..de8d29496 100644 --- a/resources/static/dialog/controllers/required_email.js +++ b/resources/static/dialog/controllers/required_email.js @@ -233,6 +233,7 @@ BrowserID.Modules.RequiredEmail = (function() { verify: false, signin: false, password: false, + secondary_auth: false, primary: false }, options); self.renderDialog("required_email", options); diff --git a/resources/static/dialog/resources/internal_api.js b/resources/static/dialog/resources/internal_api.js index a019ddf73..c6528aba4 100644 --- a/resources/static/dialog/resources/internal_api.js +++ b/resources/static/dialog/resources/internal_api.js @@ -62,7 +62,7 @@ storage.site.set(origin, "remember", true); } - complete(authenticated || null); + complete(!!authenticated || null); }, complete.curry(null)); }; diff --git a/resources/static/dialog/resources/state_machine.js b/resources/static/dialog/resources/state_machine.js index 488c57638..142261ce3 100644 --- a/resources/static/dialog/resources/state_machine.js +++ b/resources/static/dialog/resources/state_machine.js @@ -38,6 +38,7 @@ var bid = BrowserID, storage = bid.Storage, mediator = bid.Mediator, + user = bid.User, publish = mediator.publish.bind(mediator), subscriptions = [], stateStack = [], @@ -210,7 +211,13 @@ }); subscribe("email_chosen", function(msg, info) { - var idInfo = storage.getEmail(info.email); + var email = info.email + idInfo = storage.getEmail(email); + + function complete() { + info.complete && info.complete(); + } + if(idInfo) { if(idInfo.type === "primary") { if(idInfo.cert) { @@ -226,7 +233,19 @@ } } else { - startState("doEmailChosen", info); + user.checkAuthentication(function(authentication) { + if(authentication === "assertion") { + startState("doAuthenticateWithRequiredEmail", { + email: email, + authenticated: false, + secondary_auth: true + }); + } + else { + startState("doEmailChosen", info); + } + complete(); + }, complete); } } else { diff --git a/resources/static/dialog/views/required_email.ejs b/resources/static/dialog/views/required_email.ejs index 7c562127a..1f3a188eb 100644 --- a/resources/static/dialog/views/required_email.ejs +++ b/resources/static/dialog/views/required_email.ejs @@ -1,4 +1,10 @@ - <strong>The site requested you sign in using</strong> + <strong> + <% if(secondary_auth) { %> + Sign in using + <% } else { %> + The site requested you sign in using + <% } %> + </strong> <div class="form_section"> <ul class="inputs"> diff --git a/resources/static/shared/network.js b/resources/static/shared/network.js index 627417493..b1687c5b9 100644 --- a/resources/static/shared/network.js +++ b/resources/static/shared/network.js @@ -117,7 +117,7 @@ BrowserID.Network = (function() { } function withContext(cb, onFailure) { - if (typeof auth_status === 'boolean' && typeof csrf_token !== 'undefined') cb(); + if (typeof auth_status !== 'undefined' && typeof csrf_token !== 'undefined') cb(); else { var url = "/wsapi/session_context"; xhr.ajax({ @@ -155,7 +155,7 @@ BrowserID.Network = (function() { csrf_token = server_time = auth_status = undef; } - function handleAuthenticationResponse(onComplete, onFailure, status) { + function handleAuthenticationResponse(type, onComplete, onFailure, status) { if (onComplete) { try { var authenticated = status.success; @@ -165,7 +165,7 @@ BrowserID.Network = (function() { // at this point we know the authentication status of the // session, let's set it to perhaps save a network request // (to fetch session context). - auth_status = authenticated; + auth_status = authenticated && type; if (onComplete) onComplete(authenticated); } catch (e) { onFailure("unexpected server response: " + e); @@ -205,7 +205,7 @@ BrowserID.Network = (function() { email: email, pass: password }, - success: handleAuthenticationResponse.bind(null, onComplete, onFailure), + success: handleAuthenticationResponse.curry("password", onComplete, onFailure), error: onFailure }); }, @@ -226,7 +226,7 @@ BrowserID.Network = (function() { email: email, assertion: assertion }, - success: handleAuthenticationResponse.bind(null, onComplete, onFailure), + success: handleAuthenticationResponse.curry("assertion", onComplete, onFailure), error: onFailure }); }, @@ -241,7 +241,7 @@ BrowserID.Network = (function() { checkAuth: function(onComplete, onFailure) { withContext(function() { try { - if (typeof auth_status !== 'boolean') throw "can't get authentication status!"; + if (typeof auth_status === 'undefined') throw "can't get authentication status!"; if (onComplete) onComplete(auth_status); } catch(e) { if (onFailure) onFailure(e.toString()); diff --git a/resources/static/test/qunit/controllers/primary_user_provisioned_unit_test.js b/resources/static/test/qunit/controllers/primary_user_provisioned_unit_test.js index e78de4af4..10fae255a 100644 --- a/resources/static/test/qunit/controllers/primary_user_provisioned_unit_test.js +++ b/resources/static/test/qunit/controllers/primary_user_provisioned_unit_test.js @@ -115,7 +115,7 @@ asyncTest("start controller with `add: false` authenticates user", function() { register("primary_user_ready", function(msg, info) { network.checkAuth(function(status) { - equal(status, true, "status is correct"); + equal(status, "assertion", "status is correct"); start(); }); }); diff --git a/resources/static/test/qunit/resources/state_machine_unit_test.js b/resources/static/test/qunit/resources/state_machine_unit_test.js index d0df3c9e6..f02af9d7f 100644 --- a/resources/static/test/qunit/resources/state_machine_unit_test.js +++ b/resources/static/test/qunit/resources/state_machine_unit_test.js @@ -42,7 +42,8 @@ machine, actions, storage = bid.Storage, - testHelpers = bid.TestHelpers; + testHelpers = bid.TestHelpers, + xhr = bid.Mocks.xhr; var ActionsMock = function() { this.called = {}; @@ -261,16 +262,33 @@ }); - test("email_chosen with secondary email, user must authenticate - call doAuthenticateWithRequiredEmail", function() { + asyncTest("email_chosen with secondary email, user must authenticate - call doAuthenticateWithRequiredEmail", function() { + var email = "testuser@testuser.com"; + storage.addEmail(email, { type: "secondary" }); + xhr.setContextInfo("authenticated", "assertion"); + + mediator.publish("email_chosen", { + email: email, + complete: function() { + equal(actions.called.doAuthenticateWithRequiredEmail, true, "doAuthenticateWithRequiredEmail called"); + start(); + } + }); }); - test("email_chosen with secondary email, user authenticated to secondary - call doEmailChosen", function() { + asyncTest("email_chosen with secondary email, user authenticated to secondary - call doEmailChosen", function() { var email = "testuser@testuser.com"; storage.addEmail(email, { type: "secondary" }); - mediator.publish("email_chosen", { email: email }); - - equal(actions.called.doEmailChosen, true, "doEmailChosen called"); + xhr.setContextInfo("authenticated", "password"); + + mediator.publish("email_chosen", { + email: email, + complete: function() { + equal(actions.called.doEmailChosen, true, "doEmailChosen called"); + start(); + } + }); }); test("email_chosen with primary email - call doProvisionPrimaryUser", function() { diff --git a/resources/static/test/qunit/shared/user_unit_test.js b/resources/static/test/qunit/shared/user_unit_test.js index 50564754d..733e48d2e 100644 --- a/resources/static/test/qunit/shared/user_unit_test.js +++ b/resources/static/test/qunit/shared/user_unit_test.js @@ -200,7 +200,7 @@ var vep = require("./vep"); lib.createUser("unregistered@testuser.com", function(status) { equal(status, "primary.verified", "primary user is already verified, correct status"); network.checkAuth(function(authenticated) { - equal(authenticated, true, "after provisioning user, user should be automatically authenticated to BrowserID"); + equal(authenticated, "assertion", "after provisioning user, user should be automatically authenticated to BrowserID"); start(); }); }, testHelpers.unexpectedXHRFailure); diff --git a/resources/static/test/qunit/testHelpers/helpers.js b/resources/static/test/qunit/testHelpers/helpers.js index a131da0ce..9e19c32b9 100644 --- a/resources/static/test/qunit/testHelpers/helpers.js +++ b/resources/static/test/qunit/testHelpers/helpers.js @@ -41,6 +41,7 @@ BrowserID.TestHelpers = { setup: function() { network.setXHR(xhr); + //xhr.setContextInfo("authenticated", false); xhr.useResult("valid"); storage.clear(); -- GitLab