66 lines
2.2 KiB
TypeScript
66 lines
2.2 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import { SignJWT, generateKeyPair } from "jose";
|
|
import { makeVerifier } from "../server/utils/auth";
|
|
|
|
const ISS = "https://auth.kuns.dev";
|
|
|
|
async function setup() {
|
|
const { publicKey, privateKey } = await generateKeyPair("RS256");
|
|
const verify = makeVerifier({
|
|
issuer: ISS,
|
|
audiences: ["aud-web", "proj-1"],
|
|
allowedSubs: ["owner-1"],
|
|
keyResolver: async () => publicKey,
|
|
});
|
|
const sign = (claims: Record<string, unknown>) =>
|
|
new SignJWT(claims)
|
|
.setProtectedHeader({ alg: "RS256" })
|
|
.setIssuer(ISS)
|
|
.setIssuedAt()
|
|
.setExpirationTime("5m")
|
|
.sign(privateKey);
|
|
return { verify, sign };
|
|
}
|
|
|
|
describe("token verification", () => {
|
|
it("accepts an owner token with a valid audience", async () => {
|
|
const { verify, sign } = await setup();
|
|
const t = await sign({ sub: "owner-1", aud: ["aud-web"] });
|
|
await expect(verify(t)).resolves.toMatchObject({ sub: "owner-1" });
|
|
});
|
|
|
|
it("accepts when aud is a single string in the allowed set", async () => {
|
|
const { verify, sign } = await setup();
|
|
const t = await sign({ sub: "owner-1", aud: "proj-1" });
|
|
await expect(verify(t)).resolves.toMatchObject({ sub: "owner-1" });
|
|
});
|
|
|
|
it("rejects a non-owner sub", async () => {
|
|
const { verify, sign } = await setup();
|
|
const t = await sign({ sub: "intruder", aud: ["aud-web"] });
|
|
await expect(verify(t)).rejects.toThrow();
|
|
});
|
|
|
|
it("rejects a token with no accepted audience", async () => {
|
|
const { verify, sign } = await setup();
|
|
const t = await sign({ sub: "owner-1", aud: ["other"] });
|
|
await expect(verify(t)).rejects.toThrow();
|
|
});
|
|
|
|
it("rejects a wrong issuer", async () => {
|
|
const { publicKey, privateKey } = await generateKeyPair("RS256");
|
|
const verify = makeVerifier({
|
|
issuer: ISS,
|
|
audiences: ["aud-web"],
|
|
allowedSubs: ["owner-1"],
|
|
keyResolver: async () => publicKey,
|
|
});
|
|
const t = await new SignJWT({ sub: "owner-1", aud: ["aud-web"] })
|
|
.setProtectedHeader({ alg: "RS256" })
|
|
.setIssuer("https://evil.example")
|
|
.setExpirationTime("5m")
|
|
.sign(privateKey);
|
|
await expect(verify(t)).rejects.toThrow();
|
|
});
|
|
});
|