fix: respect skip-auth-preflight in forward auth mode via X-Forwarded-Method

Signed-off-by: Kevin Stiehl <kevin.stiehl@maybit.email>
This commit is contained in:
Kevin Stiehl 2026-08-13 19:29:58 +02:00
parent 1f049e5ebd
commit dcc0bdad51
No known key found for this signature in database
GPG Key ID: 19A475D64331E39A
3 changed files with 51 additions and 4 deletions

View File

@ -587,7 +587,7 @@ func (p *OAuthProxy) ErrorPage(rw http.ResponseWriter, req *http.Request, code i
// IsAllowedRequest is used to check if auth should be skipped for this request // IsAllowedRequest is used to check if auth should be skipped for this request
func (p *OAuthProxy) IsAllowedRequest(req *http.Request) bool { func (p *OAuthProxy) IsAllowedRequest(req *http.Request) bool {
isPreflightRequestAllowed := p.skipAuthPreflight && req.Method == http.MethodOptions isPreflightRequestAllowed := p.skipAuthPreflight && requestutil.GetRequestMethod(req) == http.MethodOptions
return isPreflightRequestAllowed || p.isAllowedRoute(req) || p.isTrustedIP(req) return isPreflightRequestAllowed || p.isAllowedRoute(req) || p.isTrustedIP(req)
} }

View File

@ -12,6 +12,7 @@ const (
XForwardedProto = "X-Forwarded-Proto" XForwardedProto = "X-Forwarded-Proto"
XForwardedHost = "X-Forwarded-Host" XForwardedHost = "X-Forwarded-Host"
XForwardedURI = "X-Forwarded-Uri" XForwardedURI = "X-Forwarded-Uri"
XForwardedMethod = "X-Forwarded-Method"
) )
// GetRequestProto returns the request scheme or X-Forwarded-Proto if present // GetRequestProto returns the request scheme or X-Forwarded-Proto if present
@ -45,6 +46,16 @@ func GetRequestURI(req *http.Request) string {
return uri return uri
} }
// GetRequestMethod returns the request method or X-Forwarded-Method if present
// and the request came from a trusted reverse proxy.
func GetRequestMethod(req *http.Request) string {
method := req.Header.Get(XForwardedMethod)
if !CanTrustForwardedHeaders(req) || method == "" {
return req.Method
}
return method
}
// GetRequestPath returns the request URI or X-Forwarded-Uri if present and the // GetRequestPath returns the request URI or X-Forwarded-Uri if present and the
// request came from a trusted reverse proxy but always strips the query // request came from a trusted reverse proxy but always strips the query
// parameters and fragment suffixes and only returns the pure path. // parameters and fragment suffixes and only returns the pure path.

View File

@ -200,6 +200,42 @@ var _ = Describe("Util Suite", func() {
}) })
}) })
Context("GetRequestMethod", func() {
Context("trusted forwarded headers are disabled", func() {
BeforeEach(func() {
req = middleware.AddRequestScope(req, &middleware.RequestScope{})
})
It("returns the request method", func() {
Expect(util.GetRequestMethod(req)).To(Equal(http.MethodGet))
})
It("ignores X-Forwarded-Method and returns the request method", func() {
req.Header.Add("X-Forwarded-Method", http.MethodOptions)
Expect(util.GetRequestMethod(req)).To(Equal(http.MethodGet))
})
})
Context("trusted forwarded headers are enabled", func() {
BeforeEach(func() {
req.RemoteAddr = "127.0.0.1:4180"
req = middleware.AddRequestScope(req, &middleware.RequestScope{
ReverseProxy: true,
TrustedProxies: trustedProxies,
})
})
It("returns the request method if X-Forwarded-Method is not present", func() {
Expect(util.GetRequestMethod(req)).To(Equal(http.MethodGet))
})
It("returns the X-Forwarded-Method when present", func() {
req.Header.Add("X-Forwarded-Method", http.MethodOptions)
Expect(util.GetRequestMethod(req)).To(Equal(http.MethodOptions))
})
})
})
Context("CanTrustForwardedHeaders", func() { Context("CanTrustForwardedHeaders", func() {
It("returns false when no scope is present", func() { It("returns false when no scope is present", func() {
Expect(util.CanTrustForwardedHeaders(req)).To(BeFalse()) Expect(util.CanTrustForwardedHeaders(req)).To(BeFalse())