diff options
Diffstat (limited to 'services/fxaccounts/tests/xpcshell/test_loginmgr_storage.js')
-rw-r--r-- | services/fxaccounts/tests/xpcshell/test_loginmgr_storage.js | 214 |
1 files changed, 214 insertions, 0 deletions
diff --git a/services/fxaccounts/tests/xpcshell/test_loginmgr_storage.js b/services/fxaccounts/tests/xpcshell/test_loginmgr_storage.js new file mode 100644 index 000000000..64ddb1fd1 --- /dev/null +++ b/services/fxaccounts/tests/xpcshell/test_loginmgr_storage.js @@ -0,0 +1,214 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +// Tests for FxAccounts, storage and the master password. + +// Stop us hitting the real auth server. +Services.prefs.setCharPref("identity.fxaccounts.auth.uri", "http://localhost"); +// See verbose logging from FxAccounts.jsm +Services.prefs.setCharPref("identity.fxaccounts.loglevel", "Trace"); + +Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/FxAccounts.jsm"); +Cu.import("resource://gre/modules/FxAccountsClient.jsm"); +Cu.import("resource://gre/modules/FxAccountsCommon.js"); +Cu.import("resource://gre/modules/osfile.jsm"); +Cu.import("resource://services-common/utils.js"); +Cu.import("resource://gre/modules/FxAccountsCommon.js"); + +// Use a backstage pass to get at our LoginManagerStorage object, so we can +// mock the prototype. +var {LoginManagerStorage} = Cu.import("resource://gre/modules/FxAccountsStorage.jsm", {}); +var isLoggedIn = true; +LoginManagerStorage.prototype.__defineGetter__("_isLoggedIn", () => isLoggedIn); + +function setLoginMgrLoggedInState(loggedIn) { + isLoggedIn = loggedIn; +} + + +initTestLogging("Trace"); + +function run_test() { + run_next_test(); +} + +function getLoginMgrData() { + let logins = Services.logins.findLogins({}, FXA_PWDMGR_HOST, null, FXA_PWDMGR_REALM); + if (logins.length == 0) { + return null; + } + Assert.equal(logins.length, 1, "only 1 login available"); + return logins[0]; +} + +function createFxAccounts() { + return new FxAccounts({ + _getDeviceName() { + return "mock device name"; + }, + fxaPushService: { + registerPushEndpoint() { + return new Promise((resolve) => { + resolve({ + endpoint: "http://mochi.test:8888" + }); + }); + }, + } + }); +} + +add_task(function* test_simple() { + let fxa = createFxAccounts(); + + let creds = { + uid: "abcd", + email: "test@example.com", + sessionToken: "sessionToken", + kA: "the kA value", + kB: "the kB value", + verified: true + }; + yield fxa.setSignedInUser(creds); + + // This should have stored stuff in both the .json file in the profile + // dir, and the login dir. + let path = OS.Path.join(OS.Constants.Path.profileDir, "signedInUser.json"); + let data = yield CommonUtils.readJSON(path); + + Assert.strictEqual(data.accountData.email, creds.email, "correct email in the clear text"); + Assert.strictEqual(data.accountData.sessionToken, creds.sessionToken, "correct sessionToken in the clear text"); + Assert.strictEqual(data.accountData.verified, creds.verified, "correct verified flag"); + + Assert.ok(!("kA" in data.accountData), "kA not stored in clear text"); + Assert.ok(!("kB" in data.accountData), "kB not stored in clear text"); + + let login = getLoginMgrData(); + Assert.strictEqual(login.username, creds.uid, "uid used for username"); + let loginData = JSON.parse(login.password); + Assert.strictEqual(loginData.version, data.version, "same version flag in both places"); + Assert.strictEqual(loginData.accountData.kA, creds.kA, "correct kA in the login mgr"); + Assert.strictEqual(loginData.accountData.kB, creds.kB, "correct kB in the login mgr"); + + Assert.ok(!("email" in loginData), "email not stored in the login mgr json"); + Assert.ok(!("sessionToken" in loginData), "sessionToken not stored in the login mgr json"); + Assert.ok(!("verified" in loginData), "verified not stored in the login mgr json"); + + yield fxa.signOut(/* localOnly = */ true); + Assert.strictEqual(getLoginMgrData(), null, "login mgr data deleted on logout"); +}); + +add_task(function* test_MPLocked() { + let fxa = createFxAccounts(); + + let creds = { + uid: "abcd", + email: "test@example.com", + sessionToken: "sessionToken", + kA: "the kA value", + kB: "the kB value", + verified: true + }; + + Assert.strictEqual(getLoginMgrData(), null, "no login mgr at the start"); + // tell the storage that the MP is locked. + setLoginMgrLoggedInState(false); + yield fxa.setSignedInUser(creds); + + // This should have stored stuff in the .json, and the login manager stuff + // will not exist. + let path = OS.Path.join(OS.Constants.Path.profileDir, "signedInUser.json"); + let data = yield CommonUtils.readJSON(path); + + Assert.strictEqual(data.accountData.email, creds.email, "correct email in the clear text"); + Assert.strictEqual(data.accountData.sessionToken, creds.sessionToken, "correct sessionToken in the clear text"); + Assert.strictEqual(data.accountData.verified, creds.verified, "correct verified flag"); + + Assert.ok(!("kA" in data.accountData), "kA not stored in clear text"); + Assert.ok(!("kB" in data.accountData), "kB not stored in clear text"); + + Assert.strictEqual(getLoginMgrData(), null, "login mgr data doesn't exist"); + yield fxa.signOut(/* localOnly = */ true) +}); + + +add_task(function* test_consistentWithMPEdgeCases() { + setLoginMgrLoggedInState(true); + + let fxa = createFxAccounts(); + + let creds1 = { + uid: "uid1", + email: "test@example.com", + sessionToken: "sessionToken", + kA: "the kA value", + kB: "the kB value", + verified: true + }; + + let creds2 = { + uid: "uid2", + email: "test2@example.com", + sessionToken: "sessionToken2", + kA: "the kA value2", + kB: "the kB value2", + verified: false, + }; + + // Log a user in while MP is unlocked. + yield fxa.setSignedInUser(creds1); + + // tell the storage that the MP is locked - this will prevent logout from + // being able to clear the data. + setLoginMgrLoggedInState(false); + + // now set the second credentials. + yield fxa.setSignedInUser(creds2); + + // We should still have creds1 data in the login manager. + let login = getLoginMgrData(); + Assert.strictEqual(login.username, creds1.uid); + // and that we do have the first kA in the login manager. + Assert.strictEqual(JSON.parse(login.password).accountData.kA, creds1.kA, + "stale data still in login mgr"); + + // Make a new FxA instance (otherwise the values in memory will be used) + // and we want the login manager to be unlocked. + setLoginMgrLoggedInState(true); + fxa = createFxAccounts(); + + let accountData = yield fxa.getSignedInUser(); + Assert.strictEqual(accountData.email, creds2.email); + // we should have no kA at all. + Assert.strictEqual(accountData.kA, undefined, "stale kA wasn't used"); + yield fxa.signOut(/* localOnly = */ true) +}); + +// A test for the fact we will accept either a UID or email when looking in +// the login manager. +add_task(function* test_uidMigration() { + setLoginMgrLoggedInState(true); + Assert.strictEqual(getLoginMgrData(), null, "expect no logins at the start"); + + // create the login entry using email as a key. + let contents = {kA: "kA"}; + + let loginInfo = new Components.Constructor( + "@mozilla.org/login-manager/loginInfo;1", Ci.nsILoginInfo, "init"); + let login = new loginInfo(FXA_PWDMGR_HOST, + null, // aFormSubmitURL, + FXA_PWDMGR_REALM, // aHttpRealm, + "foo@bar.com", // aUsername + JSON.stringify(contents), // aPassword + "", // aUsernameField + "");// aPasswordField + Services.logins.addLogin(login); + + // ensure we read it. + let storage = new LoginManagerStorage(); + let got = yield storage.get("uid", "foo@bar.com"); + Assert.deepEqual(got, contents); +}); |