Skip to content

Commit 92f3ec0

Browse files
Implement hashed user ID cookie for analytics on Gitpod domains (#20231)
* Set hashed user ID cookie on JWT refresh for specific Gitpod domains * refactor: Update setHashedUserIdCookie method in session handler for testing purposes * attempt 2 to fix test * refactor: Clear gitpod_hashed_user_id cookie after logout
1 parent fdbf605 commit 92f3ec0

File tree

3 files changed

+39
-32
lines changed

3 files changed

+39
-32
lines changed

components/server/src/analytics-controller.ts

Lines changed: 0 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ import { Config } from "./config";
1818
import { RateLimited } from "./api/rate-limited";
1919
import { RateLimitter } from "./rate-limitter";
2020
import { RateLimiterRes } from "rate-limiter-flexible";
21-
import * as crypto from "crypto";
2221

2322
@injectable()
2423
export class AnalyticsController {
@@ -70,7 +69,6 @@ export class AnalyticsController {
7069
const clientHeaderFields = toClientHeaderFields(req);
7170
const event = req.body as RemoteIdentifyMessage;
7271
this.identifyUser(req.user.id, event, clientHeaderFields);
73-
this.setHashedUserIdCookie(req.user.id, req, res);
7472
res.sendStatus(200);
7573
} catch (e) {
7674
console.error("failed to identify user", e);
@@ -179,34 +177,4 @@ export class AnalyticsController {
179177
throw e;
180178
}
181179
}
182-
183-
private setHashedUserIdCookie(userId: string, req: express.Request, res: express.Response): void {
184-
const hashedUserId = crypto.createHash("md5").update(userId).digest("hex");
185-
const oneYearInSeconds = 365 * 24 * 60 * 60;
186-
187-
/**
188-
* This implementation is inspired by isGitpodIo() from /workspace/gitpod/components/dashboard/src/utils.ts
189-
* We're using a server-side equivalent here because:
190-
* 1. The original function is client-side code using window.location
191-
* 2. This is server-side code that needs to use the request object
192-
* 3. We need to determine the appropriate domain for setting the cookie
193-
*/
194-
const hostname = req.hostname;
195-
if (
196-
hostname === "gitpod.io" ||
197-
hostname === "gitpod-staging.com" ||
198-
hostname.endsWith("gitpod-dev.com") ||
199-
hostname.endsWith("gitpod-io-dev.com")
200-
) {
201-
const domain = `.${hostname}`;
202-
203-
res.cookie("gitpod_hashed_user_id", hashedUserId, {
204-
domain: domain,
205-
maxAge: oneYearInSeconds * 1000, // Convert to milliseconds
206-
httpOnly: true,
207-
secure: true,
208-
sameSite: "lax",
209-
});
210-
}
211-
}
212180
}

components/server/src/session-handler.spec.db.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@ describe("SessionHandler", () => {
5656
beforeEach(async () => {
5757
container = createTestContainer();
5858
sessionHandler = container.get(SessionHandler);
59+
(sessionHandler as any).setHashedUserIdCookie = () => {
60+
return;
61+
};
5962
jwtSessionHandler = sessionHandler.jwtSessionConvertor();
6063
const userService = container.get(UserService);
6164
// insert some users to the DB to reproduce INC-379

components/server/src/session-handler.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import express from "express";
88
import { inject, injectable } from "inversify";
99
import websocket from "ws";
10+
import * as crypto from "crypto";
1011

1112
import { User } from "@gitpod/gitpod-protocol";
1213
import { log } from "@gitpod/gitpod-protocol/lib/util/logging";
@@ -81,6 +82,8 @@ export class SessionHandler {
8182
}
8283
}
8384

85+
this.setHashedUserIdCookie(req, res);
86+
8487
res.status(200);
8588
res.send("User session already has a valid JWT session.");
8689
};
@@ -230,6 +233,39 @@ export class SessionHandler {
230233
sameSite,
231234
secure,
232235
});
236+
res.clearCookie("gitpod_hashed_user_id", {
237+
domain: `.${res.req.hostname}`,
238+
httpOnly: true,
239+
secure: true,
240+
sameSite: "lax",
241+
});
242+
}
243+
244+
private setHashedUserIdCookie(req: express.Request, res: express.Response): void {
245+
const user = req.user as User;
246+
if (!user) return;
247+
248+
const hostname = req.hostname;
249+
if (
250+
hostname === "gitpod.io" ||
251+
hostname === "gitpod-staging.com" ||
252+
hostname.endsWith("gitpod-dev.com") ||
253+
hostname.endsWith("gitpod-io-dev.com")
254+
) {
255+
const existingHashedId = req.cookies["gitpod_hashed_user_id"];
256+
if (!existingHashedId) {
257+
const hashedUserId = crypto.createHash("md5").update(user.id).digest("hex");
258+
const oneYearInMilliseconds = 365 * 24 * 60 * 60 * 1000;
259+
260+
res.cookie("gitpod_hashed_user_id", hashedUserId, {
261+
domain: `.${hostname}`,
262+
maxAge: oneYearInMilliseconds,
263+
httpOnly: true,
264+
secure: true,
265+
sameSite: "lax",
266+
});
267+
}
268+
}
233269
}
234270
}
235271

0 commit comments

Comments
 (0)