release: WRNexusJS 0.8.0
This commit is contained in:
@@ -0,0 +1,138 @@
|
||||
import { describe, expect, test } from "bun:test";
|
||||
import {
|
||||
createGovernance,
|
||||
createMachineIdentityManager,
|
||||
createSamlFederation,
|
||||
createScimHandler,
|
||||
discoverOidc,
|
||||
memoryScimStore,
|
||||
oidcAuthorizationUrl,
|
||||
syncDirectory,
|
||||
} from "../src/index.ts";
|
||||
|
||||
describe("enterprise identity", () => {
|
||||
test("discovers OIDC safely and creates PKCE authorization URLs", async () => {
|
||||
const metadata = {
|
||||
issuer: "https://id.test",
|
||||
authorization_endpoint: "https://id.test/auth",
|
||||
token_endpoint: "https://id.test/token",
|
||||
jwks_uri: "https://id.test/jwks",
|
||||
};
|
||||
const discovered = await discoverOidc(metadata.issuer, {
|
||||
fetch: (async () => Response.json(metadata)) as unknown as typeof fetch,
|
||||
});
|
||||
const url = new URL(
|
||||
oidcAuthorizationUrl(discovered, {
|
||||
clientId: "app",
|
||||
redirectUri: "https://app.test/callback",
|
||||
state: "state",
|
||||
nonce: "nonce",
|
||||
codeChallenge: "challenge",
|
||||
}),
|
||||
);
|
||||
expect(url.searchParams.get("code_challenge_method")).toBe("S256");
|
||||
});
|
||||
|
||||
test("validates signed SAML boundaries and prevents replay", async () => {
|
||||
const assertion = {
|
||||
id: "assertion-1",
|
||||
issuer: "https://id.test",
|
||||
audience: "app",
|
||||
recipient: "https://app.test/saml",
|
||||
expiresAt: 200,
|
||||
identity: { externalId: "u1", username: "u1", groups: [], active: true },
|
||||
};
|
||||
const federation = createSamlFederation({
|
||||
adapter: { createLoginRequest: () => "request", verifySignedResponse: async () => assertion },
|
||||
issuer: assertion.issuer,
|
||||
audience: assertion.audience,
|
||||
recipient: assertion.recipient,
|
||||
now: () => 100,
|
||||
});
|
||||
expect((await federation.callback("signed")).externalId).toBe("u1");
|
||||
await expect(federation.callback("signed")).rejects.toThrow("WRN-SAML-REPLAY");
|
||||
});
|
||||
|
||||
test("syncs LDAP/AD adapters and provisions SCIM users", async () => {
|
||||
const values: string[] = [];
|
||||
expect(
|
||||
(
|
||||
await syncDirectory(
|
||||
{
|
||||
kind: "active-directory",
|
||||
search: async () => [
|
||||
{ externalId: "u1", username: "user", groups: ["staff"], active: true },
|
||||
],
|
||||
},
|
||||
{
|
||||
baseDn: "dc=test",
|
||||
upsert: (identity) => {
|
||||
values.push(identity.externalId);
|
||||
},
|
||||
},
|
||||
)
|
||||
).synchronized,
|
||||
).toBe(1);
|
||||
const handler = createScimHandler({ store: memoryScimStore(), bearerToken: "a".repeat(32) });
|
||||
const created = await handler(
|
||||
new Request("https://app.test/scim/v2/Users", {
|
||||
method: "POST",
|
||||
headers: { authorization: `Bearer ${"a".repeat(32)}` },
|
||||
body: JSON.stringify({ userName: "person@example.test", active: true }),
|
||||
}),
|
||||
);
|
||||
expect(created.status).toBe(201);
|
||||
expect(
|
||||
(
|
||||
await handler(
|
||||
new Request("https://app.test/scim/v2/Users", {
|
||||
headers: { authorization: `Bearer ${"a".repeat(32)}` },
|
||||
}),
|
||||
)
|
||||
).status,
|
||||
).toBe(200);
|
||||
expect(values).toEqual(["u1"]);
|
||||
});
|
||||
|
||||
test("issues scoped machine identities without exposing hashes", async () => {
|
||||
const manager = createMachineIdentityManager(() => 100);
|
||||
const issued = await manager.issue({
|
||||
ownerId: "org",
|
||||
name: "deploy",
|
||||
kind: "service-account",
|
||||
scopes: ["deploy:write"],
|
||||
});
|
||||
expect(issued.credential.secretHash).toBe("[REDACTED]");
|
||||
expect((await manager.authenticate(issued.secret, "deploy:write"))?.kind).toBe(
|
||||
"service-account",
|
||||
);
|
||||
expect(await manager.authenticate(issued.secret, "admin")).toBeNull();
|
||||
});
|
||||
|
||||
test("tracks consent, approvals, export/deletion, retention and audit", async () => {
|
||||
const audit: string[] = [];
|
||||
const deleted: string[] = [];
|
||||
const governance = createGovernance({
|
||||
now: () => 100,
|
||||
audit: (event) => {
|
||||
audit.push(event.type);
|
||||
},
|
||||
exportSubject: (id) => ({ id }),
|
||||
deleteSubject: (id) => {
|
||||
deleted.push(id);
|
||||
},
|
||||
});
|
||||
await governance.consent("u1", "analytics", true, "v2");
|
||||
const exportRequest = await governance.request("u1", "export");
|
||||
expect((await governance.decide(exportRequest.id, "admin", true)).result).toEqual({ id: "u1" });
|
||||
const deleteRequest = await governance.request("u1", "delete");
|
||||
await governance.decide(deleteRequest.id, "admin", true);
|
||||
expect(
|
||||
await governance.enforceRetention([{ subjectId: "u2", createdAt: 0 }], 50, (record) => {
|
||||
deleted.push(record.subjectId);
|
||||
}),
|
||||
).toBe(1);
|
||||
expect(deleted).toEqual(["u1", "u2"]);
|
||||
expect(audit).toContain("consent.changed");
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user