From dba30a4434dc08875cb99d742d58948d138c93ee Mon Sep 17 00:00:00 2001 From: Sergey Petushkov Date: Mon, 21 Jul 2025 16:46:17 +0200 Subject: [PATCH 1/2] fix(compass-web): adjust sandbox code to account for backend changes --- configs/webpack-config-compass/src/index.ts | 3 ++ .../compass-web/scripts/electron-proxy.js | 34 +++++-------------- 2 files changed, 12 insertions(+), 25 deletions(-) diff --git a/configs/webpack-config-compass/src/index.ts b/configs/webpack-config-compass/src/index.ts index 4c0254303bc..c5774688797 100644 --- a/configs/webpack-config-compass/src/index.ts +++ b/configs/webpack-config-compass/src/index.ts @@ -45,6 +45,9 @@ const sharedIgnoreWarnings: NonNullable = [ /the request of a dependency is an expression/, // Optional, platform-specific dependencies (mostly from driver) /Module not found.+?(mongo_crypt_v1.(dll|so|dylib)|@mongodb-js\/zstd|aws-crt|gcp-metadata)/, + // Optional, comes from emotion trying to (safely) use react apis that we + // don't have in React 17 + /export 'useInsertionEffect'/, ]; const sharedResolveOptions = ( diff --git a/packages/compass-web/scripts/electron-proxy.js b/packages/compass-web/scripts/electron-proxy.js index 5481fa54b83..e27f1c52b8e 100644 --- a/packages/compass-web/scripts/electron-proxy.js +++ b/packages/compass-web/scripts/electron-proxy.js @@ -118,12 +118,15 @@ class AtlasCloudAuthenticator { * @returns {Promise} */ async #getCloudSessionCookies() { - const cloudHostCookies = await session.defaultSession.cookies.get({ - domain: CLOUD_CONFIG_VARIANTS === 'local' ? 'localhost' : 'mongodb.com', - }); - return cloudHostCookies.map((cookie) => { - return `${cookie.name}=${cookie.value}`; - }); + const tld = CLOUD_CONFIG_VARIANTS === 'local' ? 'localhost' : 'mongodb.com'; + const cloudHostCookies = (await session.defaultSession.cookies.get({})) + .filter((cookie) => { + return cookie.domain?.endsWith(tld) ?? true; + }) + .map((cookie) => { + return `${cookie.name}=${cookie.value}`; + }); + return cloudHostCookies; } /** @@ -135,18 +138,10 @@ class AtlasCloudAuthenticator { } async #fetch(path, init) { - let csrfHeaders; - if ( - init?.method && - /^(GET|HEAD|OPTIONS|TRACE)$/i.test(init.method) === false - ) { - csrfHeaders = await this.#getCSRFHeaders(); - } return electronFetch(`${CLOUD_ORIGIN}${path}`, { ...init, headers: { ...init?.headers, - ...csrfHeaders, }, }).then(handleRes); } @@ -159,17 +154,6 @@ class AtlasCloudAuthenticator { return new URL(url, 'http://localhost').pathname.startsWith('/v2/'); } - async #getCSRFHeaders() { - const projectId = await this.getProjectId(); - const { csrfToken, csrfTime } = await this.#fetch( - `/v2/${projectId}/params` - ); - return { - ...(csrfToken && { 'X-CSRF-Token': csrfToken }), - ...(csrfTime && { 'X-CSRF-Time': csrfTime }), - }; - } - async getCloudHeaders(hostSubdomain = '') { const cookie = (await this.#getCloudSessionCookies()).join('; '); return { From aea3d365b604fc6ad0b10c672d9feefe4fab6583 Mon Sep 17 00:00:00 2001 From: Sergey Petushkov Date: Mon, 21 Jul 2025 17:24:31 +0200 Subject: [PATCH 2/2] chore(compass-web): utilise the set-cookie header when received in the proxy --- .../compass-web/scripts/electron-proxy.js | 29 +++++++++++++++---- 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/packages/compass-web/scripts/electron-proxy.js b/packages/compass-web/scripts/electron-proxy.js index e27f1c52b8e..c888784e50d 100644 --- a/packages/compass-web/scripts/electron-proxy.js +++ b/packages/compass-web/scripts/electron-proxy.js @@ -303,16 +303,33 @@ expressProxy.use( return req; }, userResHeaderDecorator(headers, _req, res) { - // Cloud backend will try to always set auth cookies on requests, but we - // can't really meaningfully store those in the browser (__secure- ones - // would be ignored anyways), so to avoid polluting storage, we just not - // allow the set-cookie header to propagate - delete headers['set-cookie']; - if (isSignedOutRedirect(headers.location)) { res.statusCode = 403; return {}; } + + // When cloud session expires, cloud backend will send a new set of + // session cookies to make sure that "active" client stays signed in. As + // these proxy requests are not going through the electron fetch, we can + // end up in a situation where electron still keeps the old session + // cookies instead on new ones. When we receive set-cookie header in the + // proxy, we will copy the cookies to the electron session to make sure + // that both are in sync with electron storage that we use as source of + // truth for cookies when creating the fetch request + if (headers['set-cookie']) { + const parsedCookies = headers['set-cookie'].map((cookieStr) => { + const [cookie, ...options] = cookieStr.split(';').map((keyVal) => { + return keyVal.split('='); + }); + const domain = options.find((opt) => { + return opt[0] === 'Domain'; + }); + return { name: cookie[0], value: cookie[1], domain: domain[1] }; + }); + session.defaultSession.cookies.set(parsedCookies); + } + delete headers['set-cookie']; + return headers; }, })