Files
Piik/tests/livekit-token.test.ts
T

181 lines
5.3 KiB
TypeScript

import { describe, expect, it } from "vitest";
import { TokenVerifier } from "livekit-server-sdk";
import { LiveKitTokenIssuer } from "../src/server/livekit-token.ts";
const apiKey = "test-api-key";
const apiSecret = "s".repeat(32);
const publicationGeneration = "publication_12345678";
const shareGeneration = "share_generation_12345678";
const rootPeerId = "viewer_root_12345678";
const secondRootPeerId = "viewer_root_23456789";
const thirdRootPeerId = "viewer_root_34567890";
function issuer(maxViewersPerRoom = 8): LiveKitTokenIssuer {
return new LiveKitTokenIssuer({
apiKey,
apiSecret,
maxViewersPerRoom,
});
}
describe("LiveKitTokenIssuer", () => {
it("allows every admitted root within the room Viewer bound", async () => {
const tokenIssuer = issuer();
await expect(
tokenIssuer.issueToken({
roomId: "42",
role: "host",
peerId: "host_peer_12345678",
shareGeneration,
publicationGeneration,
allowlistedRootPeerIds: [rootPeerId, secondRootPeerId],
}),
).resolves.toEqual(expect.any(String));
await expect(
tokenIssuer.issueToken({
roomId: "42",
role: "viewer",
peerId: secondRootPeerId,
shareGeneration,
publicationGeneration,
allowlistedRootPeerIds: [rootPeerId, secondRootPeerId],
}),
).resolves.toEqual(expect.any(String));
await expect(
tokenIssuer.issueToken({
roomId: "42",
role: "host",
peerId: "host_peer_12345678",
shareGeneration,
publicationGeneration,
allowlistedRootPeerIds: [
rootPeerId,
secondRootPeerId,
thirdRootPeerId,
],
}),
).resolves.toEqual(expect.any(String));
});
it("issues a generation-bound host token limited to screen sharing", async () => {
const claims = await new TokenVerifier(apiKey, apiSecret).verify(
await issuer().issueToken({
roomId: "42",
role: "host",
peerId: "host_peer_12345678",
shareGeneration,
publicationGeneration,
allowlistedRootPeerIds: [rootPeerId],
}),
);
expect(claims.sub).toBe("host");
expect(claims.exp! - claims.nbf!).toBe(5 * 60);
expect(claims.video).toMatchObject({
roomJoin: true,
room: `screener-v1.42.${shareGeneration}.${publicationGeneration}`,
canPublish: true,
canSubscribe: false,
canPublishData: false,
canUpdateOwnMetadata: false,
canPublishSources: ["screen_share", "screen_share_audio"],
});
expect(claims.roomConfig).toBeUndefined();
});
it("issues a subscribe-only token to a current fallback root", async () => {
const claims = await new TokenVerifier(apiKey, apiSecret).verify(
await issuer(3).issueToken({
roomId: "7",
role: "viewer",
peerId: rootPeerId,
shareGeneration,
publicationGeneration,
allowlistedRootPeerIds: [rootPeerId],
}),
);
expect(claims.sub).toBe(`viewer:${rootPeerId}`);
expect(claims.video).toMatchObject({
roomJoin: true,
room: `screener-v1.7.${shareGeneration}.${publicationGeneration}`,
canPublish: false,
canSubscribe: true,
canPublishData: false,
canUpdateOwnMetadata: false,
});
expect(claims.video?.canPublishSources).toBeUndefined();
expect(claims.roomConfig).toBeUndefined();
});
it("does not issue viewer tokens outside the current root allowlist", async () => {
await expect(
issuer().issueToken({
roomId: "7",
role: "viewer",
peerId: "viewer_other_12345678",
shareGeneration,
publicationGeneration,
allowlistedRootPeerIds: [rootPeerId],
}),
).rejects.toThrow("viewer is not an allowlisted SFU root");
});
it("rejects duplicate, excessive, and malformed root allowlists", async () => {
const tokenIssuer = issuer(1);
const request = {
roomId: "7",
role: "host" as const,
peerId: "host_peer_12345678",
shareGeneration,
publicationGeneration,
};
await expect(
tokenIssuer.issueToken({
...request,
allowlistedRootPeerIds: [rootPeerId, rootPeerId],
}),
).rejects.toThrow("root allowlist is invalid");
await expect(
issuer().issueToken({
...request,
allowlistedRootPeerIds: [rootPeerId, rootPeerId],
}),
).rejects.toThrow("root allowlist contains duplicates");
await expect(
issuer().issueToken({
...request,
allowlistedRootPeerIds: ["not valid"],
}),
).rejects.toThrow("root allowlist is invalid");
});
it("isolates publication generations in separate LiveKit rooms", async () => {
const tokenIssuer = issuer();
const verifier = new TokenVerifier(apiKey, apiSecret);
const baseRequest = {
roomId: "7",
role: "host" as const,
peerId: "host_peer_12345678",
shareGeneration,
allowlistedRootPeerIds: [rootPeerId],
};
const first = await verifier.verify(
await tokenIssuer.issueToken({
...baseRequest,
publicationGeneration: "generation_first_12345678",
}),
);
const second = await verifier.verify(
await tokenIssuer.issueToken({
...baseRequest,
publicationGeneration: "generation_second_12345678",
}),
);
expect(first.video?.room).not.toBe(second.video?.room);
});
});