From 24f91a0b6039a96270e9f6cd10e03d9ac270d5de 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 539da89..eb7ffb4 100644 --- a/README.md +++ b/README.md @@ -187,6 +187,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 4006850..0285fbf 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 ba33668..d7c53b0 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 f1a6920..0070373 100644 --- a/oauthproxy.go +++ b/oauthproxy.go @@ -60,6 +60,7 @@ type OAuthProxy struct { serveMux http.Handler PassBasicAuth bool SkipProviderButton bool + PassUserHeaders bool BasicAuthPassword string PassAccessToken bool CookieCipher *cookie.Cipher @@ -194,6 +195,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, SkipProviderButton: opts.SkipProviderButton, @@ -602,6 +604,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 59a0ada..f62471d 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 4777d9d..680d329 100644 --- a/options.go +++ b/options.go @@ -54,6 +54,7 @@ type Options struct { PassAccessToken bool `flag:"pass-access-token" cfg:"pass_access_token"` PassHostHeader bool `flag:"pass-host-header" cfg:"pass_host_header"` SkipProviderButton bool `flag:"skip-provider-button" cfg:"skip_provider_button"` + PassUserHeaders bool `flag:"pass-user-headers" cfg:"pass_user_headers"` // These options allow for other providers besides Google, with // potential overrides. @@ -95,6 +96,7 @@ func NewOptions() *Options { CookieExpire: time.Duration(168) * time.Hour, CookieRefresh: time.Duration(0), PassBasicAuth: true, + PassUserHeaders: true, PassAccessToken: false, PassHostHeader: true, SkipProviderButton: false,