Add permissive forward-auth middleware that extracts user identity from X-authentik-* headers when TrustedProxy is enabled. Headers are ignored when TrustedProxy is false to prevent spoofing from untrusted sources. - GetUser(c) helper retrieves AuthentikUser from Gin context - authentikMiddleware splits groups/entitlements on pipe delimiter - /health and /swagger bypass header extraction - WithAuthentik option wires middleware into the Engine Co-Authored-By: Virgil <virgil@lethean.io>
99 lines
2.8 KiB
Go
99 lines
2.8 KiB
Go
// SPDX-License-Identifier: EUPL-1.2
|
|
|
|
package api
|
|
|
|
import (
|
|
"net/http"
|
|
"time"
|
|
|
|
"github.com/gin-contrib/cors"
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
// Option configures an Engine during construction.
|
|
type Option func(*Engine)
|
|
|
|
// WithAddr sets the listen address for the server.
|
|
func WithAddr(addr string) Option {
|
|
return func(e *Engine) {
|
|
e.addr = addr
|
|
}
|
|
}
|
|
|
|
// WithBearerAuth adds bearer token authentication middleware.
|
|
// Requests to /health and paths starting with /swagger are exempt.
|
|
func WithBearerAuth(token string) Option {
|
|
return func(e *Engine) {
|
|
skip := []string{"/health", "/swagger"}
|
|
e.middlewares = append(e.middlewares, bearerAuthMiddleware(token, skip))
|
|
}
|
|
}
|
|
|
|
// WithRequestID adds middleware that assigns an X-Request-ID to every response.
|
|
// Client-provided IDs are preserved; otherwise a random hex ID is generated.
|
|
func WithRequestID() Option {
|
|
return func(e *Engine) {
|
|
e.middlewares = append(e.middlewares, requestIDMiddleware())
|
|
}
|
|
}
|
|
|
|
// WithCORS configures Cross-Origin Resource Sharing via gin-contrib/cors.
|
|
// Pass "*" to allow all origins, or supply specific origin URLs.
|
|
// Standard methods (GET, POST, PUT, PATCH, DELETE, OPTIONS) and common
|
|
// headers (Authorization, Content-Type, X-Request-ID) are permitted.
|
|
func WithCORS(allowOrigins ...string) Option {
|
|
return func(e *Engine) {
|
|
cfg := cors.Config{
|
|
AllowMethods: []string{"GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"},
|
|
AllowHeaders: []string{"Authorization", "Content-Type", "X-Request-ID"},
|
|
MaxAge: 12 * time.Hour,
|
|
}
|
|
|
|
for _, o := range allowOrigins {
|
|
if o == "*" {
|
|
cfg.AllowAllOrigins = true
|
|
break
|
|
}
|
|
}
|
|
if !cfg.AllowAllOrigins {
|
|
cfg.AllowOrigins = allowOrigins
|
|
}
|
|
|
|
e.middlewares = append(e.middlewares, cors.New(cfg))
|
|
}
|
|
}
|
|
|
|
// WithMiddleware appends arbitrary Gin middleware to the engine.
|
|
func WithMiddleware(mw ...gin.HandlerFunc) Option {
|
|
return func(e *Engine) {
|
|
e.middlewares = append(e.middlewares, mw...)
|
|
}
|
|
}
|
|
|
|
// WithWSHandler registers a WebSocket handler at GET /ws.
|
|
// Typically this wraps a go-ws Hub.Handler().
|
|
func WithWSHandler(h http.Handler) Option {
|
|
return func(e *Engine) {
|
|
e.wsHandler = h
|
|
}
|
|
}
|
|
|
|
// WithAuthentik adds Authentik forward-auth middleware that extracts user
|
|
// identity from X-authentik-* headers set by a trusted reverse proxy.
|
|
// The middleware is permissive: unauthenticated requests are allowed through.
|
|
func WithAuthentik(cfg AuthentikConfig) Option {
|
|
return func(e *Engine) {
|
|
e.middlewares = append(e.middlewares, authentikMiddleware(cfg))
|
|
}
|
|
}
|
|
|
|
// WithSwagger enables the Swagger UI at /swagger/.
|
|
// The title, description, and version populate the OpenAPI info block.
|
|
func WithSwagger(title, description, version string) Option {
|
|
return func(e *Engine) {
|
|
e.swaggerTitle = title
|
|
e.swaggerDesc = description
|
|
e.swaggerVersion = version
|
|
e.swaggerEnabled = true
|
|
}
|
|
}
|