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:
Geoff Lankow 2024-06-19 02:39:37 +00:00
parent a2558c2be1
commit 7118d9b96b
21 changed files with 215 additions and 184 deletions

View File

@ -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
);

View File

@ -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;
}

View File

@ -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

View File

@ -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 };

View File

@ -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 {

View File

@ -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;

View File

@ -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,
};
},

View File

@ -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",

View File

@ -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(),
},
{

View File

@ -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",

View File

@ -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";

View File

@ -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,

View File

@ -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";

View File

@ -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",

View File

@ -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";

View File

@ -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",
},

View File

@ -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({

View File

@ -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",

View File

@ -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,

View File

@ -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);

View File

@ -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,