Add forward auth portal — CPM as built-in IdP replacing Authentik
CPM can now act as its own forward auth provider for proxied sites. Users authenticate at a login portal (credentials or OAuth) and Caddy gates access via a verify subrequest, eliminating the need for external IdPs like Authentik. Key components: - Forward auth flow: verify endpoint, exchange code callback, login portal - User groups with membership management - Per-proxy-host access control (users and/or groups) - Caddy config generation for forward_auth handler + callback route - OAuth and credential login on the portal page - Admin UI: groups page, inline user/group assignment in proxy host form - REST API: /api/v1/groups, /api/v1/forward-auth-sessions, per-host access - Integration tests for groups and forward auth schema Also fixes mTLS E2E test selectors broken by the RBAC refactor. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -28,6 +28,10 @@ import {
|
||||
DropdownMenuTrigger,
|
||||
} from "@/components/ui/dropdown-menu";
|
||||
|
||||
type ForwardAuthUser = { id: number; email: string; name: string | null; role: string };
|
||||
type ForwardAuthGroup = { id: number; name: string; description: string | null; member_count: number };
|
||||
type ForwardAuthAccessMap = Record<number, { userIds: number[]; groupIds: number[] }>;
|
||||
|
||||
type Props = {
|
||||
hosts: ProxyHost[];
|
||||
certificates: Certificate[];
|
||||
@@ -39,9 +43,12 @@ type Props = {
|
||||
initialSort?: { sortBy: string; sortDir: "asc" | "desc" };
|
||||
mtlsRoles?: MtlsRole[];
|
||||
issuedClientCerts?: IssuedClientCertificate[];
|
||||
forwardAuthUsers?: ForwardAuthUser[];
|
||||
forwardAuthGroups?: ForwardAuthGroup[];
|
||||
forwardAuthAccessMap?: ForwardAuthAccessMap;
|
||||
};
|
||||
|
||||
export default function ProxyHostsClient({ hosts, certificates, accessLists, caCertificates, authentikDefaults, pagination, initialSearch, initialSort, mtlsRoles, issuedClientCerts }: Props) {
|
||||
export default function ProxyHostsClient({ hosts, certificates, accessLists, caCertificates, authentikDefaults, pagination, initialSearch, initialSort, mtlsRoles, issuedClientCerts, forwardAuthUsers, forwardAuthGroups, forwardAuthAccessMap }: Props) {
|
||||
const [createOpen, setCreateOpen] = useState(false);
|
||||
const [duplicateHost, setDuplicateHost] = useState<ProxyHost | null>(null);
|
||||
const [editHost, setEditHost] = useState<ProxyHost | null>(null);
|
||||
@@ -303,6 +310,8 @@ export default function ProxyHostsClient({ hosts, certificates, accessLists, caC
|
||||
caCertificates={caCertificates}
|
||||
mtlsRoles={mtlsRoles ?? []}
|
||||
issuedClientCerts={issuedClientCerts ?? []}
|
||||
forwardAuthUsers={forwardAuthUsers ?? []}
|
||||
forwardAuthGroups={forwardAuthGroups ?? []}
|
||||
/>
|
||||
|
||||
{editHost && (
|
||||
@@ -315,6 +324,9 @@ export default function ProxyHostsClient({ hosts, certificates, accessLists, caC
|
||||
caCertificates={caCertificates}
|
||||
mtlsRoles={mtlsRoles ?? []}
|
||||
issuedClientCerts={issuedClientCerts ?? []}
|
||||
forwardAuthUsers={forwardAuthUsers ?? []}
|
||||
forwardAuthGroups={forwardAuthGroups ?? []}
|
||||
forwardAuthAccess={forwardAuthAccessMap?.[editHost.id] ?? null}
|
||||
/>
|
||||
)}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user