From 7a751f06774bee96fefecba79701f8db38f55c74 Mon Sep 17 00:00:00 2001 From: Omar Elazhary Date: Mon, 8 Feb 2016 15:57:47 +0000 Subject: [PATCH] Allow to pass user headers only (issue #205) * This fixes https://github.com/bitly/oauth2_proxy/issues/205 * Add new boolean option -pass-user-headers to control whether X-Forwarded-User and X-Forwarded-Email headers will be set (as opposed to HTTP BASIC auth) * This is required e.g. for grafana [1] where X-Forwarded-User is needed but HTTP BASIC auth fails (password is not known and must not be known in this scenario) * Keep behaviour of PassBasicAuth unchanged for compatibility [1] http://docs.grafana.org/installation/configuration/#authproxy --- README.md | 1 + contrib/oauth2_proxy.cfg.example | 1 + main.go | 1 + oauthproxy.go | 8 ++++++++ oauthproxy_test.go | 1 + options.go | 2 ++ 6 files changed, 14 insertions(+) diff --git a/README.md b/README.md index 3c0f98fe9..144b0cc33 100644 --- a/README.md +++ b/README.md @@ -163,6 +163,7 @@ Usage of oauth2_proxy: -login-url="": Authentication endpoint -pass-access-token=false: pass OAuth access_token to upstream via X-Forwarded-Access-Token header -pass-basic-auth=true: pass HTTP Basic Auth, X-Forwarded-User and X-Forwarded-Email information to upstream + -pass-user-headers=true: pass X-Forwarded-User and X-Forwarded-Email information to upstream -pass-host-header=true: pass the request Host Header to upstream -profile-url="": Profile access endpoint -provider="google": OAuth provider diff --git a/contrib/oauth2_proxy.cfg.example b/contrib/oauth2_proxy.cfg.example index 4006850a4..0285fbf81 100644 --- a/contrib/oauth2_proxy.cfg.example +++ b/contrib/oauth2_proxy.cfg.example @@ -23,6 +23,7 @@ ## pass HTTP Basic Auth, X-Forwarded-User and X-Forwarded-Email information to upstream # pass_basic_auth = true +# pass_user_headers = true ## pass the request Host Header to upstream ## when disabled the upstream Host is used as the Host Header # pass_host_header = true diff --git a/main.go b/main.go index dd9a100e8..36fbffdf8 100644 --- a/main.go +++ b/main.go @@ -32,6 +32,7 @@ func main() { flagSet.String("redirect-url", "", "the OAuth Redirect URL. ie: \"https://internalapp.yourcompany.com/oauth2/callback\"") flagSet.Var(&upstreams, "upstream", "the http url(s) of the upstream endpoint or file:// paths for static files. Routing is based on the path") flagSet.Bool("pass-basic-auth", true, "pass HTTP Basic Auth, X-Forwarded-User and X-Forwarded-Email information to upstream") + flagSet.Bool("pass-user-headers", true, "pass X-Forwarded-User and X-Forwarded-Email information to upstream") flagSet.String("basic-auth-password", "", "the password to set when passing the HTTP Basic Auth header") flagSet.Bool("pass-access-token", false, "pass OAuth access_token to upstream via X-Forwarded-Access-Token header") flagSet.Bool("pass-host-header", true, "pass the request Host Header to upstream") diff --git a/oauthproxy.go b/oauthproxy.go index 16adf2249..634e48fde 100644 --- a/oauthproxy.go +++ b/oauthproxy.go @@ -59,6 +59,7 @@ type OAuthProxy struct { DisplayHtpasswdForm bool serveMux http.Handler PassBasicAuth bool + PassUserHeaders bool BasicAuthPassword string PassAccessToken bool CookieCipher *cookie.Cipher @@ -193,6 +194,7 @@ func NewOAuthProxy(opts *Options, validator func(string) bool) *OAuthProxy { skipAuthRegex: opts.SkipAuthRegex, compiledRegex: opts.CompiledRegex, PassBasicAuth: opts.PassBasicAuth, + PassUserHeaders: opts.PassUserHeaders, BasicAuthPassword: opts.BasicAuthPassword, PassAccessToken: opts.PassAccessToken, CookieCipher: cipher, @@ -593,6 +595,12 @@ func (p *OAuthProxy) Authenticate(rw http.ResponseWriter, req *http.Request) int req.Header["X-Forwarded-Email"] = []string{session.Email} } } + if p.PassUserHeaders { + req.Header["X-Forwarded-User"] = []string{session.User} + if session.Email != "" { + req.Header["X-Forwarded-Email"] = []string{session.Email} + } + } if p.PassAccessToken && session.AccessToken != "" { req.Header["X-Forwarded-Access-Token"] = []string{session.AccessToken} } diff --git a/oauthproxy_test.go b/oauthproxy_test.go index 7af1de18b..2347b8181 100644 --- a/oauthproxy_test.go +++ b/oauthproxy_test.go @@ -156,6 +156,7 @@ func TestBasicAuthPassword(t *testing.T) { opts.ClientSecret = "foobar" opts.CookieSecure = false opts.PassBasicAuth = true + opts.PassUserHeaders = true opts.BasicAuthPassword = "This is a secure password" opts.Validate() diff --git a/options.go b/options.go index 5d4c86f01..3feea9279 100644 --- a/options.go +++ b/options.go @@ -47,6 +47,7 @@ type Options struct { Upstreams []string `flag:"upstream" cfg:"upstreams"` SkipAuthRegex []string `flag:"skip-auth-regex" cfg:"skip_auth_regex"` PassBasicAuth bool `flag:"pass-basic-auth" cfg:"pass_basic_auth"` + PassUserHeaders bool `flag:"pass-user-headers" cfg:"pass_user_headers"` BasicAuthPassword string `flag:"basic-auth-password" cfg:"basic_auth_password"` PassAccessToken bool `flag:"pass-access-token" cfg:"pass_access_token"` PassHostHeader bool `flag:"pass-host-header" cfg:"pass_host_header"` @@ -91,6 +92,7 @@ func NewOptions() *Options { CookieExpire: time.Duration(168) * time.Hour, CookieRefresh: time.Duration(0), PassBasicAuth: true, + PassUserHeaders: true, PassAccessToken: false, PassHostHeader: true, ApprovalPrompt: "force",