From 78df804e15a7e348c20cef9712172eee64d5c3f8 Mon Sep 17 00:00:00 2001 From: Stefan Bodewig Date: Thu, 5 Jul 2018 17:13:04 +0200 Subject: [PATCH] optionally expose the access token in a response header --- README.md | 1 + main.go | 1 + oauthproxy.go | 7 ++++++- oauthproxy_test.go | 30 ++++++++++++++++++++++++++++++ options.go | 2 ++ 5 files changed, 40 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 03c753cce..cb8352a9b 100644 --- a/README.md +++ b/README.md @@ -214,6 +214,7 @@ Usage of oauth2_proxy: -resource string: The resource that is protected (Azure AD only) -scope string: OAuth scope specification -set-xauthrequest: set X-Auth-Request-User and X-Auth-Request-Email response headers (useful in Nginx auth_request mode) + -set-xaccesstoken: set X-Access-Token response headers (useful in Nginx auth_request mode) -signature-key string: GAP-Signature request signature key (algorithm:secretkey) -skip-auth-preflight: will skip authentication for OPTIONS requests -skip-auth-regex value: bypass authentication for requests path's that match (may be given multiple times) diff --git a/main.go b/main.go index 287dc4894..bb63f1497 100644 --- a/main.go +++ b/main.go @@ -31,6 +31,7 @@ func main() { 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.Bool("set-xaccesstoken", false, "set X-Access-Token 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.Bool("pass-user-headers", true, "pass X-Forwarded-User and X-Forwarded-Email information to upstream") diff --git a/oauthproxy.go b/oauthproxy.go index 21e5dfc74..438b2a51c 100644 --- a/oauthproxy.go +++ b/oauthproxy.go @@ -61,6 +61,7 @@ type OAuthProxy struct { DisplayHtpasswdForm bool serveMux http.Handler SetXAuthRequest bool + SetXAccessToken bool PassBasicAuth bool SkipProviderButton bool PassUserHeaders bool @@ -163,7 +164,7 @@ func NewOAuthProxy(opts *Options, validator func(string) bool) *OAuthProxy { log.Printf("Cookie settings: name:%s secure(https):%v httponly:%v expiry:%s domain:%s refresh:%s", opts.CookieName, opts.CookieSecure, opts.CookieHttpOnly, opts.CookieExpire, opts.CookieDomain, refresh) var cipher *cookie.Cipher - if opts.PassAccessToken || (opts.CookieRefresh != time.Duration(0)) { + if opts.PassAccessToken || opts.SetXAccessToken || (opts.CookieRefresh != time.Duration(0)) { var err error cipher, err = cookie.NewCipher(secretBytes(opts.CookieSecret)) if err != nil { @@ -198,6 +199,7 @@ func NewOAuthProxy(opts *Options, validator func(string) bool) *OAuthProxy { skipAuthPreflight: opts.SkipAuthPreflight, compiledRegex: opts.CompiledRegex, SetXAuthRequest: opts.SetXAuthRequest, + SetXAccessToken: opts.SetXAccessToken, PassBasicAuth: opts.PassBasicAuth, PassUserHeaders: opts.PassUserHeaders, BasicAuthPassword: opts.BasicAuthPassword, @@ -695,6 +697,9 @@ func (p *OAuthProxy) Authenticate(rw http.ResponseWriter, req *http.Request) int rw.Header().Set("X-Auth-Request-Email", session.Email) } } + if p.SetXAccessToken && session.AccessToken != "" { + rw.Header().Set("X-Access-Token", session.AccessToken) + } 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 1e6b3140d..2a7d98287 100644 --- a/oauthproxy_test.go +++ b/oauthproxy_test.go @@ -674,6 +674,36 @@ func TestAuthOnlyEndpointSetXAuthRequestHeaders(t *testing.T) { assert.Equal(t, "oauth_user@example.com", pc_test.rw.HeaderMap["X-Auth-Request-Email"][0]) } +func TestAuthOnlyEndpointSetXAccessToken(t *testing.T) { + var pc_test ProcessCookieTest + + pc_test.opts = NewOptions() + pc_test.opts.SetXAccessToken = true + pc_test.opts.CookieSecret = "0123456789abcdefghijklmnopqrstuv" + 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_token", pc_test.rw.HeaderMap["X-Access-Token"][0]) +} + func TestAuthSkippedForPreflightRequests(t *testing.T) { upstream := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(200) diff --git a/options.go b/options.go index 949fbba80..109e28585 100644 --- a/options.go +++ b/options.go @@ -60,6 +60,7 @@ type Options struct { PassUserHeaders bool `flag:"pass-user-headers" cfg:"pass_user_headers"` SSLInsecureSkipVerify bool `flag:"ssl-insecure-skip-verify" cfg:"ssl_insecure_skip_verify"` SetXAuthRequest bool `flag:"set-xauthrequest" cfg:"set_xauthrequest"` + SetXAccessToken bool `flag:"set-xaccesstoken" cfg:"set_xaccesstoken"` SkipAuthPreflight bool `flag:"skip-auth-preflight" cfg:"skip_auth_preflight"` // These options allow for other providers besides Google, with @@ -105,6 +106,7 @@ func NewOptions() *Options { CookieExpire: time.Duration(168) * time.Hour, CookieRefresh: time.Duration(0), SetXAuthRequest: false, + SetXAccessToken: false, SkipAuthPreflight: false, PassBasicAuth: true, PassUserHeaders: true,