Squashed commit of the following:
commit b5a751005850115c84fd8fddb83f32a52835a422 Author: fuomag9 <1580624+fuomag9@users.noreply.github.com> Date: Sat Nov 8 13:54:22 2025 +0100 Update ProxyHostsClient.tsx commit c93b3898c31b9c206fba74605dad5a578e326ce4 Author: fuomag9 <1580624+fuomag9@users.noreply.github.com> Date: Sat Nov 8 13:43:00 2025 +0100 test-protected-paths
This commit is contained in:
@@ -658,6 +658,18 @@ function AuthentikFields({ authentik }: { authentik?: ProxyHost["authentik"] | n
|
||||
size="small"
|
||||
fullWidth
|
||||
/>
|
||||
<TextField
|
||||
name="authentik_protected_paths"
|
||||
label="Protected Paths (Optional)"
|
||||
placeholder="/secret/*, /admin/*"
|
||||
helperText="Leave empty to protect entire domain. Specify paths to protect specific routes only."
|
||||
defaultValue={initial?.protectedPaths?.join(", ") ?? ""}
|
||||
disabled={!enabled}
|
||||
multiline
|
||||
minRows={2}
|
||||
size="small"
|
||||
fullWidth
|
||||
/>
|
||||
<HiddenCheckboxField
|
||||
name="authentik_set_host_header"
|
||||
defaultChecked={setHostHeaderDefault}
|
||||
|
||||
@@ -44,6 +44,7 @@ function parseAuthentikConfig(formData: FormData): ProxyHostAuthentikInput | und
|
||||
const authEndpoint = parseOptionalText(formData.get("authentik_auth_endpoint"));
|
||||
const copyHeaders = parseCsv(formData.get("authentik_copy_headers"));
|
||||
const trustedProxies = parseCsv(formData.get("authentik_trusted_proxies"));
|
||||
const protectedPaths = parseCsv(formData.get("authentik_protected_paths"));
|
||||
const setHostHeader = formData.has("authentik_set_host_header_present")
|
||||
? parseCheckbox(formData.get("authentik_set_host_header"))
|
||||
: undefined;
|
||||
@@ -67,6 +68,9 @@ function parseAuthentikConfig(formData: FormData): ProxyHostAuthentikInput | und
|
||||
if (trustedProxies.length > 0 || formData.has("authentik_trusted_proxies")) {
|
||||
result.trustedProxies = trustedProxies;
|
||||
}
|
||||
if (protectedPaths.length > 0 || formData.has("authentik_protected_paths")) {
|
||||
result.protectedPaths = protectedPaths;
|
||||
}
|
||||
if (setHostHeader !== undefined) {
|
||||
result.setOutpostHostHeader = setHostHeader;
|
||||
}
|
||||
|
||||
@@ -68,6 +68,7 @@ type ProxyHostAuthentikMeta = {
|
||||
copy_headers?: string[];
|
||||
trusted_proxies?: string[];
|
||||
set_outpost_host_header?: boolean;
|
||||
protected_paths?: string[];
|
||||
};
|
||||
|
||||
type AuthentikRouteConfig = {
|
||||
@@ -78,6 +79,7 @@ type AuthentikRouteConfig = {
|
||||
copyHeaders: string[];
|
||||
trustedProxies: string[];
|
||||
setOutpostHostHeader: boolean;
|
||||
protectedPaths: string[] | null;
|
||||
};
|
||||
|
||||
type RedirectHostRow = {
|
||||
@@ -494,22 +496,75 @@ function buildProxyRoutes(
|
||||
forwardAuthHandler.trusted_proxies = trustedProxies;
|
||||
}
|
||||
|
||||
handlers.push(forwardAuthHandler);
|
||||
// Path-based authentication support
|
||||
if (authentik.protectedPaths && authentik.protectedPaths.length > 0) {
|
||||
// Create separate routes for each protected path
|
||||
for (const protectedPath of authentik.protectedPaths) {
|
||||
const protectedHandlers: Record<string, unknown>[] = [...handlers];
|
||||
const protectedReverseProxy = JSON.parse(JSON.stringify(reverseProxyHandler));
|
||||
|
||||
protectedHandlers.push(forwardAuthHandler);
|
||||
protectedHandlers.push(protectedReverseProxy);
|
||||
|
||||
hostRoutes.push({
|
||||
match: [
|
||||
{
|
||||
host: domains,
|
||||
path: [protectedPath]
|
||||
}
|
||||
],
|
||||
handle: protectedHandlers,
|
||||
terminal: true
|
||||
});
|
||||
}
|
||||
|
||||
// Create a catch-all route for non-protected paths (without forward auth)
|
||||
const unprotectedHandlers: Record<string, unknown>[] = [...handlers];
|
||||
unprotectedHandlers.push(reverseProxyHandler);
|
||||
|
||||
hostRoutes.push({
|
||||
match: [
|
||||
{
|
||||
host: domains
|
||||
}
|
||||
],
|
||||
handle: unprotectedHandlers,
|
||||
terminal: true
|
||||
});
|
||||
} else {
|
||||
// No path-based protection: protect entire domain (backward compatibility)
|
||||
handlers.push(forwardAuthHandler);
|
||||
handlers.push(reverseProxyHandler);
|
||||
|
||||
const route: CaddyHttpRoute = {
|
||||
match: [
|
||||
{
|
||||
host: domains
|
||||
}
|
||||
],
|
||||
handle: handlers,
|
||||
terminal: true
|
||||
};
|
||||
|
||||
hostRoutes.push(route);
|
||||
}
|
||||
} else {
|
||||
// No Authentik: standard reverse proxy
|
||||
handlers.push(reverseProxyHandler);
|
||||
|
||||
const route: CaddyHttpRoute = {
|
||||
match: [
|
||||
{
|
||||
host: domains
|
||||
}
|
||||
],
|
||||
handle: handlers,
|
||||
terminal: true
|
||||
};
|
||||
|
||||
hostRoutes.push(route);
|
||||
}
|
||||
|
||||
handlers.push(reverseProxyHandler);
|
||||
|
||||
const route: CaddyHttpRoute = {
|
||||
match: [
|
||||
{
|
||||
host: domains
|
||||
}
|
||||
],
|
||||
handle: handlers,
|
||||
terminal: true
|
||||
};
|
||||
|
||||
hostRoutes.push(route);
|
||||
routes.push(...hostRoutes);
|
||||
}
|
||||
|
||||
@@ -960,6 +1015,11 @@ function parseAuthentikConfig(meta: ProxyHostAuthentikMeta | undefined | null):
|
||||
const setOutpostHostHeader =
|
||||
meta.set_outpost_host_header !== undefined ? Boolean(meta.set_outpost_host_header) : true;
|
||||
|
||||
const protectedPaths =
|
||||
Array.isArray(meta.protected_paths) && meta.protected_paths.length > 0
|
||||
? meta.protected_paths.map((path) => path?.trim()).filter((path): path is string => Boolean(path))
|
||||
: null;
|
||||
|
||||
return {
|
||||
enabled: true,
|
||||
outpostDomain,
|
||||
@@ -967,6 +1027,7 @@ function parseAuthentikConfig(meta: ProxyHostAuthentikMeta | undefined | null):
|
||||
authEndpoint,
|
||||
copyHeaders,
|
||||
trustedProxies,
|
||||
setOutpostHostHeader
|
||||
setOutpostHostHeader,
|
||||
protectedPaths
|
||||
};
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ export type ProxyHostAuthentikConfig = {
|
||||
copyHeaders: string[];
|
||||
trustedProxies: string[];
|
||||
setOutpostHostHeader: boolean;
|
||||
protectedPaths: string[] | null;
|
||||
};
|
||||
|
||||
export type ProxyHostAuthentikInput = {
|
||||
@@ -39,6 +40,7 @@ export type ProxyHostAuthentikInput = {
|
||||
copyHeaders?: string[] | null;
|
||||
trustedProxies?: string[] | null;
|
||||
setOutpostHostHeader?: boolean | null;
|
||||
protectedPaths?: string[] | null;
|
||||
};
|
||||
|
||||
type ProxyHostAuthentikMeta = {
|
||||
@@ -49,6 +51,7 @@ type ProxyHostAuthentikMeta = {
|
||||
copy_headers?: string[];
|
||||
trusted_proxies?: string[];
|
||||
set_outpost_host_header?: boolean;
|
||||
protected_paths?: string[];
|
||||
};
|
||||
|
||||
type ProxyHostMeta = {
|
||||
@@ -150,6 +153,13 @@ function sanitizeAuthentikMeta(meta: ProxyHostAuthentikMeta | undefined): ProxyH
|
||||
normalized.set_outpost_host_header = Boolean(meta.set_outpost_host_header);
|
||||
}
|
||||
|
||||
if (Array.isArray(meta.protected_paths)) {
|
||||
const paths = meta.protected_paths.map((path) => path?.trim()).filter((path): path is string => Boolean(path));
|
||||
if (paths.length > 0) {
|
||||
normalized.protected_paths = paths;
|
||||
}
|
||||
}
|
||||
|
||||
return Object.keys(normalized).length > 0 ? normalized : undefined;
|
||||
}
|
||||
|
||||
@@ -263,6 +273,17 @@ function normalizeAuthentikInput(
|
||||
next.set_outpost_host_header = Boolean(input.setOutpostHostHeader);
|
||||
}
|
||||
|
||||
if (input.protectedPaths !== undefined) {
|
||||
const paths = (input.protectedPaths ?? [])
|
||||
.map((path) => path?.trim())
|
||||
.filter((path): path is string => Boolean(path));
|
||||
if (paths.length > 0) {
|
||||
next.protected_paths = paths;
|
||||
} else {
|
||||
delete next.protected_paths;
|
||||
}
|
||||
}
|
||||
|
||||
if ((next.enabled ?? false) && next.outpost_domain && !next.auth_endpoint) {
|
||||
next.auth_endpoint = `/${next.outpost_domain}/auth/caddy`;
|
||||
}
|
||||
@@ -321,6 +342,8 @@ function hydrateAuthentik(meta: ProxyHostAuthentikMeta | undefined): ProxyHostAu
|
||||
: DEFAULT_AUTHENTIK_TRUSTED_PROXIES;
|
||||
const setOutpostHostHeader =
|
||||
meta.set_outpost_host_header !== undefined ? Boolean(meta.set_outpost_host_header) : true;
|
||||
const protectedPaths =
|
||||
Array.isArray(meta.protected_paths) && meta.protected_paths.length > 0 ? meta.protected_paths : null;
|
||||
|
||||
return {
|
||||
enabled,
|
||||
@@ -329,7 +352,8 @@ function hydrateAuthentik(meta: ProxyHostAuthentikMeta | undefined): ProxyHostAu
|
||||
authEndpoint,
|
||||
copyHeaders,
|
||||
trustedProxies,
|
||||
setOutpostHostHeader
|
||||
setOutpostHostHeader,
|
||||
protectedPaths
|
||||
};
|
||||
}
|
||||
|
||||
@@ -358,6 +382,9 @@ function dehydrateAuthentik(config: ProxyHostAuthentikConfig | null): ProxyHostA
|
||||
meta.trusted_proxies = [...config.trustedProxies];
|
||||
}
|
||||
meta.set_outpost_host_header = config.setOutpostHostHeader;
|
||||
if (config.protectedPaths && config.protectedPaths.length > 0) {
|
||||
meta.protected_paths = [...config.protectedPaths];
|
||||
}
|
||||
|
||||
return meta;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user