mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-17 06:09:19 +00:00
Bug 1888019 - Use a different client ID, scope and keys for Sync in Thunderbird. r=teshaq,sync-reviewers
Differential Revision: https://phabricator.services.mozilla.com/D205783
This commit is contained in:
parent
a2558c2be1
commit
7118d9b96b
@ -19,7 +19,7 @@ import {
|
||||
FXA_PWDMGR_PLAINTEXT_FIELDS,
|
||||
FXA_PWDMGR_REAUTH_ALLOWLIST,
|
||||
FXA_PWDMGR_SECURE_FIELDS,
|
||||
FX_OAUTH_CLIENT_ID,
|
||||
OAUTH_CLIENT_ID,
|
||||
ON_ACCOUNT_STATE_CHANGE_NOTIFICATION,
|
||||
ONLOGIN_NOTIFICATION,
|
||||
ONLOGOUT_NOTIFICATION,
|
||||
@ -1089,10 +1089,7 @@ FxAccountsInternal.prototype = {
|
||||
* @param { Object } tokenData: The token's data, with `tokenData.token` being the token itself
|
||||
**/
|
||||
destroyOAuthToken(tokenData) {
|
||||
return this.fxAccountsClient.oauthDestroy(
|
||||
FX_OAUTH_CLIENT_ID,
|
||||
tokenData.token
|
||||
);
|
||||
return this.fxAccountsClient.oauthDestroy(OAUTH_CLIENT_ID, tokenData.token);
|
||||
},
|
||||
|
||||
_destroyAllOAuthTokens(tokenInfos) {
|
||||
@ -1378,7 +1375,7 @@ FxAccountsInternal.prototype = {
|
||||
async _doTokenFetchWithSessionToken(sessionToken, scopeString, ttl) {
|
||||
const result = await this.fxAccountsClient.accessTokenWithSessionToken(
|
||||
sessionToken,
|
||||
FX_OAUTH_CLIENT_ID,
|
||||
OAUTH_CLIENT_ID,
|
||||
scopeString,
|
||||
ttl
|
||||
);
|
||||
|
@ -3,6 +3,7 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
import {
|
||||
CLIENT_IS_THUNDERBIRD,
|
||||
COMMAND_SENDTAB,
|
||||
COMMAND_SENDTAB_TAIL,
|
||||
COMMAND_CLOSETAB,
|
||||
@ -49,26 +50,30 @@ export class FxAccountsCommands {
|
||||
}
|
||||
|
||||
async availableCommands() {
|
||||
// Invalid keys usually means the account is not verified yet.
|
||||
const encryptedSendTabKeys = await this.sendTab.getEncryptedSendTabKeys();
|
||||
let commands = {};
|
||||
|
||||
if (encryptedSendTabKeys) {
|
||||
commands[COMMAND_SENDTAB] = encryptedSendTabKeys;
|
||||
}
|
||||
if (!CLIENT_IS_THUNDERBIRD) {
|
||||
// Invalid keys usually means the account is not verified yet.
|
||||
const encryptedSendTabKeys = await this.sendTab.getEncryptedSendTabKeys();
|
||||
|
||||
// Close Tab is still a worked-on feature, so we should not broadcast it widely yet
|
||||
let closeTabEnabled = Services.prefs.getBoolPref(
|
||||
"identity.fxaccounts.commands.remoteTabManagement.enabled",
|
||||
false
|
||||
);
|
||||
if (closeTabEnabled) {
|
||||
const encryptedCloseTabKeys =
|
||||
await this.closeTab.getEncryptedCloseTabKeys();
|
||||
if (encryptedCloseTabKeys) {
|
||||
commands[COMMAND_CLOSETAB] = encryptedCloseTabKeys;
|
||||
if (encryptedSendTabKeys) {
|
||||
commands[COMMAND_SENDTAB] = encryptedSendTabKeys;
|
||||
}
|
||||
|
||||
// Close Tab is still a worked-on feature, so we should not broadcast it widely yet
|
||||
let closeTabEnabled = Services.prefs.getBoolPref(
|
||||
"identity.fxaccounts.commands.remoteTabManagement.enabled",
|
||||
false
|
||||
);
|
||||
if (closeTabEnabled) {
|
||||
const encryptedCloseTabKeys =
|
||||
await this.closeTab.getEncryptedCloseTabKeys();
|
||||
if (encryptedCloseTabKeys) {
|
||||
commands[COMMAND_CLOSETAB] = encryptedCloseTabKeys;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return commands;
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
import { AppConstants } from "resource://gre/modules/AppConstants.sys.mjs";
|
||||
import { Log } from "resource://gre/modules/Log.sys.mjs";
|
||||
import { LogManager } from "resource://gre/modules/LogManager.sys.mjs";
|
||||
|
||||
@ -88,10 +89,22 @@ export let COMMAND_CLOSETAB_TAIL = "close-uri/v1";
|
||||
export let COMMAND_CLOSETAB = COMMAND_PREFIX + COMMAND_CLOSETAB_TAIL;
|
||||
|
||||
// OAuth
|
||||
export let FX_OAUTH_CLIENT_ID = "5882386c6d801776";
|
||||
export let CLIENT_IS_THUNDERBIRD = AppConstants.MOZ_APP_NAME == "thunderbird";
|
||||
let FX_OAUTH_CLIENT_ID = "5882386c6d801776";
|
||||
let TB_OAUTH_CLIENT_ID = "8269bacd7bbc7f80";
|
||||
export let OAUTH_CLIENT_ID = CLIENT_IS_THUNDERBIRD
|
||||
? TB_OAUTH_CLIENT_ID
|
||||
: FX_OAUTH_CLIENT_ID;
|
||||
export let SCOPE_PROFILE = "profile";
|
||||
export let SCOPE_PROFILE_WRITE = "profile:write";
|
||||
// Sync scope in Firefox.
|
||||
export let SCOPE_OLD_SYNC = "https://identity.mozilla.com/apps/oldsync";
|
||||
// Sync scope in Thunderbird.
|
||||
let SCOPE_THUNDERBIRD_SYNC = "https://identity.thunderbird.net/apps/sync";
|
||||
// The scope to use for sync, depending on the current application.
|
||||
export let SCOPE_APP_SYNC = CLIENT_IS_THUNDERBIRD
|
||||
? SCOPE_THUNDERBIRD_SYNC
|
||||
: SCOPE_OLD_SYNC;
|
||||
|
||||
// This scope was previously used to calculate a telemetry tracking identifier for
|
||||
// the account, but that system has since been decommissioned. It's here entirely
|
||||
|
@ -6,7 +6,7 @@ import { RESTRequest } from "resource://services-common/rest.sys.mjs";
|
||||
|
||||
import {
|
||||
log,
|
||||
SCOPE_OLD_SYNC,
|
||||
SCOPE_APP_SYNC,
|
||||
SCOPE_PROFILE,
|
||||
} from "resource://gre/modules/FxAccountsCommon.sys.mjs";
|
||||
import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs";
|
||||
@ -344,7 +344,7 @@ export var FxAccountsConfig = {
|
||||
|
||||
async _getAuthParams() {
|
||||
if (this._isOAuthFlow()) {
|
||||
const scopes = [SCOPE_OLD_SYNC, SCOPE_PROFILE];
|
||||
const scopes = [SCOPE_APP_SYNC, SCOPE_PROFILE];
|
||||
return lazy.fxAccounts._internal.beginOAuthFlow(scopes);
|
||||
}
|
||||
return { service: SYNC_PARAM };
|
||||
|
@ -7,9 +7,9 @@ import { CommonUtils } from "resource://services-common/utils.sys.mjs";
|
||||
import { CryptoUtils } from "resource://services-crypto/utils.sys.mjs";
|
||||
|
||||
import {
|
||||
SCOPE_OLD_SYNC,
|
||||
SCOPE_APP_SYNC,
|
||||
DEPRECATED_SCOPE_ECOSYSTEM_TELEMETRY,
|
||||
FX_OAUTH_CLIENT_ID,
|
||||
OAUTH_CLIENT_ID,
|
||||
log,
|
||||
logPII,
|
||||
} from "resource://gre/modules/FxAccountsCommon.sys.mjs";
|
||||
@ -35,7 +35,7 @@ const DEPRECATED_SCOPE_WEBEXT_SYNC = "sync:addon_storage";
|
||||
// These are the scopes that correspond to new storage for the `LEGACY_DERIVED_KEYS_NAMES`.
|
||||
// We will, if necessary, migrate storage for those keys so that it's associated with
|
||||
// these scopes.
|
||||
const LEGACY_DERIVED_KEY_SCOPES = [SCOPE_OLD_SYNC];
|
||||
const LEGACY_DERIVED_KEY_SCOPES = [SCOPE_APP_SYNC];
|
||||
|
||||
// These are scopes that we used to store, but are no longer using,
|
||||
// and hence should be deleted from storage if present.
|
||||
@ -474,23 +474,21 @@ export class FxAccountsKeys {
|
||||
async _fetchScopedKeysMetadata(sessionToken) {
|
||||
// Hard-coded list of scopes that we know about.
|
||||
// This list will probably grow in future.
|
||||
const scopes = [SCOPE_OLD_SYNC].join(" ");
|
||||
const scopes = [SCOPE_APP_SYNC].join(" ");
|
||||
const scopedKeysMetadata =
|
||||
await this._fxai.fxAccountsClient.getScopedKeyData(
|
||||
sessionToken,
|
||||
FX_OAUTH_CLIENT_ID,
|
||||
OAUTH_CLIENT_ID,
|
||||
scopes
|
||||
);
|
||||
// The server may decline us permission for some of those scopes, although it really shouldn't.
|
||||
// We can live without them...except for the OLDSYNC scope, whose absence would be catastrophic.
|
||||
if (!scopedKeysMetadata.hasOwnProperty(SCOPE_OLD_SYNC)) {
|
||||
// We can live without them...except for the sync scope, whose absence would be catastrophic.
|
||||
if (!scopedKeysMetadata.hasOwnProperty(SCOPE_APP_SYNC)) {
|
||||
log.warn(
|
||||
"The FxA server did not grant Firefox the `oldsync` scope; this is most unexpected!" +
|
||||
"The FxA server did not grant Firefox the sync scope; this is most unexpected!" +
|
||||
` scopes were: ${Object.keys(scopedKeysMetadata)}`
|
||||
);
|
||||
throw new Error(
|
||||
"The FxA server did not grant Firefox the `oldsync` scope"
|
||||
);
|
||||
throw new Error("The FxA server did not grant Firefox the sync scope");
|
||||
}
|
||||
return scopedKeysMetadata;
|
||||
}
|
||||
@ -645,7 +643,7 @@ export class FxAccountsKeys {
|
||||
*/
|
||||
async _deriveLegacyScopedKey(uid, kBbytes, scope, scopedKeyMetadata) {
|
||||
let kid, key;
|
||||
if (scope == SCOPE_OLD_SYNC) {
|
||||
if (scope == SCOPE_APP_SYNC) {
|
||||
kid = await this._deriveXClientState(kBbytes);
|
||||
key = await this._deriveSyncKey(kBbytes);
|
||||
} else {
|
||||
|
@ -9,13 +9,13 @@ ChromeUtils.defineESModuleGetters(lazy, {
|
||||
});
|
||||
|
||||
import {
|
||||
FX_OAUTH_CLIENT_ID,
|
||||
OAUTH_CLIENT_ID,
|
||||
SCOPE_PROFILE,
|
||||
SCOPE_PROFILE_WRITE,
|
||||
SCOPE_OLD_SYNC,
|
||||
SCOPE_APP_SYNC,
|
||||
} from "resource://gre/modules/FxAccountsCommon.sys.mjs";
|
||||
|
||||
const VALID_SCOPES = [SCOPE_PROFILE, SCOPE_PROFILE_WRITE, SCOPE_OLD_SYNC];
|
||||
const VALID_SCOPES = [SCOPE_PROFILE, SCOPE_PROFILE_WRITE, SCOPE_APP_SYNC];
|
||||
|
||||
export const ERROR_INVALID_SCOPES = "INVALID_SCOPES";
|
||||
export const ERROR_INVALID_STATE = "INVALID_STATE";
|
||||
@ -116,7 +116,7 @@ export class FxAccountsOAuth {
|
||||
throw new Error(ERROR_INVALID_SCOPES);
|
||||
}
|
||||
const queryParams = {
|
||||
client_id: FX_OAUTH_CLIENT_ID,
|
||||
client_id: OAUTH_CLIENT_ID,
|
||||
action: "email",
|
||||
response_type: "code",
|
||||
access_type: "offline",
|
||||
@ -194,15 +194,15 @@ export class FxAccountsOAuth {
|
||||
sessionTokenHex,
|
||||
code,
|
||||
verifier,
|
||||
FX_OAUTH_CLIENT_ID
|
||||
OAUTH_CLIENT_ID
|
||||
);
|
||||
if (
|
||||
requestedScopes.includes(SCOPE_OLD_SYNC) &&
|
||||
!scope.includes(SCOPE_OLD_SYNC)
|
||||
requestedScopes.includes(SCOPE_APP_SYNC) &&
|
||||
!scope.includes(SCOPE_APP_SYNC)
|
||||
) {
|
||||
throw new Error(ERROR_SYNC_SCOPE_NOT_GRANTED);
|
||||
}
|
||||
if (scope.includes(SCOPE_OLD_SYNC) && !keys_jwe) {
|
||||
if (scope.includes(SCOPE_APP_SYNC) && !keys_jwe) {
|
||||
throw new Error(ERROR_NO_KEYS_JWE);
|
||||
}
|
||||
let scopedKeys;
|
||||
|
@ -28,7 +28,7 @@ import {
|
||||
COMMAND_PAIR_COMPLETE,
|
||||
COMMAND_PAIR_PREFERENCES,
|
||||
COMMAND_FIREFOX_VIEW,
|
||||
FX_OAUTH_CLIENT_ID,
|
||||
OAUTH_CLIENT_ID,
|
||||
ON_PROFILE_CHANGE_NOTIFICATION,
|
||||
PREF_LAST_FXA_USER,
|
||||
WEBCHANNEL_ID,
|
||||
@ -647,7 +647,7 @@ FxAccountsWebChannelHelpers.prototype = {
|
||||
|
||||
return {
|
||||
signedInUser,
|
||||
clientId: FX_OAUTH_CLIENT_ID,
|
||||
clientId: OAUTH_CLIENT_ID,
|
||||
capabilities,
|
||||
};
|
||||
},
|
||||
|
@ -12,14 +12,14 @@ const { XPCOMUtils } = ChromeUtils.importESModule(
|
||||
const { sinon } = ChromeUtils.importESModule(
|
||||
"resource://testing-common/Sinon.sys.mjs"
|
||||
);
|
||||
const { SCOPE_OLD_SYNC } = ChromeUtils.importESModule(
|
||||
const { SCOPE_APP_SYNC, SCOPE_OLD_SYNC } = ChromeUtils.importESModule(
|
||||
"resource://gre/modules/FxAccountsCommon.sys.mjs"
|
||||
);
|
||||
|
||||
// Some mock key data, in both scoped-key and legacy field formats.
|
||||
const MOCK_ACCOUNT_KEYS = {
|
||||
scopedKeys: {
|
||||
[SCOPE_OLD_SYNC]: {
|
||||
[SCOPE_APP_SYNC]: {
|
||||
kid: "1234567890123-u7u7u7u7u7u7u7u7u7u7uw",
|
||||
k: "qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqg",
|
||||
kty: "oct",
|
||||
|
@ -13,9 +13,10 @@ const { FxAccountsClient } = ChromeUtils.importESModule(
|
||||
"resource://gre/modules/FxAccountsClient.sys.mjs"
|
||||
);
|
||||
const {
|
||||
CLIENT_IS_THUNDERBIRD,
|
||||
ERRNO_INVALID_AUTH_TOKEN,
|
||||
ERROR_NO_ACCOUNT,
|
||||
FX_OAUTH_CLIENT_ID,
|
||||
OAUTH_CLIENT_ID,
|
||||
ONLOGIN_NOTIFICATION,
|
||||
ONLOGOUT_NOTIFICATION,
|
||||
ONVERIFIED_NOTIFICATION,
|
||||
@ -34,7 +35,7 @@ const MOCK_TOKEN_RESPONSE = {
|
||||
access_token:
|
||||
"43793fdfffec22eb39fc3c44ed09193a6fde4c24e5d6a73f73178597b268af69",
|
||||
token_type: "bearer",
|
||||
scope: "https://identity.mozilla.com/apps/oldsync",
|
||||
scope: SCOPE_APP_SYNC,
|
||||
expires_in: 21600,
|
||||
auth_at: 1589579900,
|
||||
};
|
||||
@ -152,13 +153,13 @@ function MockFxAccountsClient() {
|
||||
|
||||
this.getScopedKeyData = function (sessionToken, client_id, scopes) {
|
||||
Assert.ok(sessionToken);
|
||||
Assert.equal(client_id, FX_OAUTH_CLIENT_ID);
|
||||
Assert.equal(scopes, SCOPE_OLD_SYNC);
|
||||
Assert.equal(client_id, OAUTH_CLIENT_ID);
|
||||
Assert.equal(scopes, SCOPE_APP_SYNC);
|
||||
return new Promise(resolve => {
|
||||
do_timeout(50, () => {
|
||||
resolve({
|
||||
"https://identity.mozilla.com/apps/oldsync": {
|
||||
identifier: "https://identity.mozilla.com/apps/oldsync",
|
||||
[SCOPE_APP_SYNC]: {
|
||||
identifier: SCOPE_APP_SYNC,
|
||||
keyRotationSecret:
|
||||
"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
keyRotationTimestamp: 1234567890123,
|
||||
@ -678,7 +679,7 @@ add_test(function test_getKeyForScope() {
|
||||
Assert.equal(!!user2.keyFetchToken, true);
|
||||
Assert.equal(!!user2.unwrapBKey, true);
|
||||
|
||||
fxa.keys.getKeyForScope(SCOPE_OLD_SYNC).then(() => {
|
||||
fxa.keys.getKeyForScope(SCOPE_APP_SYNC).then(() => {
|
||||
fxa._internal.getUserAccountData().then(user3 => {
|
||||
// Now we should have keys
|
||||
Assert.equal(fxa._internal.isUserEmailVerified(user3), true);
|
||||
@ -712,7 +713,7 @@ add_task(
|
||||
|
||||
await fxa.setSignedInUser(user);
|
||||
// getKeyForScope will run the migration
|
||||
await fxa.keys.getKeyForScope(SCOPE_OLD_SYNC);
|
||||
await fxa.keys.getKeyForScope(SCOPE_APP_SYNC);
|
||||
let newUser = await fxa._internal.getUserAccountData();
|
||||
// Then, the deprecated keys will be removed
|
||||
Assert.strictEqual(newUser.kExtSync, undefined);
|
||||
@ -732,21 +733,21 @@ add_task(
|
||||
user.scopedKeys = {
|
||||
...MOCK_ACCOUNT_KEYS.scopedKeys,
|
||||
[DEPRECATED_SCOPE_ECOSYSTEM_TELEMETRY]:
|
||||
MOCK_ACCOUNT_KEYS.scopedKeys[SCOPE_OLD_SYNC],
|
||||
MOCK_ACCOUNT_KEYS.scopedKeys[SCOPE_APP_SYNC],
|
||||
[DEPRECATED_SCOPE_WEBEXT_SYNC]:
|
||||
MOCK_ACCOUNT_KEYS.scopedKeys[SCOPE_OLD_SYNC],
|
||||
[EXTRA_SCOPE]: MOCK_ACCOUNT_KEYS.scopedKeys[SCOPE_OLD_SYNC],
|
||||
MOCK_ACCOUNT_KEYS.scopedKeys[SCOPE_APP_SYNC],
|
||||
[EXTRA_SCOPE]: MOCK_ACCOUNT_KEYS.scopedKeys[SCOPE_APP_SYNC],
|
||||
};
|
||||
|
||||
await fxa.setSignedInUser(user);
|
||||
await fxa.keys.getKeyForScope(SCOPE_OLD_SYNC);
|
||||
await fxa.keys.getKeyForScope(SCOPE_APP_SYNC);
|
||||
let newUser = await fxa._internal.getUserAccountData();
|
||||
// It should have removed the deprecated ecosystem_telemetry key,
|
||||
// and the old kinto extension sync key
|
||||
// but left the other keys intact.
|
||||
const expectedScopedKeys = {
|
||||
...MOCK_ACCOUNT_KEYS.scopedKeys,
|
||||
[EXTRA_SCOPE]: MOCK_ACCOUNT_KEYS.scopedKeys[SCOPE_OLD_SYNC],
|
||||
[EXTRA_SCOPE]: MOCK_ACCOUNT_KEYS.scopedKeys[SCOPE_APP_SYNC],
|
||||
};
|
||||
Assert.deepEqual(newUser.scopedKeys, expectedScopedKeys);
|
||||
Assert.equal(newUser.ecosystemUserId, null);
|
||||
@ -777,7 +778,7 @@ add_task(async function test_getKeyForScope_nonexistent_account() {
|
||||
});
|
||||
});
|
||||
|
||||
await Assert.rejects(fxa.keys.getKeyForScope(SCOPE_OLD_SYNC), err => {
|
||||
await Assert.rejects(fxa.keys.getKeyForScope(SCOPE_APP_SYNC), err => {
|
||||
Assert.equal(err.message, ERROR_INVALID_ACCOUNT_STATE);
|
||||
return true; // expected error
|
||||
});
|
||||
@ -808,7 +809,7 @@ add_task(async function test_getKeyForScope_invalid_token() {
|
||||
Assert.notEqual(user.encryptedSendTabKeys, null);
|
||||
|
||||
try {
|
||||
await fxa.keys.getKeyForScope(SCOPE_OLD_SYNC);
|
||||
await fxa.keys.getKeyForScope(SCOPE_APP_SYNC);
|
||||
Assert.ok(false);
|
||||
} catch (err) {
|
||||
Assert.equal(err.code, 401);
|
||||
@ -831,8 +832,8 @@ add_task(async function test_getKeyForScope_oldsync() {
|
||||
let client = fxa._internal.fxAccountsClient;
|
||||
client.getScopedKeyData = () =>
|
||||
Promise.resolve({
|
||||
"https://identity.mozilla.com/apps/oldsync": {
|
||||
identifier: "https://identity.mozilla.com/apps/oldsync",
|
||||
[SCOPE_APP_SYNC]: {
|
||||
identifier: SCOPE_APP_SYNC,
|
||||
keyRotationSecret:
|
||||
"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
keyRotationTimestamp: 1510726317123,
|
||||
@ -862,7 +863,7 @@ add_task(async function test_getKeyForScope_oldsync() {
|
||||
await fxa.setSignedInUser(user);
|
||||
|
||||
// We derive, persist and return the sync key
|
||||
const key = await fxa.keys.getKeyForScope(SCOPE_OLD_SYNC);
|
||||
const key = await fxa.keys.getKeyForScope(SCOPE_APP_SYNC);
|
||||
|
||||
// We verify the key returned matches what we would expect from the test vectors
|
||||
// kb = 2ee722fdd8ccaa721bdeb2d1b76560efef705b04349d9357c3e592cf4906e075 (from test vectors)
|
||||
@ -871,7 +872,7 @@ add_task(async function test_getKeyForScope_oldsync() {
|
||||
//
|
||||
// k can be verified by HKDF(kb, undefined, "identity.mozilla.com/picl/v1/oldsync", 64)
|
||||
Assert.deepEqual(key, {
|
||||
scope: SCOPE_OLD_SYNC,
|
||||
scope: SCOPE_APP_SYNC,
|
||||
kid: "1510726317123-BAik7hEOdpGnPZnPBSdaTg",
|
||||
k: "fwM5VZu0Spf5XcFRZYX2zk6MrqZP7zvovCBcvuKwgYMif3hz98FHmIVa3qjKjrW0J244Zj-P5oWaOcQbvypmpw",
|
||||
kty: "oct",
|
||||
@ -888,10 +889,10 @@ add_task(async function test_getScopedKeys_cached_key() {
|
||||
};
|
||||
|
||||
await fxa.setSignedInUser(user);
|
||||
let key = await fxa.keys.getKeyForScope(SCOPE_OLD_SYNC);
|
||||
let key = await fxa.keys.getKeyForScope(SCOPE_APP_SYNC);
|
||||
Assert.deepEqual(key, {
|
||||
scope: SCOPE_OLD_SYNC,
|
||||
...MOCK_ACCOUNT_KEYS.scopedKeys[SCOPE_OLD_SYNC],
|
||||
scope: SCOPE_APP_SYNC,
|
||||
...MOCK_ACCOUNT_KEYS.scopedKeys[SCOPE_APP_SYNC],
|
||||
});
|
||||
});
|
||||
|
||||
@ -934,8 +935,8 @@ add_task(async function test_getScopedKeys_misconfigured_fxa_server() {
|
||||
};
|
||||
await fxa.setSignedInUser(user);
|
||||
await Assert.rejects(
|
||||
fxa.keys.getKeyForScope(SCOPE_OLD_SYNC),
|
||||
/The FxA server did not grant Firefox the `oldsync` scope/
|
||||
fxa.keys.getKeyForScope(SCOPE_APP_SYNC),
|
||||
/The FxA server did not grant Firefox the sync scope/
|
||||
);
|
||||
});
|
||||
|
||||
@ -947,10 +948,10 @@ add_task(async function test_setScopedKeys() {
|
||||
};
|
||||
await fxa.setSignedInUser(user);
|
||||
await fxa.keys.setScopedKeys(MOCK_ACCOUNT_KEYS.scopedKeys);
|
||||
const key = await fxa.keys.getKeyForScope(SCOPE_OLD_SYNC);
|
||||
const key = await fxa.keys.getKeyForScope(SCOPE_APP_SYNC);
|
||||
Assert.deepEqual(key, {
|
||||
scope: SCOPE_OLD_SYNC,
|
||||
...MOCK_ACCOUNT_KEYS.scopedKeys[SCOPE_OLD_SYNC],
|
||||
scope: SCOPE_APP_SYNC,
|
||||
...MOCK_ACCOUNT_KEYS.scopedKeys[SCOPE_APP_SYNC],
|
||||
});
|
||||
});
|
||||
|
||||
@ -1166,7 +1167,10 @@ add_test(async function test_getOAuthTokenWithSessionToken() {
|
||||
) => {
|
||||
oauthTokenCalled = true;
|
||||
Assert.equal(sessionTokenHex, "alice's session token");
|
||||
Assert.equal(clientId, "5882386c6d801776");
|
||||
Assert.equal(
|
||||
clientId,
|
||||
CLIENT_IS_THUNDERBIRD ? "a958794159236f76" : "5882386c6d801776"
|
||||
);
|
||||
Assert.equal(scope, "profile");
|
||||
Assert.equal(ttl, undefined);
|
||||
return MOCK_TOKEN_RESPONSE;
|
||||
@ -1445,7 +1449,7 @@ add_task(async function test_listAttachedOAuthClients() {
|
||||
deviceId: "deadbeef",
|
||||
sessionTokenId: null,
|
||||
name: "Firefox Preview (no session token)",
|
||||
scope: ["profile", "https://identity.mozilla.com/apps/oldsync"],
|
||||
scope: ["profile", SCOPE_APP_SYNC],
|
||||
lastAccessTime: Date.now(),
|
||||
},
|
||||
{
|
||||
|
@ -9,6 +9,7 @@ const { FxAccounts } = ChromeUtils.importESModule(
|
||||
|
||||
add_task(
|
||||
async function test_non_https_remote_server_uri_with_requireHttps_false() {
|
||||
Services.prefs.setStringPref("identity.fxaccounts.autoconfig.uri", "");
|
||||
Services.prefs.setBoolPref("identity.fxaccounts.allowHttp", true);
|
||||
Services.prefs.setStringPref(
|
||||
"identity.fxaccounts.remote.root",
|
||||
|
@ -13,6 +13,7 @@ const { FxAccountsDevice } = ChromeUtils.importESModule(
|
||||
"resource://gre/modules/FxAccountsDevice.sys.mjs"
|
||||
);
|
||||
const {
|
||||
CLIENT_IS_THUNDERBIRD,
|
||||
ERRNO_DEVICE_SESSION_CONFLICT,
|
||||
ERRNO_TOO_MANY_CLIENT_REQUESTS,
|
||||
ERRNO_UNKNOWN_DEVICE,
|
||||
@ -625,48 +626,50 @@ add_task(
|
||||
}
|
||||
);
|
||||
|
||||
add_task(async function test_verification_updates_registration() {
|
||||
const deviceName = "foo";
|
||||
add_task(
|
||||
{ skip_if: () => CLIENT_IS_THUNDERBIRD },
|
||||
async function test_verification_updates_registration() {
|
||||
const deviceName = "foo";
|
||||
|
||||
const credentials = getTestUser("baz");
|
||||
const fxa = await MockFxAccounts(credentials, {
|
||||
id: "device-id",
|
||||
name: deviceName,
|
||||
});
|
||||
const credentials = getTestUser("baz");
|
||||
const fxa = await MockFxAccounts(credentials, {
|
||||
id: "device-id",
|
||||
name: deviceName,
|
||||
});
|
||||
|
||||
// We should already have a device registration, but without send-tab due to
|
||||
// our inability to fetch keys for an unverified users.
|
||||
const state = fxa._internal.currentAccountState;
|
||||
const { device } = await state.getUserAccountData();
|
||||
Assert.equal(device.registeredCommandsKeys.length, 0);
|
||||
// We should already have a device registration, but without send-tab due to
|
||||
// our inability to fetch keys for an unverified users.
|
||||
const state = fxa._internal.currentAccountState;
|
||||
const { device } = await state.getUserAccountData();
|
||||
Assert.equal(device.registeredCommandsKeys.length, 0);
|
||||
|
||||
let updatePromise = new Promise(resolve => {
|
||||
const old_registerOrUpdateDevice = fxa.device._registerOrUpdateDevice.bind(
|
||||
fxa.device
|
||||
);
|
||||
fxa.device._registerOrUpdateDevice = async function (
|
||||
currentState,
|
||||
signedInUser
|
||||
) {
|
||||
await old_registerOrUpdateDevice(currentState, signedInUser);
|
||||
fxa.device._registerOrUpdateDevice = old_registerOrUpdateDevice;
|
||||
resolve();
|
||||
let updatePromise = new Promise(resolve => {
|
||||
const old_registerOrUpdateDevice =
|
||||
fxa.device._registerOrUpdateDevice.bind(fxa.device);
|
||||
fxa.device._registerOrUpdateDevice = async function (
|
||||
currentState,
|
||||
signedInUser
|
||||
) {
|
||||
await old_registerOrUpdateDevice(currentState, signedInUser);
|
||||
fxa.device._registerOrUpdateDevice = old_registerOrUpdateDevice;
|
||||
resolve();
|
||||
};
|
||||
});
|
||||
|
||||
fxa._internal.checkEmailStatus = async function () {
|
||||
credentials.verified = true;
|
||||
return credentials;
|
||||
};
|
||||
});
|
||||
|
||||
fxa._internal.checkEmailStatus = async function () {
|
||||
credentials.verified = true;
|
||||
return credentials;
|
||||
};
|
||||
await updatePromise;
|
||||
|
||||
await updatePromise;
|
||||
|
||||
const { device: newDevice, encryptedSendTabKeys } =
|
||||
await state.getUserAccountData();
|
||||
Assert.equal(newDevice.registeredCommandsKeys.length, 1);
|
||||
Assert.notEqual(encryptedSendTabKeys, null);
|
||||
await fxa.signOut(true);
|
||||
});
|
||||
const { device: newDevice, encryptedSendTabKeys } =
|
||||
await state.getUserAccountData();
|
||||
Assert.equal(newDevice.registeredCommandsKeys.length, 1);
|
||||
Assert.notEqual(encryptedSendTabKeys, null);
|
||||
await fxa.signOut(true);
|
||||
}
|
||||
);
|
||||
|
||||
add_task(async function test_devicelist_pushendpointexpired() {
|
||||
const deviceId = "mydeviceid";
|
||||
|
@ -620,7 +620,7 @@ add_task(async function test_accessTokenWithSessionToken() {
|
||||
access_token:
|
||||
"43793fdfffec22eb39fc3c44ed09193a6fde4c24e5d6a73f73178597b268af69",
|
||||
token_type: "bearer",
|
||||
scope: "https://identity.mozilla.com/apps/oldsync",
|
||||
scope: SCOPE_APP_SYNC,
|
||||
expires_in: 21600,
|
||||
auth_at: 1589579900,
|
||||
});
|
||||
@ -634,7 +634,7 @@ add_task(async function test_accessTokenWithSessionToken() {
|
||||
let sessionTokenHex =
|
||||
"0599c36ebb5cad6feb9285b9547b65342b5434d55c07b33bffd4307ab8f82dc4";
|
||||
let clientId = "5882386c6d801776";
|
||||
let scope = "https://identity.mozilla.com/apps/oldsync";
|
||||
let scope = SCOPE_APP_SYNC;
|
||||
let ttl = 100;
|
||||
let result = await client.accessTokenWithSessionToken(
|
||||
sessionTokenHex,
|
||||
|
@ -8,16 +8,12 @@ const { getFxAccountsSingleton } = ChromeUtils.importESModule(
|
||||
);
|
||||
const fxAccounts = getFxAccountsSingleton();
|
||||
|
||||
const { ON_NEW_DEVICE_ID, PREF_ACCOUNT_ROOT } = ChromeUtils.importESModule(
|
||||
"resource://gre/modules/FxAccountsCommon.sys.mjs"
|
||||
const { CLIENT_IS_THUNDERBIRD, ON_NEW_DEVICE_ID, PREF_ACCOUNT_ROOT } =
|
||||
ChromeUtils.importESModule("resource://gre/modules/FxAccountsCommon.sys.mjs");
|
||||
const { TestUtils } = ChromeUtils.importESModule(
|
||||
"resource://testing-common/TestUtils.sys.mjs"
|
||||
);
|
||||
|
||||
function promiseObserved(topic) {
|
||||
return new Promise(res => {
|
||||
Services.obs.addObserver(res, topic);
|
||||
});
|
||||
}
|
||||
|
||||
_("Misc tests for FxAccounts.device");
|
||||
|
||||
fxAccounts.device._checkRemoteCommandsUpdateNeeded = async () => false;
|
||||
@ -90,9 +86,16 @@ add_task(async function test_reset() {
|
||||
.callsFake(async () => {
|
||||
return { id: "foo" };
|
||||
});
|
||||
const notifyPromise = TestUtils.topicObserved(ON_NEW_DEVICE_ID);
|
||||
await fxAccounts._internal.setSignedInUser(credentials);
|
||||
// wait for device registration to complete.
|
||||
await promiseObserved(ON_NEW_DEVICE_ID);
|
||||
await notifyPromise;
|
||||
if (!CLIENT_IS_THUNDERBIRD) {
|
||||
// Firefox fires the notification twice - once during `setSignedInUser` and
|
||||
// once after it returns. It's the second notification we need to wait for.
|
||||
// Thunderbird, OTOH, fires only once during `setSignedInUser` and that's
|
||||
// what we need to wait for.
|
||||
await TestUtils.topicObserved(ON_NEW_DEVICE_ID);
|
||||
}
|
||||
ok(!Services.prefs.prefHasUserValue(testPref));
|
||||
// signing the user out should reset the name pref.
|
||||
const namePref = PREF_ACCOUNT_ROOT + "device.name";
|
||||
|
@ -40,7 +40,7 @@ add_task(async function test_derive_legacy_sync_key_test_vector() {
|
||||
const uid = "aeaa1725c7a24ff983c6295725d5fc9b";
|
||||
const kB = "eaf9570b7219a4187d3d6bf3cec2770c2e0719b7cc0dfbb38243d6f1881675e9";
|
||||
const scopedKeyMetadata = {
|
||||
identifier: "https://identity.mozilla.com/apps/oldsync",
|
||||
identifier: SCOPE_APP_SYNC,
|
||||
keyRotationTimestamp: 1510726317123,
|
||||
keyRotationSecret:
|
||||
"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
@ -49,7 +49,7 @@ add_task(async function test_derive_legacy_sync_key_test_vector() {
|
||||
const scopedKey = await keys._deriveLegacyScopedKey(
|
||||
uid,
|
||||
CommonUtils.hexToBytes(kB),
|
||||
"https://identity.mozilla.com/apps/oldsync",
|
||||
SCOPE_APP_SYNC,
|
||||
scopedKeyMetadata
|
||||
);
|
||||
|
||||
@ -71,8 +71,8 @@ add_task(async function test_derive_multiple_keys_at_once() {
|
||||
keyRotationSecret:
|
||||
"517d478cb4f994aa69930416648a416fdaa1762c5abf401a2acf11a0f185e98d",
|
||||
},
|
||||
"https://identity.mozilla.com/apps/oldsync": {
|
||||
identifier: "https://identity.mozilla.com/apps/oldsync",
|
||||
[SCOPE_APP_SYNC]: {
|
||||
identifier: SCOPE_APP_SYNC,
|
||||
keyRotationTimestamp: 1510726318123,
|
||||
keyRotationSecret:
|
||||
"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
@ -91,7 +91,7 @@ add_task(async function test_derive_multiple_keys_at_once() {
|
||||
kid: "1510726317-tUkxiR1lTlFrTgkF0tJidA",
|
||||
k: "TYK6Hmj86PfKiqsk9DZmX61nxk9VsExGrwo94HP-0wU",
|
||||
},
|
||||
"https://identity.mozilla.com/apps/oldsync": {
|
||||
[SCOPE_APP_SYNC]: {
|
||||
kty: "oct",
|
||||
kid: "1510726318123-IqQv4onc7VcVE1kTQkyyOw",
|
||||
k: "DW_ll5GwX6SJ5GPqJVAuMUP2t6kDqhUulc2cbt26xbTcaKGQl-9l29FHAQ7kUiJETma4s9fIpEHrt909zgFang",
|
||||
@ -103,17 +103,17 @@ add_task(function test_check_valid_scoped_keys() {
|
||||
const keys = new FxAccountsKeys(null);
|
||||
add_task(function test_missing_key_data() {
|
||||
const scopedKeys = {
|
||||
"https://identity.mozilla.com/apps/oldsync": {
|
||||
[SCOPE_APP_SYNC]: {
|
||||
kty: "oct",
|
||||
kid: "1510726318123-IqQv4onc7VcVE1kTQkyyOw",
|
||||
scope: "https://identity.mozilla.com/apps/oldsync",
|
||||
scope: SCOPE_APP_SYNC,
|
||||
},
|
||||
};
|
||||
Assert.equal(keys.validScopedKeys(scopedKeys), false);
|
||||
});
|
||||
add_task(function test_unexpected_scope() {
|
||||
const scopedKeys = {
|
||||
"https://identity.mozilla.com/apps/oldsync": {
|
||||
[SCOPE_APP_SYNC]: {
|
||||
kty: "oct",
|
||||
kid: "1510726318123-IqQv4onc7VcVE1kTQkyyOw",
|
||||
k: "DW_ll5GwX6SJ5GPqJVAuMUP2t6kDqhUulc2cbt26xbTcaKGQl-9l29FHAQ7kUiJETma4s9fIpEHrt909zgFang",
|
||||
@ -124,59 +124,59 @@ add_task(function test_check_valid_scoped_keys() {
|
||||
});
|
||||
add_task(function test_not_oct_key() {
|
||||
const scopedKeys = {
|
||||
"https://identity.mozilla.com/apps/oldsync": {
|
||||
[SCOPE_APP_SYNC]: {
|
||||
// Should be "oct"!
|
||||
kty: "EC",
|
||||
kid: "1510726318123-IqQv4onc7VcVE1kTQkyyOw",
|
||||
k: "DW_ll5GwX6SJ5GPqJVAuMUP2t6kDqhUulc2cbt26xbTcaKGQl-9l29FHAQ7kUiJETma4s9fIpEHrt909zgFang",
|
||||
scope: "https://identity.mozilla.com/apps/oldsync",
|
||||
scope: SCOPE_APP_SYNC,
|
||||
},
|
||||
};
|
||||
Assert.equal(keys.validScopedKeys(scopedKeys), false);
|
||||
});
|
||||
add_task(function test_invalid_kid_not_timestamp() {
|
||||
const scopedKeys = {
|
||||
"https://identity.mozilla.com/apps/oldsync": {
|
||||
[SCOPE_APP_SYNC]: {
|
||||
kty: "oct",
|
||||
// Does not have the timestamp!
|
||||
kid: "IqQv4onc7VcVE1kTQkyyOw",
|
||||
k: "DW_ll5GwX6SJ5GPqJVAuMUP2t6kDqhUulc2cbt26xbTcaKGQl-9l29FHAQ7kUiJETma4s9fIpEHrt909zgFang",
|
||||
scope: "https://identity.mozilla.com/apps/oldsync",
|
||||
scope: SCOPE_APP_SYNC,
|
||||
},
|
||||
};
|
||||
Assert.equal(keys.validScopedKeys(scopedKeys), false);
|
||||
});
|
||||
add_task(function test_invalid_kid_not_valid_timestamp() {
|
||||
const scopedKeys = {
|
||||
"https://identity.mozilla.com/apps/oldsync": {
|
||||
[SCOPE_APP_SYNC]: {
|
||||
kty: "oct",
|
||||
// foo is not a valid timestamp!
|
||||
kid: "foo-IqQv4onc7VcVE1kTQkyyOw",
|
||||
k: "DW_ll5GwX6SJ5GPqJVAuMUP2t6kDqhUulc2cbt26xbTcaKGQl-9l29FHAQ7kUiJETma4s9fIpEHrt909zgFang",
|
||||
scope: "https://identity.mozilla.com/apps/oldsync",
|
||||
scope: SCOPE_APP_SYNC,
|
||||
},
|
||||
};
|
||||
Assert.equal(keys.validScopedKeys(scopedKeys), false);
|
||||
});
|
||||
add_task(function test_invalid_kid_not_b64_fingerprint() {
|
||||
const scopedKeys = {
|
||||
"https://identity.mozilla.com/apps/oldsync": {
|
||||
[SCOPE_APP_SYNC]: {
|
||||
kty: "oct",
|
||||
// fingerprint not a valid base64 encoded string.
|
||||
kid: "1510726318123-notvalidb64][",
|
||||
k: "DW_ll5GwX6SJ5GPqJVAuMUP2t6kDqhUulc2cbt26xbTcaKGQl-9l29FHAQ7kUiJETma4s9fIpEHrt909zgFang",
|
||||
scope: "https://identity.mozilla.com/apps/oldsync",
|
||||
scope: SCOPE_APP_SYNC,
|
||||
},
|
||||
};
|
||||
Assert.equal(keys.validScopedKeys(scopedKeys), false);
|
||||
});
|
||||
add_task(function test_invalid_k_not_base64() {
|
||||
const scopedKeys = {
|
||||
"https://identity.mozilla.com/apps/oldsync": {
|
||||
[SCOPE_APP_SYNC]: {
|
||||
kty: "oct",
|
||||
kid: "1510726318123-IqQv4onc7VcVE1kTQkyyOw",
|
||||
k: "notavalidb64[]",
|
||||
scope: "https://identity.mozilla.com/apps/oldsync",
|
||||
scope: SCOPE_APP_SYNC,
|
||||
},
|
||||
};
|
||||
Assert.equal(keys.validScopedKeys(scopedKeys), false);
|
||||
@ -192,11 +192,11 @@ add_task(function test_check_valid_scoped_keys() {
|
||||
scope: "https://identity.mozilla.com/apps/otherscope",
|
||||
},
|
||||
// Invalid
|
||||
"https://identity.mozilla.com/apps/oldsync": {
|
||||
[SCOPE_APP_SYNC]: {
|
||||
kty: "oct",
|
||||
kid: "1510726318123-IqQv4onc7VcVE1kTQkyyOw",
|
||||
k: "notavalidb64[]",
|
||||
scope: "https://identity.mozilla.com/apps/oldsync",
|
||||
scope: SCOPE_APP_SYNC,
|
||||
},
|
||||
};
|
||||
Assert.equal(keys.validScopedKeys(scopedKeys), false);
|
||||
@ -204,11 +204,11 @@ add_task(function test_check_valid_scoped_keys() {
|
||||
|
||||
add_task(function test_valid_scopedkeys() {
|
||||
const scopedKeys = {
|
||||
"https://identity.mozilla.com/apps/oldsync": {
|
||||
[SCOPE_APP_SYNC]: {
|
||||
kty: "oct",
|
||||
kid: "1510726318123-IqQv4onc7VcVE1kTQkyyOw",
|
||||
k: "DW_ll5GwX6SJ5GPqJVAuMUP2t6kDqhUulc2cbt26xbTcaKGQl-9l29FHAQ7kUiJETma4s9fIpEHrt909zgFang",
|
||||
scope: "https://identity.mozilla.com/apps/oldsync",
|
||||
scope: SCOPE_APP_SYNC,
|
||||
},
|
||||
"https://identity.mozilla.com/apps/otherscope": {
|
||||
kty: "oct",
|
||||
|
@ -17,7 +17,7 @@ const {
|
||||
"resource://gre/modules/FxAccountsOAuth.sys.mjs"
|
||||
);
|
||||
|
||||
const { SCOPE_PROFILE, FX_OAUTH_CLIENT_ID } = ChromeUtils.importESModule(
|
||||
const { SCOPE_PROFILE, OAUTH_CLIENT_ID } = ChromeUtils.importESModule(
|
||||
"resource://gre/modules/FxAccountsCommon.sys.mjs"
|
||||
);
|
||||
|
||||
@ -45,15 +45,15 @@ add_task(function test_begin_oauth_flow() {
|
||||
}
|
||||
});
|
||||
add_task(async function test_begin_oauth_flow_ok() {
|
||||
const scopes = [SCOPE_PROFILE, SCOPE_OLD_SYNC];
|
||||
const scopes = [SCOPE_PROFILE, SCOPE_APP_SYNC];
|
||||
const queryParams = await oauth.beginOAuthFlow(scopes);
|
||||
|
||||
// First verify default query parameters
|
||||
Assert.equal(queryParams.client_id, FX_OAUTH_CLIENT_ID);
|
||||
Assert.equal(queryParams.client_id, OAUTH_CLIENT_ID);
|
||||
Assert.equal(queryParams.action, "email");
|
||||
Assert.equal(queryParams.response_type, "code");
|
||||
Assert.equal(queryParams.access_type, "offline");
|
||||
Assert.equal(queryParams.scope, [SCOPE_PROFILE, SCOPE_OLD_SYNC].join(" "));
|
||||
Assert.equal(queryParams.scope, [SCOPE_PROFILE, SCOPE_APP_SYNC].join(" "));
|
||||
|
||||
// Then, we verify that the state is a valid Base64 value
|
||||
const state = queryParams.state;
|
||||
@ -120,7 +120,7 @@ add_task(function test_complete_oauth_flow() {
|
||||
}),
|
||||
};
|
||||
const oauth = new FxAccountsOAuth(fxaClient);
|
||||
const scopes = [SCOPE_PROFILE, SCOPE_OLD_SYNC];
|
||||
const scopes = [SCOPE_PROFILE, SCOPE_APP_SYNC];
|
||||
const sessionToken = "01abcef12";
|
||||
const queryParams = await oauth.beginOAuthFlow(scopes);
|
||||
try {
|
||||
@ -133,7 +133,7 @@ add_task(function test_complete_oauth_flow() {
|
||||
}
|
||||
});
|
||||
add_task(async function test_jwe_not_returned() {
|
||||
const scopes = [SCOPE_PROFILE, SCOPE_OLD_SYNC];
|
||||
const scopes = [SCOPE_PROFILE, SCOPE_APP_SYNC];
|
||||
const fxaClient = {
|
||||
oauthToken: () =>
|
||||
Promise.resolve({
|
||||
@ -157,15 +157,15 @@ add_task(function test_complete_oauth_flow() {
|
||||
add_task(async function test_complete_oauth_ok() {
|
||||
// First, we initialize some fake values we would typically get
|
||||
// from outside our system
|
||||
const scopes = [SCOPE_PROFILE, SCOPE_OLD_SYNC];
|
||||
const scopes = [SCOPE_PROFILE, SCOPE_APP_SYNC];
|
||||
const oauthCode = "fake oauth code";
|
||||
const sessionToken = "01abcef12";
|
||||
const plainTextScopedKeys = {
|
||||
"https://identity.mozilla.com/apps/oldsync": {
|
||||
[SCOPE_APP_SYNC]: {
|
||||
kty: "oct",
|
||||
kid: "1510726318123-IqQv4onc7VcVE1kTQkyyOw",
|
||||
k: "DW_ll5GwX6SJ5GPqJVAuMUP2t6kDqhUulc2cbt26xbTcaKGQl-9l29FHAQ7kUiJETma4s9fIpEHrt909zgFang",
|
||||
scope: "https://identity.mozilla.com/apps/oldsync",
|
||||
scope: SCOPE_APP_SYNC,
|
||||
},
|
||||
};
|
||||
const fakeAccessToken = "fake access token";
|
||||
@ -280,16 +280,16 @@ add_task(function test_complete_oauth_flow() {
|
||||
add_task(async function test_complete_oauth_invalid_scoped_keys() {
|
||||
// First, we initialize some fake values we would typically get
|
||||
// from outside our system
|
||||
const scopes = [SCOPE_PROFILE, SCOPE_OLD_SYNC];
|
||||
const scopes = [SCOPE_PROFILE, SCOPE_APP_SYNC];
|
||||
const oauthCode = "fake oauth code";
|
||||
const sessionToken = "01abcef12";
|
||||
const invalidScopedKeys = {
|
||||
"https://identity.mozilla.com/apps/oldsync": {
|
||||
[SCOPE_APP_SYNC]: {
|
||||
// ====== This is an invalid key type! Should be "oct", so we will raise an error once we realize
|
||||
kty: "EC",
|
||||
kid: "1510726318123-IqQv4onc7VcVE1kTQkyyOw",
|
||||
k: "DW_ll5GwX6SJ5GPqJVAuMUP2t6kDqhUulc2cbt26xbTcaKGQl-9l29FHAQ7kUiJETma4s9fIpEHrt909zgFang",
|
||||
scope: "https://identity.mozilla.com/apps/oldsync",
|
||||
scope: SCOPE_APP_SYNC,
|
||||
},
|
||||
};
|
||||
const fakeAccessToken = "fake access token";
|
||||
|
@ -72,8 +72,8 @@ const fxAccounts = {
|
||||
fxAccountsClient: {
|
||||
async getScopedKeyData() {
|
||||
return {
|
||||
"https://identity.mozilla.com/apps/oldsync": {
|
||||
identifier: "https://identity.mozilla.com/apps/oldsync",
|
||||
[SCOPE_APP_SYNC]: {
|
||||
identifier: SCOPE_APP_SYNC,
|
||||
keyRotationTimestamp: 12345678,
|
||||
},
|
||||
};
|
||||
@ -151,7 +151,7 @@ add_task(async function testFullFlow() {
|
||||
new TextEncoder().encode(JSON.stringify(epk.publicJWK)),
|
||||
{ pad: false }
|
||||
),
|
||||
scope: "profile https://identity.mozilla.com/apps/oldsync",
|
||||
scope: `profile ${SCOPE_APP_SYNC}`,
|
||||
code_challenge: "chal",
|
||||
code_challenge_method: "S256",
|
||||
},
|
||||
@ -169,7 +169,9 @@ add_task(async function testFullFlow() {
|
||||
const oauthUrl = await promiseSwitchToWebContent;
|
||||
Assert.equal(
|
||||
oauthUrl,
|
||||
`${OAUTH_URI}?client_id=client_id_1&scope=profile+https%3A%2F%2Fidentity.mozilla.com%2Fapps%2Foldsync&email=foo%40bar.com&uid=abcd&channel_id=${CHANNEL_ID}&redirect_uri=urn%3Aietf%3Awg%3Aoauth%3A2.0%3Aoob%3Apair-auth-webchannel`
|
||||
`${OAUTH_URI}?client_id=client_id_1&scope=profile+${encodeURIComponent(
|
||||
SCOPE_APP_SYNC
|
||||
)}&email=foo%40bar.com&uid=abcd&channel_id=${CHANNEL_ID}&redirect_uri=urn%3Aietf%3Awg%3Aoauth%3A2.0%3Aoob%3Apair-auth-webchannel`
|
||||
);
|
||||
|
||||
let pairSuppMetadata = await simulateIncomingWebChannel(
|
||||
@ -199,7 +201,7 @@ add_task(async function testFullFlow() {
|
||||
const generateArgs = generateJWE.firstCall.args;
|
||||
Assert.deepEqual(generateArgs[0], epk.publicJWK);
|
||||
Assert.deepEqual(JSON.parse(new TextDecoder().decode(generateArgs[1])), {
|
||||
"https://identity.mozilla.com/apps/oldsync": {
|
||||
[SCOPE_APP_SYNC]: {
|
||||
kid: "123456",
|
||||
k: KSYNC,
|
||||
kty: "oct",
|
||||
@ -217,10 +219,7 @@ add_task(async function testFullFlow() {
|
||||
Assert.equal(oauthCodeArgs.client_id, "client_id_1");
|
||||
Assert.equal(oauthCodeArgs.access_type, "offline");
|
||||
Assert.equal(oauthCodeArgs.state, "mystate");
|
||||
Assert.equal(
|
||||
oauthCodeArgs.scope,
|
||||
"profile https://identity.mozilla.com/apps/oldsync"
|
||||
);
|
||||
Assert.equal(oauthCodeArgs.scope, `profile ${SCOPE_APP_SYNC}`);
|
||||
Assert.equal(oauthCodeArgs.code_challenge, "chal");
|
||||
Assert.equal(oauthCodeArgs.code_challenge_method, "S256");
|
||||
|
||||
@ -318,7 +317,7 @@ add_task(async function testPairingChannelFailure() {
|
||||
data: {
|
||||
client_id: "client_id_1",
|
||||
state: "mystate",
|
||||
scope: "profile https://identity.mozilla.com/apps/oldsync",
|
||||
scope: `profile ${SCOPE_APP_SYNC}`,
|
||||
code_challenge: "chal",
|
||||
code_challenge_method: "S256",
|
||||
},
|
||||
|
@ -3,8 +3,14 @@
|
||||
|
||||
"use strict";
|
||||
|
||||
const { ON_PROFILE_CHANGE_NOTIFICATION, WEBCHANNEL_ID, log } =
|
||||
ChromeUtils.importESModule("resource://gre/modules/FxAccountsCommon.sys.mjs");
|
||||
const {
|
||||
CLIENT_IS_THUNDERBIRD,
|
||||
ON_PROFILE_CHANGE_NOTIFICATION,
|
||||
WEBCHANNEL_ID,
|
||||
log,
|
||||
} = ChromeUtils.importESModule(
|
||||
"resource://gre/modules/FxAccountsCommon.sys.mjs"
|
||||
);
|
||||
const { CryptoUtils } = ChromeUtils.importESModule(
|
||||
"resource://services-crypto/utils.sys.mjs"
|
||||
);
|
||||
@ -684,6 +690,7 @@ add_task(async function test_helpers_login_with_customize_sync() {
|
||||
});
|
||||
|
||||
add_task(
|
||||
{ skip_if: () => CLIENT_IS_THUNDERBIRD },
|
||||
async function test_helpers_login_with_customize_sync_and_declined_engines() {
|
||||
let configured = false;
|
||||
let helpers = new FxAccountsWebChannelHelpers({
|
||||
|
@ -3,7 +3,7 @@ head = "head.js ../../../common/tests/unit/head_helpers.js ../../../common/tests
|
||||
firefox-appdir = "browser"
|
||||
skip-if = [
|
||||
"os == 'android'",
|
||||
"appname == 'thunderbird'",
|
||||
"appname == 'thunderbird' && !nightly_build"
|
||||
]
|
||||
support-files = [
|
||||
"!/services/common/tests/unit/head_helpers.js",
|
||||
|
@ -20,7 +20,7 @@ import {
|
||||
} from "resource://gre/modules/FxAccounts.sys.mjs";
|
||||
import { FxAccountsClient } from "resource://gre/modules/FxAccountsClient.sys.mjs";
|
||||
|
||||
import { SCOPE_OLD_SYNC } from "resource://gre/modules/FxAccountsCommon.sys.mjs";
|
||||
import { SCOPE_APP_SYNC } from "resource://gre/modules/FxAccountsCommon.sys.mjs";
|
||||
|
||||
// A mock "storage manager" for FxAccounts that doesn't actually write anywhere.
|
||||
export function MockFxaStorageManager() {}
|
||||
@ -119,7 +119,7 @@ export var makeIdentityConfig = function (overrides) {
|
||||
user: {
|
||||
email: "foo",
|
||||
scopedKeys: {
|
||||
[SCOPE_OLD_SYNC]: {
|
||||
[SCOPE_APP_SYNC]: {
|
||||
kid: "1234567890123-u7u7u7u7u7u7u7u7u7u7uw",
|
||||
k: "qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqg",
|
||||
kty: "oct",
|
||||
@ -174,8 +174,8 @@ export var makeFxAccountsInternalMock = function (config) {
|
||||
keys: {
|
||||
getScopedKeys: () =>
|
||||
Promise.resolve({
|
||||
"https://identity.mozilla.com/apps/oldsync": {
|
||||
identifier: "https://identity.mozilla.com/apps/oldsync",
|
||||
[SCOPE_APP_SYNC]: {
|
||||
identifier: SCOPE_APP_SYNC,
|
||||
keyRotationSecret:
|
||||
"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
keyRotationTimestamp: 1510726317123,
|
||||
|
@ -48,7 +48,7 @@ XPCOMUtils.defineLazyPreferenceGetter(
|
||||
// FxAccountsCommon.js doesn't use a "namespace", so create one here.
|
||||
import * as fxAccountsCommon from "resource://gre/modules/FxAccountsCommon.sys.mjs";
|
||||
|
||||
const SCOPE_OLD_SYNC = fxAccountsCommon.SCOPE_OLD_SYNC;
|
||||
const SCOPE_APP_SYNC = fxAccountsCommon.SCOPE_APP_SYNC;
|
||||
|
||||
const OBSERVER_TOPICS = [
|
||||
fxAccountsCommon.ONLOGIN_NOTIFICATION,
|
||||
@ -305,7 +305,7 @@ SyncAuthManager.prototype = {
|
||||
lazy.log.debug("unlockAndVerifyAuthState has an unverified user");
|
||||
return LOGIN_FAILED_LOGIN_REJECTED;
|
||||
}
|
||||
if (await fxa.keys.canGetKeyForScope(SCOPE_OLD_SYNC)) {
|
||||
if (await fxa.keys.canGetKeyForScope(SCOPE_APP_SYNC)) {
|
||||
lazy.log.debug(
|
||||
"unlockAndVerifyAuthState already has (or can fetch) sync keys"
|
||||
);
|
||||
@ -323,7 +323,7 @@ SyncAuthManager.prototype = {
|
||||
// without unlocking the MP or cleared the saved logins, so we've now
|
||||
// lost them - the user will need to reauth before continuing.
|
||||
let result;
|
||||
if (await fxa.keys.canGetKeyForScope(SCOPE_OLD_SYNC)) {
|
||||
if (await fxa.keys.canGetKeyForScope(SCOPE_APP_SYNC)) {
|
||||
result = STATUS_OK;
|
||||
} else {
|
||||
result = LOGIN_FAILED_LOGIN_REJECTED;
|
||||
@ -377,7 +377,7 @@ SyncAuthManager.prototype = {
|
||||
// We need keys for things to work. If we don't have them, just
|
||||
// return null for the token - sync calling unlockAndVerifyAuthState()
|
||||
// before actually syncing will setup the error states if necessary.
|
||||
if (!(await fxa.keys.canGetKeyForScope(SCOPE_OLD_SYNC))) {
|
||||
if (!(await fxa.keys.canGetKeyForScope(SCOPE_APP_SYNC))) {
|
||||
this._log.info(
|
||||
"Unable to fetch keys (master-password locked?), so aborting token fetch"
|
||||
);
|
||||
@ -400,7 +400,7 @@ SyncAuthManager.prototype = {
|
||||
try {
|
||||
this._log.info("Getting sync key");
|
||||
const tokenAndKey = await fxa.getOAuthTokenAndKey({
|
||||
scope: SCOPE_OLD_SYNC,
|
||||
scope: SCOPE_APP_SYNC,
|
||||
ttl,
|
||||
});
|
||||
|
||||
@ -419,7 +419,7 @@ SyncAuthManager.prototype = {
|
||||
"Token server returned 401, retrying token fetch with fresh credentials"
|
||||
);
|
||||
const tokenAndKey = await fxa.getOAuthTokenAndKey({
|
||||
scope: SCOPE_OLD_SYNC,
|
||||
scope: SCOPE_APP_SYNC,
|
||||
ttl,
|
||||
});
|
||||
token = await getToken(tokenAndKey.key, tokenAndKey.token);
|
||||
|
@ -24,6 +24,7 @@ const {
|
||||
ERRNO_INVALID_AUTH_TOKEN,
|
||||
ONLOGIN_NOTIFICATION,
|
||||
ONVERIFIED_NOTIFICATION,
|
||||
SCOPE_APP_SYNC,
|
||||
} = ChromeUtils.importESModule(
|
||||
"resource://gre/modules/FxAccountsCommon.sys.mjs"
|
||||
);
|
||||
@ -66,8 +67,8 @@ MockFxAccountsClient.prototype = {
|
||||
},
|
||||
getScopedKeyData() {
|
||||
return Promise.resolve({
|
||||
"https://identity.mozilla.com/apps/oldsync": {
|
||||
identifier: "https://identity.mozilla.com/apps/oldsync",
|
||||
[SCOPE_APP_SYNC]: {
|
||||
identifier: SCOPE_APP_SYNC,
|
||||
keyRotationSecret:
|
||||
"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
keyRotationTimestamp: 1234567890123,
|
||||
|
Loading…
x
Reference in New Issue
Block a user