mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-10-27 21:18:30 -05:00
138 lines
4.2 KiB
TypeScript
138 lines
4.2 KiB
TypeScript
import { createCookieSessionStorage } from "react-router";
|
|
import { describe, expect, test } from "vitest";
|
|
import { createAuthSession } from "./session.server";
|
|
|
|
const SECRET = "test-secret";
|
|
|
|
const secureAuthSession = createAuthSession({
|
|
isSecureContext: true,
|
|
secret: SECRET,
|
|
});
|
|
|
|
const legacyStorage = createCookieSessionStorage({
|
|
cookie: {
|
|
name: "__session",
|
|
domain: "sendou.ink",
|
|
path: "/",
|
|
httpOnly: true,
|
|
secrets: [SECRET],
|
|
secure: true,
|
|
},
|
|
});
|
|
|
|
const legacyCookieHeader = async (data: Record<string, unknown>) => {
|
|
const session = await legacyStorage.getSession();
|
|
for (const [key, value] of Object.entries(data)) {
|
|
session.set(key, value);
|
|
}
|
|
return toCookieHeader(await legacyStorage.commitSession(session));
|
|
};
|
|
|
|
const hostOnlyCookieHeader = async (data: Record<string, unknown>) => {
|
|
const session = await secureAuthSession.storage.getSession();
|
|
for (const [key, value] of Object.entries(data)) {
|
|
session.set(key, value);
|
|
}
|
|
return toCookieHeader(await secureAuthSession.storage.commitSession(session));
|
|
};
|
|
|
|
describe("createAuthSession", () => {
|
|
test("issues a host-only __Host- cookie in a secure context", async () => {
|
|
const session = await secureAuthSession.storage.getSession();
|
|
session.set("user", 1);
|
|
|
|
const setCookie = await secureAuthSession.storage.commitSession(session);
|
|
|
|
expect(setCookie.startsWith("__Host-session=")).toBe(true);
|
|
expect(setCookie).toContain("Secure");
|
|
expect(setCookie).toContain("Path=/");
|
|
expect(setCookie).not.toContain("Domain");
|
|
});
|
|
|
|
test("keeps the plain cookie name outside a secure context", () => {
|
|
const authSession = createAuthSession({
|
|
isSecureContext: false,
|
|
secret: SECRET,
|
|
});
|
|
|
|
expect(authSession.cookieName).toBe("__session");
|
|
});
|
|
|
|
test("reads the session from the legacy domain cookie when no host-only cookie exists", async () => {
|
|
const session = await secureAuthSession.storage.getSession(
|
|
await legacyCookieHeader({ user: 1 }),
|
|
);
|
|
|
|
expect(session.get("user")).toBe(1);
|
|
});
|
|
|
|
test("prefers the host-only cookie over the legacy cookie", async () => {
|
|
const cookieHeader = `${await legacyCookieHeader({ user: 1 })}; ${await hostOnlyCookieHeader({ user: 2 })}`;
|
|
|
|
const session = await secureAuthSession.storage.getSession(cookieHeader);
|
|
|
|
expect(session.get("user")).toBe(2);
|
|
});
|
|
});
|
|
|
|
describe("legacySessionMigrationCookies", () => {
|
|
test("returns null without a legacy cookie", async () => {
|
|
const result = await secureAuthSession.legacySessionMigrationCookies(
|
|
await hostOnlyCookieHeader({ user: 1 }),
|
|
);
|
|
|
|
expect(result).toBeNull();
|
|
});
|
|
|
|
test("returns null outside a secure context", async () => {
|
|
const authSession = createAuthSession({
|
|
isSecureContext: false,
|
|
secret: SECRET,
|
|
});
|
|
|
|
const result = await authSession.legacySessionMigrationCookies(
|
|
await legacyCookieHeader({ user: 1 }),
|
|
);
|
|
|
|
expect(result).toBeNull();
|
|
});
|
|
|
|
test("re-issues the legacy session host-only and expires the legacy domain cookie", async () => {
|
|
const result = await secureAuthSession.legacySessionMigrationCookies(
|
|
await legacyCookieHeader({ user: 1, impersonated_user: 2 }),
|
|
);
|
|
|
|
const migrated = await secureAuthSession.storage.getSession(
|
|
toCookieHeader(result!.hostOnly!),
|
|
);
|
|
expect(migrated.get("user")).toBe(1);
|
|
expect(migrated.get("impersonated_user")).toBe(2);
|
|
expect(result!.expireLegacy.startsWith("__session=;")).toBe(true);
|
|
expect(result!.expireLegacy).toContain("Domain=sendou.ink");
|
|
expect(result!.expireLegacy).toContain("Expires=Thu, 01 Jan 1970");
|
|
});
|
|
|
|
test("only expires the legacy cookie when a host-only cookie already exists", async () => {
|
|
const cookieHeader = `${await legacyCookieHeader({ user: 1 })}; ${await hostOnlyCookieHeader({ user: 2 })}`;
|
|
|
|
const result =
|
|
await secureAuthSession.legacySessionMigrationCookies(cookieHeader);
|
|
|
|
expect(result?.hostOnly).toBeNull();
|
|
expect(result?.expireLegacy).toContain("Domain=sendou.ink");
|
|
});
|
|
|
|
test("does not issue a host-only cookie for an empty legacy session", async () => {
|
|
const result = await secureAuthSession.legacySessionMigrationCookies(
|
|
await legacyCookieHeader({}),
|
|
);
|
|
|
|
expect(result?.hostOnly).toBeNull();
|
|
expect(result?.expireLegacy).toContain("Domain=sendou.ink");
|
|
});
|
|
});
|
|
|
|
function toCookieHeader(setCookie: string) {
|
|
return setCookie.split(";")[0];
|
|
}
|