86 lines
2.8 KiB
TypeScript
86 lines
2.8 KiB
TypeScript
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);
|
|
});
|