zerobyte/app/server/modules/sso/__tests__/sso.registration.test.ts
Nicolas Meienberger c2ed9e3693
Some checks failed
Release Workflow / determine-release-type (push) Has been cancelled
Release Workflow / checks (push) Has been cancelled
Release Workflow / e2e-tests (push) Has been cancelled
Release Workflow / build-images (push) Has been cancelled
Release Workflow / publish-release (push) Has been cancelled
refactor: correctly delete orphan sessions after idp deletion
2026-03-05 21:02:56 +01:00

106 lines
3.3 KiB
TypeScript

import { beforeEach, describe, expect, test } from "bun:test";
import { createApp } from "~/server/app";
import { config } from "~/server/core/config";
import { db } from "~/server/db/db";
import { account, invitation, member, organization, ssoProvider, usersTable, verification } from "~/server/db/schema";
import { createTestSession, createTestSessionWithOrgAdmin } from "~/test/helpers/auth";
const app = createApp();
const ssoRegisterUrl = new URL("/api/auth/sso/register", config.baseUrl).toString();
function buildRegisterBody(organizationId: string, suffix: string) {
return {
providerId: `oidc-${suffix}-${Bun.randomUUIDv7()}`,
issuer: "https://issuer.example.com",
domain: "example.com",
organizationId,
oidcConfig: {
clientId: "client-id",
clientSecret: "client-secret",
skipDiscovery: true,
discoveryEndpoint: "https://issuer.example.com/.well-known/openid-configuration",
authorizationEndpoint: "https://issuer.example.com/oauth2/authorize",
tokenEndpoint: "https://issuer.example.com/oauth2/token",
jwksEndpoint: "https://issuer.example.com/.well-known/jwks.json",
},
};
}
describe("SSO provider registration authorization", () => {
beforeEach(async () => {
await db.delete(member);
await db.delete(account);
await db.delete(invitation);
await db.delete(ssoProvider);
await db.delete(verification);
await db.delete(organization);
await db.delete(usersTable);
});
test("allows organization owners to register providers for their active organization", async () => {
const { headers, organizationId } = await createTestSession();
const response = await app.request(ssoRegisterUrl, {
method: "POST",
headers: {
...headers,
"Content-Type": "application/json",
},
body: JSON.stringify(buildRegisterBody(organizationId, "owner")),
});
expect(response.status).toBe(200);
});
test("rejects org admins for registration when they are not owners", async () => {
const { headers, organizationId } = await createTestSessionWithOrgAdmin();
const response = await app.request(ssoRegisterUrl, {
method: "POST",
headers: {
...headers,
"Content-Type": "application/json",
},
body: JSON.stringify(buildRegisterBody(organizationId, "admin")),
});
expect(response.status).toBe(403);
const body = await response.json();
expect(body.message).toBe("Only organization owners can register SSO providers");
});
test("rejects users who are owners elsewhere but only members of the target organization", async () => {
const { headers, user } = await createTestSession();
const targetOrgId = Bun.randomUUIDv7();
await db.insert(organization).values({
id: targetOrgId,
name: "Target Org",
slug: `target-org-${Date.now()}`,
createdAt: new Date(),
});
await db.insert(member).values({
id: Bun.randomUUIDv7(),
userId: user.id,
organizationId: targetOrgId,
role: "member",
createdAt: new Date(),
});
const response = await app.request(ssoRegisterUrl, {
method: "POST",
headers: {
...headers,
"Content-Type": "application/json",
},
body: JSON.stringify(buildRegisterBody(targetOrgId, "cross-org")),
});
expect(response.status).toBe(403);
const body = await response.json();
expect(body.message).toBe("Only organization owners can register SSO providers");
});
});