100 lines
4.1 KiB
TypeScript
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);
|
|
});
|
|
});
|