Skip to content

Commit e3a3ffd

Browse files
authored
fix(compass-web): adjust sandbox code for cloud backend and electron changes COMPASS-9569 (#7128)
* fix(compass-web): adjust sandbox code to account for backend changes * chore(compass-web): utilise the set-cookie header when received in the proxy
1 parent 20cb662 commit e3a3ffd

File tree

2 files changed

+35
-31
lines changed

2 files changed

+35
-31
lines changed

configs/webpack-config-compass/src/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ const sharedIgnoreWarnings: NonNullable<Configuration['ignoreWarnings']> = [
4545
/the request of a dependency is an expression/,
4646
// Optional, platform-specific dependencies (mostly from driver)
4747
/Module not found.+?(mongo_crypt_v1.(dll|so|dylib)|@mongodb-js\/zstd|aws-crt|gcp-metadata)/,
48+
// Optional, comes from emotion trying to (safely) use react apis that we
49+
// don't have in React 17
50+
/export 'useInsertionEffect'/,
4851
];
4952

5053
const sharedResolveOptions = (

packages/compass-web/scripts/electron-proxy.js

Lines changed: 32 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -118,12 +118,15 @@ class AtlasCloudAuthenticator {
118118
* @returns {Promise<string[]>}
119119
*/
120120
async #getCloudSessionCookies() {
121-
const cloudHostCookies = await session.defaultSession.cookies.get({
122-
domain: CLOUD_CONFIG_VARIANTS === 'local' ? 'localhost' : 'mongodb.com',
123-
});
124-
return cloudHostCookies.map((cookie) => {
125-
return `${cookie.name}=${cookie.value}`;
126-
});
121+
const tld = CLOUD_CONFIG_VARIANTS === 'local' ? 'localhost' : 'mongodb.com';
122+
const cloudHostCookies = (await session.defaultSession.cookies.get({}))
123+
.filter((cookie) => {
124+
return cookie.domain?.endsWith(tld) ?? true;
125+
})
126+
.map((cookie) => {
127+
return `${cookie.name}=${cookie.value}`;
128+
});
129+
return cloudHostCookies;
127130
}
128131

129132
/**
@@ -135,18 +138,10 @@ class AtlasCloudAuthenticator {
135138
}
136139

137140
async #fetch(path, init) {
138-
let csrfHeaders;
139-
if (
140-
init?.method &&
141-
/^(GET|HEAD|OPTIONS|TRACE)$/i.test(init.method) === false
142-
) {
143-
csrfHeaders = await this.#getCSRFHeaders();
144-
}
145141
return electronFetch(`${CLOUD_ORIGIN}${path}`, {
146142
...init,
147143
headers: {
148144
...init?.headers,
149-
...csrfHeaders,
150145
},
151146
}).then(handleRes);
152147
}
@@ -159,17 +154,6 @@ class AtlasCloudAuthenticator {
159154
return new URL(url, 'http://localhost').pathname.startsWith('/v2/');
160155
}
161156

162-
async #getCSRFHeaders() {
163-
const projectId = await this.getProjectId();
164-
const { csrfToken, csrfTime } = await this.#fetch(
165-
`/v2/${projectId}/params`
166-
);
167-
return {
168-
...(csrfToken && { 'X-CSRF-Token': csrfToken }),
169-
...(csrfTime && { 'X-CSRF-Time': csrfTime }),
170-
};
171-
}
172-
173157
async getCloudHeaders(hostSubdomain = '') {
174158
const cookie = (await this.#getCloudSessionCookies()).join('; ');
175159
return {
@@ -319,16 +303,33 @@ expressProxy.use(
319303
return req;
320304
},
321305
userResHeaderDecorator(headers, _req, res) {
322-
// Cloud backend will try to always set auth cookies on requests, but we
323-
// can't really meaningfully store those in the browser (__secure- ones
324-
// would be ignored anyways), so to avoid polluting storage, we just not
325-
// allow the set-cookie header to propagate
326-
delete headers['set-cookie'];
327-
328306
if (isSignedOutRedirect(headers.location)) {
329307
res.statusCode = 403;
330308
return {};
331309
}
310+
311+
// When cloud session expires, cloud backend will send a new set of
312+
// session cookies to make sure that "active" client stays signed in. As
313+
// these proxy requests are not going through the electron fetch, we can
314+
// end up in a situation where electron still keeps the old session
315+
// cookies instead on new ones. When we receive set-cookie header in the
316+
// proxy, we will copy the cookies to the electron session to make sure
317+
// that both are in sync with electron storage that we use as source of
318+
// truth for cookies when creating the fetch request
319+
if (headers['set-cookie']) {
320+
const parsedCookies = headers['set-cookie'].map((cookieStr) => {
321+
const [cookie, ...options] = cookieStr.split(';').map((keyVal) => {
322+
return keyVal.split('=');
323+
});
324+
const domain = options.find((opt) => {
325+
return opt[0] === 'Domain';
326+
});
327+
return { name: cookie[0], value: cookie[1], domain: domain[1] };
328+
});
329+
session.defaultSession.cookies.set(parsedCookies);
330+
}
331+
delete headers['set-cookie'];
332+
332333
return headers;
333334
},
334335
})

0 commit comments

Comments
 (0)