diff --git a/internal/proxy/oauthproxy.go b/internal/proxy/oauthproxy.go index 6b0463ac..a4e30e07 100755 --- a/internal/proxy/oauthproxy.go +++ b/internal/proxy/oauthproxy.go @@ -70,6 +70,8 @@ type OAuthProxy struct { skipAuthPreflight bool templates *template.Template + PassAccessToken bool + StatsdClient *statsd.Client mux map[string]*route @@ -303,6 +305,7 @@ func NewOAuthProxy(opts *Options, optFuncs ...func(*OAuthProxy) error) (*OAuthPr redirectURL: &url.URL{Path: "/oauth2/callback"}, skipAuthPreflight: opts.SkipAuthPreflight, templates: getTemplates(), + PassAccessToken: opts.PassAccessToken, } for _, optFunc := range optFuncs { @@ -1037,6 +1040,11 @@ func (p *OAuthProxy) Authenticate(rw http.ResponseWriter, req *http.Request) (er } req.Header.Set("X-Forwarded-User", session.User) + + if p.PassAccessToken && session.AccessToken != "" { + req.Header.Set("X-Forwarded-Access-Token", session.AccessToken) + } + req.Header.Set("X-Forwarded-Email", session.Email) req.Header.Set("X-Forwarded-Groups", strings.Join(session.Groups, ",")) diff --git a/internal/proxy/oauthproxy_test.go b/internal/proxy/oauthproxy_test.go index f97aad5a..8824af0e 100644 --- a/internal/proxy/oauthproxy_test.go +++ b/internal/proxy/oauthproxy_test.go @@ -999,6 +999,7 @@ func TestHeadersSentToUpstreams(t *testing.T) { opts.ClientSecret = "foobar" opts.CookieSecret = testEncodedCookieSecret opts.CookieSecure = false + opts.PassAccessToken = true opts.upstreamConfigs = generateTestUpstreamConfigs(upstream.URL) opts.Validate() providerURL, _ := url.Parse("http://sso-auth.example.com/") @@ -1007,6 +1008,7 @@ func TestHeadersSentToUpstreams(t *testing.T) { state := testSession() state.Email = "foo@example.com" state.User = "foo" + state.AccessToken = "SupErSensItiveAccesSToken" state.Groups = []string{"fooGroup"} proxy, _ := NewOAuthProxy(opts, testValidatorFunc(true)) @@ -1041,10 +1043,11 @@ func TestHeadersSentToUpstreams(t *testing.T) { } expectedHeaders := map[string]string{ - "X-Forwarded-Email": "foo@example.com", - "X-Forwarded-User": "foo", - "X-Forwarded-Groups": "fooGroup", - "Cookie": tc.expectedCookieHeader, + "X-Forwarded-Email": "foo@example.com", + "X-Forwarded-User": "foo", + "X-Forwarded-Groups": "fooGroup", + "X-Forwarded-Access-Token": "SupErSensItiveAccesSToken", + "Cookie": tc.expectedCookieHeader, } for key, val := range expectedHeaders { diff --git a/internal/proxy/options.go b/internal/proxy/options.go index 7ec0bee9..52865819 100644 --- a/internal/proxy/options.go +++ b/internal/proxy/options.go @@ -36,6 +36,7 @@ import ( // CookieExpire - expire timeframe for cookie // CookieSecure - set secure (HTTPS) cookie flag // CookieHTTPOnly - set HttpOnly cookie flag +// PassAccessToken - send access token in the http headers // Provider - OAuth provider // Scope - OAuth scope specification // SessionLifetimeTTL - time to live for a session lifetime @@ -71,6 +72,8 @@ type Options struct { CookieSecure bool `envconfig:"COOKIE_SECURE" default:"true"` CookieHTTPOnly bool `envconfig:"COOKIE_HTTP_ONLY"` + PassAccessToken bool `envconfig:"PASS_ACCESS_TOKEN" default:"false"` + // These options allow for other providers besides Google, with potential overrides. Provider string `envconfig:"PROVIDER" default:"google"` Scope string `envconfig:"SCOPE"` @@ -106,6 +109,7 @@ func NewOptions() *Options { SkipAuthPreflight: false, RequestLogging: true, DefaultUpstreamTimeout: time.Duration(1) * time.Second, + PassAccessToken: false, } } diff --git a/internal/proxy/options_test.go b/internal/proxy/options_test.go index fdce6899..5cc2d275 100644 --- a/internal/proxy/options_test.go +++ b/internal/proxy/options_test.go @@ -183,3 +183,11 @@ func TestValidateCookieBadName(t *testing.T) { testutil.Equal(t, err.Error(), "Invalid configuration:\n"+ fmt.Sprintf(" invalid cookie name: %q", o.CookieName)) } + +func TestPassAccessToken(t *testing.T) { + o := testOptions() + testutil.Equal(t, false, o.PassAccessToken) + o.PassAccessToken = true + testutil.Equal(t, nil, o.Validate()) + testutil.Equal(t, true, o.PassAccessToken) +}