mirror of
https://github.com/eduardogsilva/wireguard_webadmin.git
synced 2026-03-17 14:26:18 +00:00
refactor session cookie handling for Authelia integration
This commit is contained in:
@@ -36,7 +36,6 @@ def _build_auth_method_entry(method):
|
|||||||
|
|
||||||
if method.auth_type == 'totp':
|
if method.auth_type == 'totp':
|
||||||
entry['totp_secret'] = method.totp_secret
|
entry['totp_secret'] = method.totp_secret
|
||||||
entry['totp_before_auth'] = method.totp_before_auth
|
|
||||||
|
|
||||||
elif method.auth_type == 'oidc':
|
elif method.auth_type == 'oidc':
|
||||||
entry['provider'] = method.oidc_provider
|
entry['provider'] = method.oidc_provider
|
||||||
|
|||||||
@@ -80,6 +80,12 @@ def build_caddyfile(apps, auth_policies, routes):
|
|||||||
return policies[policy_name].get("policy_type", "bypass")
|
return policies[policy_name].get("policy_type", "bypass")
|
||||||
return "bypass"
|
return "bypass"
|
||||||
|
|
||||||
|
def emit_authelia_portal():
|
||||||
|
lines.append(f" handle_path {AUTHELIA_PORTAL_PATH}/* {{")
|
||||||
|
lines.append(f" reverse_proxy {AUTHELIA_INTERNAL_URL}")
|
||||||
|
lines.append(f" }}")
|
||||||
|
lines.append("")
|
||||||
|
|
||||||
for app in apps:
|
for app in apps:
|
||||||
app_id = app.get("id", "unknown")
|
app_id = app.get("id", "unknown")
|
||||||
hosts = app.get("hosts", [])
|
hosts = app.get("hosts", [])
|
||||||
@@ -93,10 +99,7 @@ def build_caddyfile(apps, auth_policies, routes):
|
|||||||
lines.append(f"{host_list} {{")
|
lines.append(f"{host_list} {{")
|
||||||
|
|
||||||
if has_authelia and app_id == "wireguard_webadmin":
|
if has_authelia and app_id == "wireguard_webadmin":
|
||||||
lines.append(f" handle_path {AUTHELIA_PORTAL_PATH}/* {{")
|
emit_authelia_portal()
|
||||||
lines.append(f" reverse_proxy {AUTHELIA_INTERNAL_URL}")
|
|
||||||
lines.append(f" }}")
|
|
||||||
lines.append("")
|
|
||||||
|
|
||||||
for static_route in static_routes:
|
for static_route in static_routes:
|
||||||
path_prefix = static_route.get("path_prefix", "")
|
path_prefix = static_route.get("path_prefix", "")
|
||||||
@@ -128,6 +131,13 @@ def build_caddyfile(apps, auth_policies, routes):
|
|||||||
# non-deny routes and a catch-all respond 403 at Caddy level,
|
# non-deny routes and a catch-all respond 403 at Caddy level,
|
||||||
# avoiding an unnecessary Authelia round-trip.
|
# avoiding an unnecessary Authelia round-trip.
|
||||||
if has_authelia and default_policy_type == "deny":
|
if has_authelia and default_policy_type == "deny":
|
||||||
|
has_protected_routes = any(
|
||||||
|
get_policy_type(pn) not in ("bypass", "deny")
|
||||||
|
for pn in app_routes.values()
|
||||||
|
)
|
||||||
|
if has_protected_routes:
|
||||||
|
emit_authelia_portal()
|
||||||
|
|
||||||
for path_prefix, policy_name in app_routes.items():
|
for path_prefix, policy_name in app_routes.items():
|
||||||
ptype = get_policy_type(policy_name)
|
ptype = get_policy_type(policy_name)
|
||||||
if ptype == "bypass":
|
if ptype == "bypass":
|
||||||
@@ -172,6 +182,11 @@ def build_caddyfile(apps, auth_policies, routes):
|
|||||||
needs_auth = True
|
needs_auth = True
|
||||||
|
|
||||||
if needs_auth:
|
if needs_auth:
|
||||||
|
# Expose the Authelia portal on this domain so session cookies can
|
||||||
|
# be set with the correct scope (authelia_url = this domain).
|
||||||
|
if app_id != "wireguard_webadmin":
|
||||||
|
emit_authelia_portal()
|
||||||
|
|
||||||
for path_prefix, policy_name in app_routes.items():
|
for path_prefix, policy_name in app_routes.items():
|
||||||
if get_policy_type(policy_name) == "bypass":
|
if get_policy_type(policy_name) == "bypass":
|
||||||
lines.append(f" @bypass_{_sanitize_id(path_prefix)} path {path_prefix}*")
|
lines.append(f" @bypass_{_sanitize_id(path_prefix)} path {path_prefix}*")
|
||||||
@@ -195,13 +210,24 @@ def _sanitize_id(value):
|
|||||||
return value.strip("/").replace("/", "_").replace("-", "_")
|
return value.strip("/").replace("/", "_").replace("-", "_")
|
||||||
|
|
||||||
|
|
||||||
def _collect_app_domains(apps, server_address):
|
def _collect_session_cookies(apps, routes, policies, server_address):
|
||||||
"""Return session cookie entries for all unique app hostnames.
|
"""Build session.cookies entries for Authelia.
|
||||||
|
|
||||||
Authelia v4.37+ requires a session.cookies entry for every domain managed
|
Authelia v4.37+ requires a session.cookies entry for every domain managed
|
||||||
via forward_auth. Without it, Authelia does not recognise the domain and
|
via forward_auth, and authelia_url must share the cookie scope with its
|
||||||
may allow requests through regardless of the access_control policy.
|
domain. For multi-domain gateways this means each domain must expose the
|
||||||
|
Authelia portal under its own hostname — Caddy handles this by routing
|
||||||
|
/authelia/* to the Authelia backend for each protected app.
|
||||||
|
|
||||||
|
Only apps with at least one protected (non-bypass, non-deny) route are
|
||||||
|
included. Deny is handled at the Caddy level; bypass needs no session.
|
||||||
"""
|
"""
|
||||||
|
def get_policy_type(policy_name):
|
||||||
|
if policy_name and policy_name in policies:
|
||||||
|
return policies[policy_name].get("policy_type", "bypass")
|
||||||
|
return "bypass"
|
||||||
|
|
||||||
|
route_entries = routes.get("entries", {}) if routes else {}
|
||||||
seen = {server_address}
|
seen = {server_address}
|
||||||
cookies = [
|
cookies = [
|
||||||
{
|
{
|
||||||
@@ -210,15 +236,45 @@ def _collect_app_domains(apps, server_address):
|
|||||||
"default_redirection_url": f"https://{server_address}",
|
"default_redirection_url": f"https://{server_address}",
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
for app in apps:
|
for app in apps:
|
||||||
for host in app.get("hosts", []):
|
app_id = app.get("id", "")
|
||||||
|
hosts = app.get("hosts", [])
|
||||||
|
|
||||||
|
if app_id == "wireguard_webadmin":
|
||||||
|
# Extra hostnames for the main app already have /authelia/* routed
|
||||||
|
# in Caddy — add their session cookies pointing to themselves.
|
||||||
|
for host in hosts:
|
||||||
|
if host not in seen:
|
||||||
|
seen.add(host)
|
||||||
|
cookies.append({
|
||||||
|
"domain": host,
|
||||||
|
"authelia_url": f"https://{host}{AUTHELIA_PORTAL_PATH}",
|
||||||
|
"default_redirection_url": f"https://{host}",
|
||||||
|
})
|
||||||
|
continue
|
||||||
|
|
||||||
|
app_route_data = route_entries.get(app_id, {})
|
||||||
|
default_ptype = get_policy_type(app_route_data.get("default_policy"))
|
||||||
|
needs_auth = default_ptype not in ("bypass", "deny")
|
||||||
|
if not needs_auth:
|
||||||
|
for route in app_route_data.get("routes", []):
|
||||||
|
if get_policy_type(route.get("policy", "")) not in ("bypass", "deny"):
|
||||||
|
needs_auth = True
|
||||||
|
break
|
||||||
|
|
||||||
|
if not needs_auth:
|
||||||
|
continue
|
||||||
|
|
||||||
|
for host in hosts:
|
||||||
if host not in seen:
|
if host not in seen:
|
||||||
seen.add(host)
|
seen.add(host)
|
||||||
cookies.append({
|
cookies.append({
|
||||||
"domain": host,
|
"domain": host,
|
||||||
"authelia_url": f"https://{server_address}{AUTHELIA_PORTAL_PATH}",
|
"authelia_url": f"https://{host}{AUTHELIA_PORTAL_PATH}",
|
||||||
"default_redirection_url": f"https://{server_address}",
|
"default_redirection_url": f"https://{host}",
|
||||||
})
|
})
|
||||||
|
|
||||||
return cookies
|
return cookies
|
||||||
|
|
||||||
|
|
||||||
@@ -229,6 +285,10 @@ def build_authelia_config(auth_policies, routes, apps):
|
|||||||
session_secret = get_or_create_secret("session_secret")
|
session_secret = get_or_create_secret("session_secret")
|
||||||
storage_encryption_key = get_or_create_secret("storage_encryption_key")
|
storage_encryption_key = get_or_create_secret("storage_encryption_key")
|
||||||
|
|
||||||
|
session_cookies = _collect_session_cookies(
|
||||||
|
apps, routes, auth_policies.get("policies", {}), server_address
|
||||||
|
)
|
||||||
|
|
||||||
config = {
|
config = {
|
||||||
"server": {
|
"server": {
|
||||||
"address": "tcp://0.0.0.0:9091",
|
"address": "tcp://0.0.0.0:9091",
|
||||||
@@ -248,7 +308,7 @@ def build_authelia_config(auth_policies, routes, apps):
|
|||||||
},
|
},
|
||||||
"session": {
|
"session": {
|
||||||
"secret": session_secret,
|
"secret": session_secret,
|
||||||
"cookies": _collect_app_domains(apps, server_address),
|
"cookies": session_cookies,
|
||||||
},
|
},
|
||||||
"storage": {
|
"storage": {
|
||||||
"encryption_key": storage_encryption_key,
|
"encryption_key": storage_encryption_key,
|
||||||
|
|||||||
Reference in New Issue
Block a user