fix: support Discord sign-in behind a trusted TLS proxy

This commit is contained in:
syntaxbullet
2026-09-07 11:50:22 +02:00
parent c7aa5a1c65
commit 50d7838de3
4 changed files with 36 additions and 1 deletions

View File

@@ -55,6 +55,32 @@ beforeEach(() => {
afterEach(() => sqlite.close());
describe("Discord sign-in and sessions", () => {
test("trusted TLS proxy supports sign-in and secure callback cookies", async () => {
const publicOrigin = "https://habits.example";
const proxyApp = createApi(db, { ...config, origin: publicOrigin, trustProxy: true }, request, () => timestamp);
const response = await proxyApp.request("http://habits.example/api/auth/discord", { headers: { "X-Forwarded-Proto": "https" } });
const location = new URL(response.headers.get("Location")!);
expect(location.origin).toBe("https://discord.com");
expect(location.searchParams.get("redirect_uri")).toBe(`${publicOrigin}/api/auth/discord/callback`);
expect(response.headers.get("Set-Cookie")).toContain("Secure");
const callback = await proxyApp.request(`http://habits.example/api/auth/discord/callback?state=${location.searchParams.get("state")}&code=test-code`, {
headers: { "X-Forwarded-Proto": "https", Cookie: cookie(response, "__Host-minabot_oauth") },
});
expect(cookie(callback, "__Host-minabot_session")).not.toBe("");
expect(callback.headers.get("Set-Cookie")).toContain("Secure");
});
test("forwarded protocol is opt-in and cannot override the actual hostname", async () => {
for (const [trustProxy, host] of [[false, "habits.example"], [true, "wrong.example"]] as const) {
const proxyApp = createApi(db, { ...config, origin: "https://habits.example", trustProxy }, request, () => timestamp);
const response = await proxyApp.request(`http://${host}/api/auth/discord`, {
headers: { "X-Forwarded-Proto": "https", "X-Forwarded-Host": "habits.example" },
});
expect(new URL(response.headers.get("Location")!).origin).toBe("https://habits.example");
expect(response.headers.get("Set-Cookie")).toBeNull();
}
});
test("me requires a valid session and health stays public", async () => {
for (const value of ["", "minabot_session=malformed", `minabot_session=${"a".repeat(43)}`]) {
const response = await app.request(`${origin}/api/me`, { headers: { Cookie: value } });