From b625de94904f33130714d92b3a650bd0cef569bf Mon Sep 17 00:00:00 2001 From: Nick Meves Date: Wed, 23 Dec 2020 17:42:02 -0800 Subject: [PATCH] Track the ReverseProxy option in the request Scope This allows for proper handling of reverse proxy based headers throughout the lifecycle of a request. --- oauthproxy.go | 2 +- pkg/apis/middleware/scope.go | 4 ++++ pkg/middleware/scope.go | 26 +++++++++++++------------- pkg/util/util.go | 14 +++++++++++--- 4 files changed, 29 insertions(+), 17 deletions(-) diff --git a/oauthproxy.go b/oauthproxy.go index cfba693..b51b9be 100644 --- a/oauthproxy.go +++ b/oauthproxy.go @@ -231,7 +231,7 @@ func NewOAuthProxy(opts *options.Options, validator func(string) bool) (*OAuthPr // the OAuth2 Proxy authentication logic kicks in. // For example forcing HTTPS or health checks. func buildPreAuthChain(opts *options.Options) (alice.Chain, error) { - chain := alice.New(middleware.NewScope()) + chain := alice.New(middleware.NewScope(opts)) if opts.ForceHTTPS { _, httpsPort, err := net.SplitHostPort(opts.HTTPSAddress) diff --git a/pkg/apis/middleware/scope.go b/pkg/apis/middleware/scope.go index 37f6f33..cb6fe4b 100644 --- a/pkg/apis/middleware/scope.go +++ b/pkg/apis/middleware/scope.go @@ -8,6 +8,10 @@ import ( // The RequestScope is used to pass information between different middlewares // within the chain. type RequestScope struct { + // ReverseProxy tracks whether OAuth2-Proxy is operating in reverse proxy + // mode and if request `X-Forwarded-*` headers should be trusted + ReverseProxy bool + // Session details the authenticated users information (if it exists). Session *sessions.SessionState diff --git a/pkg/middleware/scope.go b/pkg/middleware/scope.go index 8871931..6485cc4 100644 --- a/pkg/middleware/scope.go +++ b/pkg/middleware/scope.go @@ -6,26 +6,26 @@ import ( "github.com/justinas/alice" middlewareapi "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/middleware" + "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/options" ) type scopeKey string -// requestScopeKey uses a typed string to reduce likelihood of clasing +// requestScopeKey uses a typed string to reduce likelihood of clashing // with other context keys const requestScopeKey scopeKey = "request-scope" -func NewScope() alice.Constructor { - return addScope -} - -// addScope injects a new request scope into the request context. -func addScope(next http.Handler) http.Handler { - return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { - scope := &middlewareapi.RequestScope{} - contextWithScope := context.WithValue(req.Context(), requestScopeKey, scope) - requestWithScope := req.WithContext(contextWithScope) - next.ServeHTTP(rw, requestWithScope) - }) +func NewScope(opts *options.Options) alice.Constructor { + return func(next http.Handler) http.Handler { + return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { + scope := &middlewareapi.RequestScope{ + ReverseProxy: opts.ReverseProxy, + } + contextWithScope := context.WithValue(req.Context(), requestScopeKey, scope) + requestWithScope := req.WithContext(contextWithScope) + next.ServeHTTP(rw, requestWithScope) + }) + } } // GetRequestScope returns the current request scope from the given request diff --git a/pkg/util/util.go b/pkg/util/util.go index 4eeabbf..452e14f 100644 --- a/pkg/util/util.go +++ b/pkg/util/util.go @@ -5,6 +5,8 @@ import ( "fmt" "io/ioutil" "net/http" + + "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/middleware" ) func GetCertPool(paths []string) (*x509.CertPool, error) { @@ -28,16 +30,17 @@ func GetCertPool(paths []string) (*x509.CertPool, error) { // GetRequestProto return the request host header or X-Forwarded-Proto if present func GetRequestProto(req *http.Request) string { proto := req.Header.Get("X-Forwarded-Proto") - if proto == "" { + if !isProxied(req) || proto == "" { proto = req.URL.Scheme } return proto } // GetRequestHost return the request host header or X-Forwarded-Host if present +// and reverse proxy mode is enabled. func GetRequestHost(req *http.Request) string { host := req.Header.Get("X-Forwarded-Host") - if host == "" { + if !isProxied(req) || host == "" { host = req.Host } return host @@ -46,9 +49,14 @@ func GetRequestHost(req *http.Request) string { // GetRequestURI return the request host header or X-Forwarded-Uri if present func GetRequestURI(req *http.Request) string { uri := req.Header.Get("X-Forwarded-Uri") - if uri == "" { + if !isProxied(req) || uri == "" { // Use RequestURI to preserve ?query uri = req.URL.RequestURI() } return uri } + +func isProxied(req *http.Request) bool { + scope := middleware.GetRequestScope(req) + return scope.ReverseProxy +}