forked from codechefPesuecc/CodeChef-PESUECC-Chapter
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtoken.test.ts
More file actions
88 lines (76 loc) · 3.19 KB
/
Copy pathtoken.test.ts
File metadata and controls
88 lines (76 loc) · 3.19 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
import { describe, it, expect, beforeAll, afterEach, vi } from "vitest";
import { createSessionToken, readSessionToken } from "./token";
beforeAll(() => {
process.env.AUTH_SECRET = "test-secret-for-unit-tests";
});
describe("session token", () => {
it("round-trips the user id and epoch", () => {
const token = createSessionToken("user-123", 7);
expect(readSessionToken(token)).toEqual({ userId: "user-123", epoch: 7 });
});
it("rejects a tampered signature", () => {
const token = createSessionToken("user-123", 0);
const flipped = token.endsWith("aa")
? token.slice(0, -2) + "bb"
: token.slice(0, -2) + "aa";
expect(readSessionToken(flipped)).toBeNull();
});
it("rejects a forged payload (re-used signature)", () => {
const token = createSessionToken("user-123", 0);
const dot = token.lastIndexOf(".");
const [uid, epoch, expiry] = token.slice(0, dot).split(":");
void uid;
const forged = `evil:${epoch}:${expiry}${token.slice(dot)}`;
expect(readSessionToken(forged)).toBeNull();
});
it("rejects malformed tokens", () => {
expect(readSessionToken("garbage")).toBeNull();
expect(readSessionToken("")).toBeNull();
expect(readSessionToken("a.b")).toBeNull();
});
it("rejects an expired token", () => {
vi.useFakeTimers();
vi.setSystemTime(new Date("2020-01-01T00:00:00Z"));
const token = createSessionToken("user-123", 0);
// 60 days later — well past the 30-day max age.
vi.setSystemTime(new Date("2020-03-01T00:00:00Z"));
expect(readSessionToken(token)).toBeNull();
vi.useRealTimers();
});
it("is bound to the epoch — a different epoch is a different token", () => {
const a = createSessionToken("user-123", 0);
const b = createSessionToken("user-123", 1);
expect(a).not.toBe(b);
expect(readSessionToken(a)?.epoch).toBe(0);
expect(readSessionToken(b)?.epoch).toBe(1);
});
});
describe("AUTH_SECRET production guard", () => {
// stubEnv sidesteps the read-only NODE_ENV type and auto-restores on unstub,
// so these env changes don't leak into the other tests.
afterEach(() => {
vi.unstubAllEnvs();
});
it("throws in production when AUTH_SECRET is unset", () => {
vi.stubEnv("NODE_ENV", "production");
vi.stubEnv("AUTH_SECRET", undefined);
expect(() => createSessionToken("user-123", 0)).toThrow(/AUTH_SECRET/);
});
it("throws in production when AUTH_SECRET is still the dev default", () => {
vi.stubEnv("NODE_ENV", "production");
vi.stubEnv("AUTH_SECRET", "dev-insecure-change-me-in-production");
expect(() => createSessionToken("user-123", 0)).toThrow(/AUTH_SECRET/);
});
it("signs normally in production once AUTH_SECRET is set", () => {
vi.stubEnv("NODE_ENV", "production");
vi.stubEnv("AUTH_SECRET", "a-real-production-secret");
const token = createSessionToken("user-123", 3);
expect(readSessionToken(token)).toEqual({ userId: "user-123", epoch: 3 });
});
it("falls back to the dev key outside production", () => {
vi.stubEnv("NODE_ENV", "test");
vi.stubEnv("AUTH_SECRET", undefined);
const token = createSessionToken("user-123", 0);
expect(readSessionToken(token)).toEqual({ userId: "user-123", epoch: 0 });
});
});