From 1fd0bc71e6d98ef518daeab0b520d2a796c904da Mon Sep 17 00:00:00 2001 From: Lukasz Siudut Date: Thu, 20 Oct 2016 17:49:59 +0530 Subject: [PATCH] add --set-xauthrequest flag for use in Nginx auth_request mode This is enhancement of #173 to use "Auth Request" consistently in the command-line option, configuration file and response headers. It always sets the X-Auth-Request-User response header and if the email is available, sets X-Auth-Request-Email as well. --- main.go | 1 + oauthproxy.go | 8 ++++++++ oauthproxy_test.go | 30 ++++++++++++++++++++++++++++++ options.go | 2 ++ 4 files changed, 41 insertions(+) diff --git a/main.go b/main.go index ba3366876..ee501f1c5 100644 --- a/main.go +++ b/main.go @@ -30,6 +30,7 @@ func main() { flagSet.String("tls-cert", "", "path to certificate file") flagSet.String("tls-key", "", "path to private key file") flagSet.String("redirect-url", "", "the OAuth Redirect URL. ie: \"https://internalapp.yourcompany.com/oauth2/callback\"") + flagSet.Bool("set-xauthrequest", false, "set X-Auth-Request-User and X-Auth-Request-Email response headers (useful in Nginx auth_request mode)") 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.String("basic-auth-password", "", "the password to set when passing the HTTP Basic Auth header") diff --git a/oauthproxy.go b/oauthproxy.go index f1a6920e7..f0bac3f09 100644 --- a/oauthproxy.go +++ b/oauthproxy.go @@ -58,6 +58,7 @@ type OAuthProxy struct { HtpasswdFile *HtpasswdFile DisplayHtpasswdForm bool serveMux http.Handler + SetXAuthRequest bool PassBasicAuth bool SkipProviderButton bool BasicAuthPassword string @@ -193,6 +194,7 @@ func NewOAuthProxy(opts *Options, validator func(string) bool) *OAuthProxy { redirectURL: redirectURL, skipAuthRegex: opts.SkipAuthRegex, compiledRegex: opts.CompiledRegex, + SetXAuthRequest: opts.SetXAuthRequest, PassBasicAuth: opts.PassBasicAuth, BasicAuthPassword: opts.BasicAuthPassword, PassAccessToken: opts.PassAccessToken, @@ -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.SetXAuthRequest { + rw.Header().Set("X-Auth-Request-User", session.User) + if session.Email != "" { + rw.Header().Set("X-Auth-Request-Email", 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 59a0adae9..86ac2087f 100644 --- a/oauthproxy_test.go +++ b/oauthproxy_test.go @@ -595,6 +595,36 @@ func TestAuthOnlyEndpointUnauthorizedOnEmailValidationFailure(t *testing.T) { assert.Equal(t, "unauthorized request\n", string(bodyBytes)) } +func TestAuthOnlyEndpointSetXAuthRequestHeaders(t *testing.T) { + var pc_test ProcessCookieTest + + pc_test.opts = NewOptions() + pc_test.opts.SetXAuthRequest = true + pc_test.opts.Validate() + + pc_test.proxy = NewOAuthProxy(pc_test.opts, func(email string) bool { + return pc_test.validate_user + }) + pc_test.proxy.provider = &TestProvider{ + ValidToken: true, + } + + pc_test.validate_user = true + + pc_test.rw = httptest.NewRecorder() + pc_test.req, _ = http.NewRequest("GET", + pc_test.opts.ProxyPrefix+"/auth", nil) + + startSession := &providers.SessionState{ + User: "oauth_user", Email: "oauth_user@example.com", AccessToken: "oauth_token"} + pc_test.SaveSession(startSession, time.Now()) + + pc_test.proxy.ServeHTTP(pc_test.rw, pc_test.req) + assert.Equal(t, http.StatusAccepted, pc_test.rw.Code) + assert.Equal(t, "oauth_user", pc_test.rw.HeaderMap["X-Auth-Request-User"][0]) + assert.Equal(t, "oauth_user@example.com", pc_test.rw.HeaderMap["X-Auth-Request-Email"][0]) +} + type SignatureAuthenticator struct { auth hmacauth.HmacAuth } diff --git a/options.go b/options.go index 4777d9d1e..e2c5e5115 100644 --- a/options.go +++ b/options.go @@ -47,6 +47,7 @@ type Options struct { CookieSecure bool `flag:"cookie-secure" cfg:"cookie_secure"` CookieHttpOnly bool `flag:"cookie-httponly" cfg:"cookie_httponly"` + SetXAuthRequest bool `flag:"set-xauthrequest" cfg:"set_xauthrequest"` 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"` @@ -94,6 +95,7 @@ func NewOptions() *Options { CookieHttpOnly: true, CookieExpire: time.Duration(168) * time.Hour, CookieRefresh: time.Duration(0), + SetXAuthRequest: false, PassBasicAuth: true, PassAccessToken: false, PassHostHeader: true,