feat: add database-refreshed identity authorization
This commit is contained in:
1 parent
716a8031b1
commit
c849077591
12 files changed
+1809
-15
No files matched your search
@@ -0,0 +1,84 @@
|
||||
import { readFile } from "node:fs/promises";
|
||||
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
|
||||
import type { AuthSession } from "@/lib/auth/session";
|
||||
import {
|
||||
authorizePlatformSession,
|
||||
type PlatformAuthorizationSnapshot,
|
||||
} from "@/lib/server/auth/platform-session";
|
||||
|
||||
type ContractCase = {
|
||||
name: string;
|
||||
session: AuthSession;
|
||||
snapshot: PlatformAuthorizationSnapshot | null;
|
||||
expected:
|
||||
| { outcome: "authenticated"; loaderCalls: number; session: AuthSession }
|
||||
| { outcome: "unauthenticated"; loaderCalls: number; reason: string };
|
||||
};
|
||||
|
||||
type ContractFixture = {
|
||||
version: 1;
|
||||
requiredClientId: string;
|
||||
cases: ContractCase[];
|
||||
};
|
||||
|
||||
const fixtureUrl = new URL("../contracts/auth/platform-session-authorization-v1.json", import.meta.url);
|
||||
|
||||
async function loadFixture(): Promise<ContractFixture> {
|
||||
return JSON.parse(await readFile(fixtureUrl, "utf8")) as ContractFixture;
|
||||
}
|
||||
|
||||
describe("platform session authorization v1 cross-language contract", () => {
|
||||
it("refreshes an active user's forged Cookie claims from the database", async () => {
|
||||
const fixture = await loadFixture();
|
||||
const contractCase = fixture.cases[0];
|
||||
const loader = vi.fn(async () => contractCase.snapshot);
|
||||
|
||||
const result = await authorizePlatformSession(
|
||||
contractCase.session,
|
||||
loader,
|
||||
fixture.requiredClientId,
|
||||
);
|
||||
|
||||
expect(result).toEqual(contractCase.expected.outcome === "authenticated"
|
||||
? { outcome: "authenticated", session: contractCase.expected.session }
|
||||
: { outcome: "unauthenticated", reason: contractCase.expected.reason });
|
||||
expect(loader).toHaveBeenCalledTimes(contractCase.expected.loaderCalls);
|
||||
});
|
||||
|
||||
it("matches every remaining authorization and rejection case", async () => {
|
||||
const fixture = await loadFixture();
|
||||
|
||||
for (const contractCase of fixture.cases.slice(1)) {
|
||||
const loader = vi.fn(async () => contractCase.snapshot);
|
||||
const result = await authorizePlatformSession(
|
||||
contractCase.session,
|
||||
loader,
|
||||
fixture.requiredClientId,
|
||||
);
|
||||
|
||||
expect(result, contractCase.name).toEqual(contractCase.expected.outcome === "authenticated"
|
||||
? { outcome: "authenticated", session: contractCase.expected.session }
|
||||
: { outcome: "unauthenticated", reason: contractCase.expected.reason });
|
||||
expect(loader, contractCase.name).toHaveBeenCalledTimes(contractCase.expected.loaderCalls);
|
||||
if (contractCase.expected.loaderCalls > 0) {
|
||||
expect(loader, contractCase.name).toHaveBeenCalledWith(contractCase.session.user.id);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it("rejects a mismatched joined organization instead of trusting its display claims", async () => {
|
||||
const fixture = await loadFixture();
|
||||
const contractCase = fixture.cases[0];
|
||||
const snapshot = structuredClone(contractCase.snapshot);
|
||||
if (!snapshot?.organization) throw new Error("fixture requires organization");
|
||||
snapshot.organization.id = "org-other";
|
||||
|
||||
await expect(authorizePlatformSession(
|
||||
contractCase.session,
|
||||
async () => snapshot,
|
||||
fixture.requiredClientId,
|
||||
)).resolves.toEqual({ outcome: "unauthenticated", reason: "organization_not_active" });
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user