import { createHmac } from "node:crypto"; import { describe, expect, it } from "vitest"; import { AuthError, resolveIdentity, verifyJwt } from "../src/auth/jwt.js"; function sign(payload: Record, secret = "secret", alg = "HS256"): string { const header = Buffer.from(JSON.stringify({ alg, typ: "JWT" })).toString("base64url"); const body = Buffer.from(JSON.stringify(payload)).toString("base64url"); const signature = createHmac("sha256", secret).update(`${header}.${body}`).digest("base64url"); return `${header}.${body}.${signature}`; } describe("auth", () => { it("verifies a valid HS256 token and resolves identity", () => { const token = sign({ uid: 42, nickname: "小明", exp: Math.floor(Date.now() / 1000) + 60 }); const identity = resolveIdentity( { jwtKey: "secret", jwtAlgorithm: "HS256" }, { headers: { authorization: `Bearer ${token}`, "x-team-id": "9" } }, ); expect(identity).toMatchObject({ uid: "42", nickname: "小明", team_id: "9" }); }); it("rejects missing, expired, tampered, and wrong-algorithm tokens", () => { const auth = { jwtKey: "secret", jwtAlgorithm: "HS256" }; expect(() => resolveIdentity(auth, { headers: {} })).toThrow(AuthError); const expired = sign({ uid: 1, exp: Math.floor(Date.now() / 1000) - 1 }); expect(() => verifyJwt(expired, "secret", "HS256")).toThrow(/过期/); const valid = sign({ uid: 1, exp: Math.floor(Date.now() / 1000) + 60 }); const tampered = `${valid.split(".").slice(0, 2).join(".")}.bad`; expect(() => verifyJwt(tampered, "secret", "HS256")).toThrow(/签名/); const wrongAlg = sign({ uid: 1, exp: Math.floor(Date.now() / 1000) + 60 }, "secret", "HS512"); expect(() => verifyJwt(wrongAlg, "secret", "HS256")).toThrow(/算法/); }); it("uses x-uid headers in development mode", () => { const identity = resolveIdentity( { jwtAlgorithm: "HS256" }, { headers: { "x-uid": "7", "x-team-id": "8", "x-nickname": "dev" } }, ); expect(identity).toEqual({ uid: "7", team_id: "8", nickname: "dev" }); }); });