Help us shape the future of Go! Take the 2026 Go Developer Survey

forwardauth

package
v1.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 30, 2026 License: Apache-2.0 Imports: 30 Imported by: 0

Documentation

Overview

Package forwardauth is the server of the forward-auth binary (cmd/forwardauth): the gin engine with the forward-auth checks Traefik calls, the provider routes, JWKS, identity, health and readiness endpoints, wide events and HTTP metrics on every request, and the graceful run of the public and the metrics listener.

Index

Constants

View Source
const (

	// MaximumPort is the highest TCP port.
	MaximumPort = 65535

	// MaximumShutdownDelay keeps ShutdownDelay plus the 20 s drain within the 30 s default termination
	// grace period of a pod [LAY-003].
	MaximumShutdownDelay = 10 * time.Second
)

Variables

This section is empty.

Functions

func NewObserver

func NewObserver(options *ObserverOptions) (auth.Observer, error)

NewObserver returns the auth.Observer main passes to the provider, the Guard and the API keys: it records each outcome on the request's wide event and counts it in forwardauth_auth_outcomes_total.

func ValidateJWTHeader

func ValidateJWTHeader(name string) error

ValidateJWTHeader reports why name cannot carry the JWT of a check answer: it must be a header name, and not one the check answer or net/http sets itself, which would overwrite or drop the token, nor Cookie or Host, which Traefik would overwrite in the upstream request.

func ValidatePathPrefix

func ValidatePathPrefix(prefix string) error

ValidatePathPrefix reports why prefix cannot hold the routes: it must pass redirect.IsPathPrefix, so it has no gin parameter, wildcard or "." segment.

func ValidateTrustedProxies added in v1.1.0

func ValidateTrustedProxies(entries []string) error

ValidateTrustedProxies reports every entry that is neither an IP address nor a CIDR. Only a request whose peer is one of them may name the client in X-Forwarded-For or X-Real-IP; for every other request, request.client_ip is the peer address, so a client cannot forge it.

Types

type Dependencies

type Dependencies struct {
	// contains filtered or unexported fields
}

Dependencies records the outbound calls of the binary, the Redis session operations and the HTTP calls of the provider and Keycloak, in forwardauth_dependency_request_duration_seconds and, during a request, summed per dependency on its wide event [LOG-004, LOG-006, MET-006]. Calls outside a request (discovery at boot, JWKS refreshes) reach only the metric. It is safe for concurrent use.

There is no OpenTelemetry tracing [OBS-001]: a check is one hop from Traefik with at most a Redis call and a provider call behind it, which the wide event already sums per dependency; the binary has no trace backend or trace context to join. Add otelhttp and redisotel here when a deployment traces.

func NewDependencies

func NewDependencies(options *DependenciesOptions) (*Dependencies, error)

NewDependencies registers the dependency histogram on options.Registerer.

func (*Dependencies) Backend

func (d *Dependencies) Backend(backend session.Backend) session.Backend

Backend wraps backend so its operations are recorded as dependency "redis" (operation: put, get, pop, compare_and_swap, revoke), under cache on the wide event. ErrRevoked is an answer, not a failure.

func (*Dependencies) HTTPClient

func (d *Dependencies) HTTPClient(name string) *http.Client

HTTPClient returns a client with the 10 s default timeout whose calls are recorded as dependency name (operation: the method), under http.<name> on the wide event. A transport error or a 5xx is a failure; the recorded error is the transport's reduced by dependency.TransportFailure: no URL, whose query may carry personal data, and no byte of a malformed answer [LOG-009]. The caller gets the error unchanged.

func (*Dependencies) RedisPing

func (d *Dependencies) RedisPing(ping func(ctx context.Context) error) func(ctx context.Context) error

RedisPing wraps ping (the readiness check's Redis PING) so each call is recorded as dependency "redis", operation ping, under cache on the wide event, like the Backend's operations.

type DependenciesOptions

type DependenciesOptions struct {
	Registerer prometheus.Registerer // required: the registry /metrics serves [MET-002]
}

DependenciesOptions configure Dependencies.

type ObserverOptions

type ObserverOptions struct {
	OutcomeCounter *prometheusadapter.OutcomeCounter // required: counts in forwardauth_auth_outcomes_total
}

ObserverOptions configure NewObserver.

type Server

type Server struct {
	// contains filtered or unexported fields
}

Server serves the forward-auth routes and the metrics endpoint. Build it with NewServer and call Run once.

func NewServer

func NewServer(options *ServerOptions) (*Server, error)

NewServer validates options, registers the HTTP metrics on options.MetricsRegistry and builds the engine with every route. It does not listen; Run does.

func (*Server) Run

func (s *Server) Run(ctx context.Context) error

Run serves until ctx ends, then answers readiness with 503, waits ShutdownDelay so load balancers drop the instance, and drains both listeners within 20 s [LAY-003]. A listener that fails to start stops the other one and its error is returned. Both listeners have stopped serving when Run returns [CON-006].

type ServerOptions

type ServerOptions struct {
	Version           string
	Port, MetricsPort int                             // 0 picks a free port (tests)
	PathPrefix        string                          // required, e.g. "/auth"; see ValidatePathPrefix
	Routes            []auth.Route                    // provider routes, absolute paths
	Guard             *session.Guard                  // required
	APIKeys           *apikey.Authenticator           // optional; runs before the Guard on the checks
	Signer            *jwt.Signer                     // optional; enables the JWT header and {prefix}/jwks
	JWTHeader         string                          // default "Authorization"; value "Bearer <jwt>"; see ValidateJWTHeader
	IdentityEndpoint  bool                            // mounts {prefix}/me
	Emitter           wideevent.Emitter               // required
	Logger            *slog.Logger                    // required: net/http's own error lines (accept errors, panics outside gin) [LOG-013]
	SampleRate        int                             // required, >= 1: keep every Nth successful event
	MetricsRegistry   *prometheus.Registry            // required; runtime collectors registered by main [MET-002]
	ReadinessCheck    func(ctx context.Context) error // optional (Redis ping)
	ShutdownDelay     time.Duration                   // 0..MaximumShutdownDelay; readiness answers 503 this long before the listeners drain
	TrustedProxies    []string                        // optional; see ValidateTrustedProxies; empty trusts no proxy
}

ServerOptions configure a Server. main fills them from the configuration.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL