tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit 02507fc25181b779f999c0d6994d6774a3825f03
parent 8cbe7e15d29e0de1af3e735c3a1810fe9289deaa
Author: lougeniac64 <5533446+lougeniaC64@users.noreply.github.com>
Date:   Wed, 10 Dec 2025 01:18:26 +0000

Bug 1942925 - Updated FxAccountsClient hosts with auth URI r=markh

Differential Revision: https://phabricator.services.mozilla.com/D265817

Diffstat:
Mservices/fxaccounts/FxAccounts.sys.mjs | 9+++++++++
Mservices/fxaccounts/FxAccountsConfig.sys.mjs | 42++++++++++++++++++++++++++++--------------
Mservices/fxaccounts/tests/xpcshell/test_accounts_config.js | 106+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------
3 files changed, 133 insertions(+), 24 deletions(-)

diff --git a/services/fxaccounts/FxAccounts.sys.mjs b/services/fxaccounts/FxAccounts.sys.mjs @@ -527,6 +527,10 @@ export class FxAccounts { }); } + resetFxAccountsClient() { + this._internal.resetFxAccountsClient(); + } + /** * Remove an OAuth token from the token cache. Callers should call this * after they determine a token is invalid, so a new token will be fetched @@ -852,6 +856,11 @@ FxAccountsInternal.prototype = { } }, + resetFxAccountsClient() { + this._fxAccountsClient = null; + this._oauth = null; + }, + get fxAccountsClient() { if (!this._fxAccountsClient) { this._fxAccountsClient = new lazy.FxAccountsClient(); diff --git a/services/fxaccounts/FxAccountsConfig.sys.mjs b/services/fxaccounts/FxAccountsConfig.sys.mjs @@ -55,24 +55,22 @@ const SYNC_PARAM = "sync"; export var FxAccountsConfig = { async promiseEmailURI(email, entrypoint, extraParams = {}) { - const authParams = await this._getAuthParams(); return this._buildURL("", { + includeAuthParams: true, extraParams: { entrypoint, email, - ...authParams, ...extraParams, }, }); }, async promiseConnectAccountURI(entrypoint, extraParams = {}) { - const authParams = await this._getAuthParams(); return this._buildURL("", { + includeAuthParams: true, extraParams: { entrypoint, action: "email", - ...authParams, ...extraParams, }, }); @@ -134,24 +132,26 @@ export var FxAccountsConfig = { /** * @param path should be parsable by the URL constructor first parameter. * @param {bool} [options.includeDefaultParams] If true include the default search params. - * @param {{[key: string]: string}} [options.extraParams] Additionnal search params. + * @param {bool} [options.includeAuthParams] If true include the auth params. + * @param {[key: string]: string} [options.extraParams] Additionnal search params. * @param {bool} [options.addAccountIdentifiers] if true we add the current logged-in user uid and email to the search params. */ async _buildURL( path, { includeDefaultParams = true, + includeAuthParams = false, extraParams = {}, addAccountIdentifiers = false, } ) { await this.ensureConfigured(); const url = new URL(path, lazy.ROOT_URL); - if (lazy.REQUIRES_HTTPS && url.protocol != "https:") { - throw new Error("Firefox Accounts server must use HTTPS"); - } + this.ensureHTTPS(url.protocol); + const authParams = includeAuthParams ? await this._getAuthParams() : {}; const params = { ...(includeDefaultParams ? this.defaultParams : null), + ...authParams, ...extraParams, }; for (let [k, v] of Object.entries(params)) { @@ -168,6 +168,12 @@ export var FxAccountsConfig = { return url.href; }, + ensureHTTPS(protocol) { + if (lazy.REQUIRES_HTTPS && protocol != "https:") { + throw new Error("Firefox Accounts server must use HTTPS"); + } + }, + async _buildURLFromString(href, extraParams = {}) { const url = new URL(href); for (let [k, v] of Object.entries(extraParams)) { @@ -177,15 +183,15 @@ export var FxAccountsConfig = { }, resetConfigURLs() { - let autoconfigURL = this.getAutoConfigURL(); - if (autoconfigURL) { - return; - } - // They have the autoconfig uri pref set, so we clear all the prefs that we - // will have initialized, which will leave them pointing at production. + // We unconditionally reset all the prefs, which will point them at prod. If the autoconfig URL is not set, + // these will be used next sign in. If the autoconfig pref *is* set then as we start the signin flow we + // will reconfigure all the prefs we just restored to whereever that autoconfig pref points now. for (let pref of CONFIG_PREFS) { Services.prefs.clearUserPref(pref); } + // Reset FxAccountsClient + lazy.fxAccounts.resetFxAccountsClient(); + // Reset the webchannel. lazy.EnsureFxAccountsWebChannel(); }, @@ -207,6 +213,8 @@ export var FxAccountsConfig = { }, async ensureConfigured() { + // We don't want to update any configuration if we are already signed in, + // or in the process of signing in. let isSignedIn = !!(await this.getSignedInUser()); if (!isSignedIn) { await this.updateConfigURLs(); @@ -246,6 +254,9 @@ export var FxAccountsConfig = { async updateConfigURLs() { let rootURL = this.getAutoConfigURL(); if (!rootURL) { + // just because there is currently no autoconfig URL doesn't mean all the dependent + // URLs are correctly set. + this.resetConfigURLs(); return; } const config = await this.fetchConfigDocument(rootURL); @@ -281,6 +292,9 @@ export var FxAccountsConfig = { ); Services.prefs.setStringPref("identity.fxaccounts.remote.root", rootURL); + // Reset FxAccountsClient + lazy.fxAccounts.resetFxAccountsClient(); + // Ensure the webchannel is pointed at the correct uri lazy.EnsureFxAccountsWebChannel(); } catch (e) { diff --git a/services/fxaccounts/tests/xpcshell/test_accounts_config.js b/services/fxaccounts/tests/xpcshell/test_accounts_config.js @@ -3,20 +3,37 @@ "use strict"; +const lazy = {}; + const { FxAccounts } = ChromeUtils.importESModule( "resource://gre/modules/FxAccounts.sys.mjs" ); -add_task(async function test_non_https_remote_server_uri() { - Services.prefs.setStringPref( - "identity.fxaccounts.remote.root", - "http://example.com/" - ); - await Assert.rejects( - FxAccounts.config.promiseConnectAccountURI(), - /Firefox Accounts server must use HTTPS/ - ); - Services.prefs.clearUserPref("identity.fxaccounts.remote.root"); +ChromeUtils.defineLazyGetter(lazy, "fxAccounts", () => { + return ChromeUtils.importESModule( + "resource://gre/modules/FxAccounts.sys.mjs" + ).getFxAccountsSingleton(); +}); + +ChromeUtils.defineESModuleGetters(lazy, { + FxAccountsConfig: "resource://gre/modules/FxAccountsConfig.sys.mjs", +}); + +add_task(async function test_non_https_with_requireHttps_false() { + Services.prefs.setBoolPref("identity.fxaccounts.allowHttp", true); + + FxAccounts.config.ensureHTTPS("http://"); + Assert.ok(true, "`ensureHTTPS did not throw an error"); + + Services.prefs.clearUserPref("identity.fxaccounts.allowHttp"); +}); + +add_task(async function test_non_https_with_requireHttps_true() { + try { + FxAccounts.config.ensureHTTPS("http://"); + } catch (error) { + Assert.ok(error.message, "Firefox Accounts server must use HTTPS"); + } }); add_task(async function test_is_production_config() { @@ -39,3 +56,72 @@ add_task(async function test_is_production_config() { Assert.ok(!FxAccounts.config.isProductionConfig()); Services.prefs.clearUserPref("identity.sync.tokenserver.uri"); }); + +add_task(async function test_reset_fxAccounts_singleton_client() { + Services.prefs.setStringPref("identity.fxaccounts.autoconfig.uri", ""); + let defaultHostUri = "https://api.accounts.firefox.com/v1"; + let alt = "x.net"; + let altHostUri = `https://api-accounts.${alt}/v1`; + + let fetchConfig = lazy.FxAccountsConfig.fetchConfigDocument; + lazy.FxAccountsConfig.fetchConfigDocument = function () { + return { + auth_server_base_url: altHostUri, + oauth_server_base_url: `https://oauth.${alt}`, + pairing_server_base_uri: `wss://x.channelserver.nonprod.cloudops.mozgcp.net`, + profile_server_base_url: `https://profile.${alt}`, + sync_tokenserver_base_url: `https://token.${alt}`, + }; + }; + + // Check that the host points to the default host + Assert.equal(lazy.fxAccounts._internal.fxAccountsClient.host, defaultHostUri); + + Services.prefs.setStringPref( + "identity.fxaccounts.autoconfig.uri", + "http://x" + ); + await lazy.FxAccountsConfig.updateConfigURLs(); + + // Check that the host points to the preset auth server URL + Assert.equal(lazy.fxAccounts._internal.fxAccountsClient.host, altHostUri); + + lazy.FxAccountsConfig.resetConfigURLs(); + + // Check that `resetConfigURLs` clears prefs + let clearedRootPref = Services.prefs.getStringPref( + "identity.fxaccounts.remote.root" + ); + Assert.equal(clearedRootPref, "https://accounts.firefox.com/"); + + let clearedAuthPref = Services.prefs.getStringPref( + "identity.fxaccounts.auth.uri" + ); + Assert.equal(clearedAuthPref, "https://api.accounts.firefox.com/v1"); + + let clearedOauthPref = Services.prefs.getStringPref( + "identity.fxaccounts.remote.oauth.uri" + ); + Assert.equal(clearedOauthPref, "https://oauth.accounts.firefox.com/v1"); + + let clearedProfilePref = Services.prefs.getStringPref( + "identity.fxaccounts.remote.profile.uri" + ); + Assert.equal(clearedProfilePref, "https://profile.accounts.firefox.com/v1"); + + let clearedPairingPref = Services.prefs.getStringPref( + "identity.fxaccounts.remote.pairing.uri" + ); + Assert.equal(clearedPairingPref, "wss://channelserver.services.mozilla.com"); + + let clearedTokenServerPref = Services.prefs.getStringPref( + "identity.sync.tokenserver.uri" + ); + Assert.equal( + clearedTokenServerPref, + "https://token.services.mozilla.com/1.0/sync/1.5" + ); + + lazy.FxAccountsConfig.fetchConfigDocument = fetchConfig; + Services.prefs.clearUserPref("identity.fxaccounts.autoconfig.uri"); +});