import "../setup.ts"; import { assertEquals } from "@std/assert"; import { SignJWT } from "@panva/jose"; import { createJWT, createMediaToken, createPasswordResetToken, createUnsubscribeToken, verifyJWT, verifyMediaToken, verifyPasswordResetToken, verifyUnsubscribeToken, } from "../../lib/jwt.ts"; const KEY = new TextEncoder().encode("test-secret-test-secret-test-secret"); Deno.test("session, media and reset tokens don't stand in for each other", async () => { const userId = crypto.randomUUID(); const session = await createJWT({ userId, username: "u", role: "user" }); const media = await createMediaToken(userId); const reset = await createPasswordResetToken(userId); assertEquals((await verifyJWT(session))?.userId, userId); assertEquals(await verifyJWT(media), null); assertEquals(await verifyJWT(reset), null); assertEquals((await verifyMediaToken(media))?.userId, userId); assertEquals(await verifyMediaToken(session), null); assertEquals(await verifyMediaToken(reset), null); assertEquals((await verifyPasswordResetToken(reset))?.userId, userId); assertEquals(await verifyPasswordResetToken(session), null); assertEquals(await verifyPasswordResetToken(media), null); }); Deno.test("verifyJWT: refuses a bad signature, an expired token, garbage", async () => { const forged = await new SignJWT({ userId: "x", username: "x", role: "admin", }) .setProtectedHeader({ alg: "HS256" }) .setExpirationTime("1h") .sign(new TextEncoder().encode("some-other-secret")); assertEquals(await verifyJWT(forged), null); const expired = await new SignJWT({ userId: "x", username: "x", role: "user", }) .setProtectedHeader({ alg: "HS256" }) .setExpirationTime(Math.floor(Date.now() / 1000) - 10) .sign(KEY); assertEquals(await verifyJWT(expired), null); const badRole = await new SignJWT({ userId: "x", username: "x", role: "god" }) .setProtectedHeader({ alg: "HS256" }) .setExpirationTime("1h") .sign(KEY); assertEquals(await verifyJWT(badRole), null); assertEquals(await verifyJWT("not.a.jwt"), null); }); Deno.test("an unsubscribe token names its user and cadence, and is nothing else", async () => { const userId = crypto.randomUUID(); const token = await createUnsubscribeToken(userId, "monthly"); assertEquals(await verifyUnsubscribeToken(token), { userId, cadence: "monthly", }); assertEquals(await verifyJWT(token), null); assertEquals(await verifyMediaToken(token), null); assertEquals( await verifyUnsubscribeToken(await createMediaToken(userId)), null, ); const yearly = await new SignJWT({ purpose: "unsubscribe", userId, cadence: "yearly", }).setProtectedHeader({ alg: "HS256" }).sign(KEY); assertEquals(await verifyUnsubscribeToken(yearly), null); });