Files
HiveGrid-Wireframes/03 Quellen und Referenzen/hivegrid-cloud/apps/web/app/modules/admin-sso/client.server.test.ts
T

100 lines
4.1 KiB
TypeScript

import { describe, expect, it } from "vitest";
import { AdminSsoConfigError, isAdminSsoConfigured, readAdminSsoEnv } from "./client.server";
describe("readAdminSsoEnv", () => {
const baseEnv = {
AUTHENTIK_ISSUER_URL: "https://auth.example.test/application/o/hivegrid-admin-panel/",
AUTHENTIK_ADMIN_CLIENT_ID: "hivegrid-admin-panel",
AUTHENTIK_ADMIN_CLIENT_SECRET: "shh",
AUTHENTIK_ADMIN_JIT_DATABASE_URL: "postgresql://hivegrid_authentik_jit:secret@db.example.test:5432/hivegrid",
AUTHENTIK_ADMIN_REDIRECT_URI: "https://admin.example.test/auth/admin/callback",
};
it("returns trimmed values when all required keys are present", () => {
const env = readAdminSsoEnv({ ...baseEnv, AUTHENTIK_ADMIN_POST_LOGOUT_REDIRECT_URI: "https://admin.example.test/login?logged_out=1" });
expect(env.issuerUrl).toBe(baseEnv.AUTHENTIK_ISSUER_URL);
expect(env.clientId).toBe("hivegrid-admin-panel");
expect(env.postLogoutRedirectUri).toBe("https://admin.example.test/login?logged_out=1");
});
it("throws when a required key is missing", () => {
expect(() => readAdminSsoEnv({ ...baseEnv, AUTHENTIK_ADMIN_CLIENT_SECRET: "" })).toThrowError(AdminSsoConfigError);
});
it("lists every missing key in the error message", () => {
try {
readAdminSsoEnv({});
expect.fail("expected throw");
} catch (err) {
expect(err).toBeInstanceOf(AdminSsoConfigError);
const message = (err as Error).message;
expect(message).toContain("AUTHENTIK_ISSUER_URL");
expect(message).toContain("AUTHENTIK_ADMIN_CLIENT_ID");
expect(message).toContain("AUTHENTIK_ADMIN_CLIENT_SECRET");
expect(message).toContain("AUTHENTIK_ADMIN_JIT_DATABASE_URL");
expect(message).toContain("AUTHENTIK_ADMIN_REDIRECT_URI");
}
});
it("rejects non-TLS remote endpoints and URL credentials", () => {
expect(() => readAdminSsoEnv({ ...baseEnv, AUTHENTIK_ISSUER_URL: "http://auth.example.test/issuer" })).toThrowError(
/must use HTTPS/,
);
expect(() => readAdminSsoEnv({ ...baseEnv, AUTHENTIK_ISSUER_URL: "https://user:password@auth.example.test/issuer" })).toThrowError(
/must not contain URL credentials/,
);
});
it("requires the exact callback path and a same-origin logout redirect", () => {
expect(() => readAdminSsoEnv({ ...baseEnv, AUTHENTIK_ADMIN_REDIRECT_URI: "https://admin.example.test/wrong" })).toThrowError(
/exact \/auth\/admin\/callback path/,
);
expect(() =>
readAdminSsoEnv({
...baseEnv,
AUTHENTIK_ADMIN_POST_LOGOUT_REDIRECT_URI: "https://evil.example.test/login?logged_out=1",
}),
).toThrowError(/must use the admin callback origin/);
});
it("requires the prepared-admin binding capability to use its dedicated login role", () => {
expect(() =>
readAdminSsoEnv({
...baseEnv,
AUTHENTIK_ADMIN_JIT_DATABASE_URL: "postgresql://hivegrid_app:secret@db.example.test:5432/hivegrid",
}),
).toThrowError(/must authenticate as hivegrid_authentik_jit/);
});
it("permits HTTP only for loopback development", () => {
expect(
readAdminSsoEnv({
...baseEnv,
AUTHENTIK_ISSUER_URL: "http://127.0.0.1:9000/application/o/hivegrid-admin-panel/",
AUTHENTIK_ADMIN_REDIRECT_URI: "http://localhost:3000/auth/admin/callback",
}),
).toMatchObject({
issuerUrl: "http://127.0.0.1:9000/application/o/hivegrid-admin-panel/",
redirectUri: "http://localhost:3000/auth/admin/callback",
});
});
});
describe("isAdminSsoConfigured", () => {
it("returns true when env is complete", () => {
expect(
isAdminSsoConfigured({
AUTHENTIK_ISSUER_URL: "https://auth.example.test/",
AUTHENTIK_ADMIN_CLIENT_ID: "id",
AUTHENTIK_ADMIN_CLIENT_SECRET: "secret",
AUTHENTIK_ADMIN_JIT_DATABASE_URL: "postgresql://hivegrid_authentik_jit:secret@db.example.test:5432/hivegrid",
AUTHENTIK_ADMIN_REDIRECT_URI: "https://admin.example.test/auth/admin/callback",
})
).toBe(true);
});
it("returns false when env is incomplete", () => {
expect(isAdminSsoConfigured({})).toBe(false);
});
});