From f64afce83d44dc6250f3c6dce43f1a8eb1af685b Mon Sep 17 00:00:00 2001 From: pushpinderbal Date: Wed, 17 Dec 2025 18:56:26 -0500 Subject: [PATCH 1/5] feat: add support for 'envoy' proxy in proxyHandler validation --- internal/controller/proxy_controller.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/internal/controller/proxy_controller.go b/internal/controller/proxy_controller.go index 2b6738ac..9e6da89b 100644 --- a/internal/controller/proxy_controller.go +++ b/internal/controller/proxy_controller.go @@ -40,6 +40,9 @@ func NewProxyController(config ProxyControllerConfig, router *gin.RouterGroup, a func (controller *ProxyController) SetupRoutes() { proxyGroup := controller.router.Group("/auth") proxyGroup.GET("/:proxy", controller.proxyHandler) + // envoy uses the original request method for ext_authz + // https://github.com/envoyproxy/envoy/issues/5357 + proxyGroup.Any("/envoy", controller.proxyHandler) } func (controller *ProxyController) proxyHandler(c *gin.Context) { @@ -55,7 +58,7 @@ func (controller *ProxyController) proxyHandler(c *gin.Context) { return } - if req.Proxy != "nginx" && req.Proxy != "traefik" && req.Proxy != "caddy" { + if req.Proxy != "nginx" && req.Proxy != "traefik" && req.Proxy != "caddy" && req.Proxy != "envoy" { log.Warn().Str("proxy", req.Proxy).Msg("Invalid proxy") c.JSON(400, gin.H{ "status": 400, From 8e062bb1df5181ffbfb4d72b7877bd14e2845148 Mon Sep 17 00:00:00 2001 From: pushpinderbal Date: Wed, 17 Dec 2025 20:21:17 -0500 Subject: [PATCH 2/5] refactor: simplify proxy route setup by consolidating envoy handling --- internal/controller/proxy_controller.go | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/internal/controller/proxy_controller.go b/internal/controller/proxy_controller.go index 9e6da89b..638f84fa 100644 --- a/internal/controller/proxy_controller.go +++ b/internal/controller/proxy_controller.go @@ -39,10 +39,7 @@ func NewProxyController(config ProxyControllerConfig, router *gin.RouterGroup, a func (controller *ProxyController) SetupRoutes() { proxyGroup := controller.router.Group("/auth") - proxyGroup.GET("/:proxy", controller.proxyHandler) - // envoy uses the original request method for ext_authz - // https://github.com/envoyproxy/envoy/issues/5357 - proxyGroup.Any("/envoy", controller.proxyHandler) + proxyGroup.Any("/:proxy", controller.proxyHandler) } func (controller *ProxyController) proxyHandler(c *gin.Context) { From ca2ec6cc01935dfecbc3389cf875ebe8d9c1310c Mon Sep 17 00:00:00 2001 From: Pushpinder Singh Date: Thu, 18 Dec 2025 15:41:50 -0500 Subject: [PATCH 3/5] feat(proxy): add method validation for proxy authentication --- internal/controller/proxy_controller.go | 9 +++++++++ internal/controller/proxy_controller_test.go | 19 +++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/internal/controller/proxy_controller.go b/internal/controller/proxy_controller.go index 638f84fa..fbece3c7 100644 --- a/internal/controller/proxy_controller.go +++ b/internal/controller/proxy_controller.go @@ -55,6 +55,15 @@ func (controller *ProxyController) proxyHandler(c *gin.Context) { return } + if req.Proxy != "envoy" && c.Request.Method != http.MethodGet { + log.Warn().Str("method", c.Request.Method).Msg("Invalid method for proxy authentication") + c.JSON(405, gin.H{ + "status": 405, + "message": "Method Not Allowed", + }) + return + } + if req.Proxy != "nginx" && req.Proxy != "traefik" && req.Proxy != "caddy" && req.Proxy != "envoy" { log.Warn().Str("proxy", req.Proxy).Msg("Invalid proxy") c.JSON(400, gin.H{ diff --git a/internal/controller/proxy_controller_test.go b/internal/controller/proxy_controller_test.go index e7e27cf0..452155f0 100644 --- a/internal/controller/proxy_controller_test.go +++ b/internal/controller/proxy_controller_test.go @@ -80,6 +80,13 @@ func TestProxyHandler(t *testing.T) { assert.Equal(t, 400, recorder.Code) + // Test invalid method + recorder = httptest.NewRecorder() + req = httptest.NewRequest("POST", "/api/auth/traefik", nil) + router.ServeHTTP(recorder, req) + + assert.Equal(t, 405, recorder.Code) + // Test logged out user (traefik/caddy) recorder = httptest.NewRecorder() req = httptest.NewRequest("GET", "/api/auth/traefik", nil) @@ -92,6 +99,18 @@ func TestProxyHandler(t *testing.T) { assert.Equal(t, 307, recorder.Code) assert.Equal(t, "http://localhost:8080/login?redirect_uri=https%3A%2F%2Fexample.com%2Fsomepath", recorder.Header().Get("Location")) + // Test logged out user (envoy) + recorder = httptest.NewRecorder() + req = httptest.NewRequest("POST", "/api/auth/envoy", nil) + req.Header.Set("X-Forwarded-Proto", "https") + req.Header.Set("X-Forwarded-Host", "example.com") + req.Header.Set("X-Forwarded-Uri", "/somepath") + req.Header.Set("Accept", "text/html") + router.ServeHTTP(recorder, req) + + assert.Equal(t, 307, recorder.Code) + assert.Equal(t, "http://localhost:8080/login?redirect_uri=https%3A%2F%2Fexample.com%2Fsomepath", recorder.Header().Get("Location")) + // Test logged out user (nginx) recorder = httptest.NewRecorder() req = httptest.NewRequest("GET", "/api/auth/nginx", nil) From 5a046bcfb2357353bdd887836e9c7df4777e89f0 Mon Sep 17 00:00:00 2001 From: Pushpinder Singh Date: Fri, 19 Dec 2025 11:18:23 -0500 Subject: [PATCH 4/5] fix(proxy): reorder method validation for proxy authentication --- internal/controller/proxy_controller.go | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/internal/controller/proxy_controller.go b/internal/controller/proxy_controller.go index fbece3c7..f1cac41c 100644 --- a/internal/controller/proxy_controller.go +++ b/internal/controller/proxy_controller.go @@ -55,15 +55,6 @@ func (controller *ProxyController) proxyHandler(c *gin.Context) { return } - if req.Proxy != "envoy" && c.Request.Method != http.MethodGet { - log.Warn().Str("method", c.Request.Method).Msg("Invalid method for proxy authentication") - c.JSON(405, gin.H{ - "status": 405, - "message": "Method Not Allowed", - }) - return - } - if req.Proxy != "nginx" && req.Proxy != "traefik" && req.Proxy != "caddy" && req.Proxy != "envoy" { log.Warn().Str("proxy", req.Proxy).Msg("Invalid proxy") c.JSON(400, gin.H{ @@ -73,6 +64,15 @@ func (controller *ProxyController) proxyHandler(c *gin.Context) { return } + if req.Proxy != "envoy" && c.Request.Method != http.MethodGet { + log.Warn().Str("method", c.Request.Method).Msg("Invalid method for proxy") + c.JSON(405, gin.H{ + "status": 405, + "message": "Method Not Allowed", + }) + return + } + isBrowser := strings.Contains(c.Request.Header.Get("Accept"), "text/html") if isBrowser { From 97291732f3d22597e93216007374103f0b7fee1a Mon Sep 17 00:00:00 2001 From: Stavros Date: Mon, 22 Dec 2025 22:19:43 +0200 Subject: [PATCH 5/5] refactor: use a slice to check for supported proxies --- internal/controller/proxy_controller.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/internal/controller/proxy_controller.go b/internal/controller/proxy_controller.go index f1cac41c..eed127e4 100644 --- a/internal/controller/proxy_controller.go +++ b/internal/controller/proxy_controller.go @@ -3,6 +3,7 @@ package controller import ( "fmt" "net/http" + "slices" "strings" "tinyauth/internal/config" "tinyauth/internal/service" @@ -13,6 +14,8 @@ import ( "github.com/rs/zerolog/log" ) +var SupportedProxies = []string{"nginx", "traefik", "caddy", "envoy"} + type Proxy struct { Proxy string `uri:"proxy" binding:"required"` } @@ -55,7 +58,7 @@ func (controller *ProxyController) proxyHandler(c *gin.Context) { return } - if req.Proxy != "nginx" && req.Proxy != "traefik" && req.Proxy != "caddy" && req.Proxy != "envoy" { + if !slices.Contains(SupportedProxies, req.Proxy) { log.Warn().Str("proxy", req.Proxy).Msg("Invalid proxy") c.JSON(400, gin.H{ "status": 400,