root: make logged HTTP headers configurable (#19716)

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
This commit is contained in:
Jens L.
2026-01-26 14:31:54 +01:00
committed by GitHub
parent 9a806f7e49
commit 03e16b3a14
4 changed files with 32 additions and 3 deletions
+3
View File
@@ -63,6 +63,9 @@ debug: false
debugger: false
log_level: info
log:
http_headers:
- User-Agent
sessions:
unauthenticated_age: days=1
+10 -1
View File
@@ -22,6 +22,7 @@ from sentry_sdk import Scope
from structlog.stdlib import get_logger
from authentik.core.models import Token, TokenIntents, User, UserTypes
from authentik.lib.config import CONFIG
LOGGER = get_logger("authentik.asgi")
ACR_AUTHENTIK_SESSION = "goauthentik.io/core/default"
@@ -320,6 +321,10 @@ class LoggingMiddleware:
def __init__(self, get_response: Callable[[HttpRequest], HttpResponse]):
self.get_response = get_response
headers = CONFIG.get("log.http_headers", [])
if isinstance(headers, str):
headers = headers.split(",")
self.headers_to_log = headers
def __call__(self, request: HttpRequest) -> HttpResponse:
start = perf_counter()
@@ -334,6 +339,11 @@ class LoggingMiddleware:
def log(self, request: HttpRequest, status_code: int, runtime: int, **kwargs):
"""Log request"""
for header in self.headers_to_log:
header_value = request.headers.get(header)
if not header_value:
continue
kwargs[header.lower().replace("-", "_")] = header_value
LOGGER.info(
request.get_full_path(),
remote=ClientIPMiddleware.get_client_ip(request),
@@ -341,6 +351,5 @@ class LoggingMiddleware:
scheme=request.scheme,
status=status_code,
runtime=runtime,
user_agent=request.META.get("HTTP_USER_AGENT", ""),
**kwargs,
)
+5
View File
@@ -15,6 +15,7 @@ type Config struct {
Debug bool `yaml:"debug" env:"AUTHENTIK_DEBUG, overwrite"`
Listen ListenConfig `yaml:"listen" env:", prefix=AUTHENTIK_LISTEN__"`
Web WebConfig `yaml:"web" env:", prefix=AUTHENTIK_WEB__"`
Log LogConfig `yaml:"log" env:", prefix=AUTHENTIK_LOG__"`
// Outpost specific config
// These are only relevant for proxy/ldap outposts, and cannot be set via YAML
@@ -105,3 +106,7 @@ type OutpostConfig struct {
type WebConfig struct {
Path string `yaml:"path" env:"PATH, overwrite"`
}
type LogConfig struct {
HttpHeaders []string `yaml:"http_headers" env:"HTTP_HEADERS, overwrite"`
}
+14 -2
View File
@@ -6,9 +6,11 @@ import (
"fmt"
"net"
"net/http"
"strings"
"time"
log "github.com/sirupsen/logrus"
"goauthentik.io/internal/config"
)
// responseLogger is wrapper of http.ResponseWriter that keeps track of its HTTP status
@@ -71,6 +73,7 @@ type loggingHandler struct {
handler http.Handler
logger *log.Entry
afterHandler afterHandler
headers []string
}
type afterHandler func(l *log.Entry, r *http.Request) *log.Entry
@@ -87,6 +90,7 @@ func NewLoggingHandler(logger *log.Entry, after afterHandler) func(h http.Handle
handler: h,
logger: logger,
afterHandler: after,
headers: config.Get().Log.HttpHeaders,
}
}
}
@@ -101,7 +105,7 @@ func (h loggingHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
if req.TLS != nil {
scheme = "https"
}
h.afterHandler(h.logger.WithFields(log.Fields{
fields := log.Fields{
"remote": req.RemoteAddr,
"host": GetHost(req),
"runtime": fmt.Sprintf("%0.3f", duration),
@@ -110,5 +114,13 @@ func (h loggingHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
"size": responseLogger.Size(),
"status": responseLogger.Status(),
"user_agent": req.UserAgent(),
}), req).Info(url.RequestURI())
}
for _, h := range h.headers {
hv := req.Header.Get(h)
if hv == "" {
continue
}
fields[strings.ToLower(strings.ReplaceAll(h, "-", "_"))] = hv
}
h.afterHandler(h.logger.WithFields(fields), req).Info(url.RequestURI())
}