diff --git a/CHANGELOG.md b/CHANGELOG.md index d1b0250b..6eb8409a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,7 @@ FEATURES * added the --skip-client-id option to permit skipping the verification of the auduence against client in token [#PR236](https://github.com/gambol99/keycloak-proxy/pull/236) * updated the base image to apline 3.6 in commit [0fdebaf821](https://github.com/gambol99/keycloak-proxy/pull/236/commits/0fdebaf8215e9480896f01ec7ab2ef7caa242da1) * moved to use zap for the logging [#PR237](https://github.com/gambol99/keycloak-proxy/pull/237) +* making the X-Auth-Token optional in the upstream headers via the --enable-token-header [#PR247](https://github.com/gambol99/keycloak-proxy/pull/247) BREAKING CHANGES: * the proxy no longer uses prefixes for resources, if you wish to use wildcard urls you need diff --git a/README.md b/README.md index 1900f006..93e91ead 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ USAGE: keycloak-proxy [options] VERSION: - v2.1.0 (git+sha: 960c2e5-dirty, built: 25/04/2017) + v2.1.0-rc2 (git+sha: 6782490-dirty, built: 06-07-2017) AUTHOR: Rohith @@ -55,7 +55,8 @@ GLOBAL OPTIONS: --upstream-url value url for the upstream endpoint you wish to proxy [$PROXY_UPSTREAM_URL] --resources value list of resources 'uri=/admin|methods=GET,PUT|roles=role1,role2' --headers value custom headers to the upstream request, key=value - --enable-encrypted-token indicates you want the access token encrypted (default: false) + --enable-token-header enables the token authentication header X-Auth-Token to upstream (default: true) + --enable-encrypted-token enable encryption for the access tokens (default: false) --enable-logging enable http logging of the requests (default: false) --enable-json-logging switch on json logging rather than text (default: false) --enable-forwarding enables the forwarding proxy mode, signing outbound request (default: false) @@ -85,6 +86,7 @@ GLOBAL OPTIONS: --tls-ca-key value path the ca private key, used by the forward signing proxy --tls-client-certificate value path to the client certificate for outbound connections in reverse and forwarding proxy modes --skip-upstream-tls-verify skip the verification of any upstream TLS (default: true) + --skip-client-id skip the check on the client token (default: false) --cors-origins value origins to add to the CORE origins control (Access-Control-Allow-Origin) --cors-methods value methods permitted in the access control (Access-Control-Allow-Methods) --cors-headers value set of headers to add to the CORS access control (Access-Control-Allow-Headers) @@ -107,6 +109,7 @@ GLOBAL OPTIONS: --forwarding-username value username to use when logging into the openid provider --forwarding-password value password to use when logging into the openid provider --forwarding-domains value list of domains which should be signed; everything else is relayed unsigned + --disable-all-logging disables all logging to stdout and stderr (default: false) --help, -h show help --version, -v print the version ``` diff --git a/config.go b/config.go index da329a0f..ee7c48a7 100644 --- a/config.go +++ b/config.go @@ -34,6 +34,7 @@ func newDefaultConfig() *Config { UpstreamTimeout: time.Duration(10) * time.Second, UpstreamKeepaliveTimeout: time.Duration(10) * time.Second, EnableAuthorizationHeader: true, + EnableTokenHeader: true, CookieAccessName: "kc-access", CookieRefreshName: "kc-state", SecureCookie: true, diff --git a/doc.go b/doc.go index 595569df..631b8436 100644 --- a/doc.go +++ b/doc.go @@ -130,6 +130,8 @@ type Config struct { // Headers permits adding customs headers across the board Headers map[string]string `json:"headers" yaml:"headers" usage:"custom headers to the upstream request, key=value"` + // EnableTokenHeader adds the JWT token to the upstream authentication headers + EnableTokenHeader bool `json:"enable-token-header" yaml:"enable-token-header" usage:"enables the token authentication header X-Auth-Token to upstream"` // EnableEncryptedToken indicates the access token should be encoded EnableEncryptedToken bool `json:"enable-encrypted-token" yaml:"enable-encrypted-token" usage:"enable encryption for the access tokens"` // EnableLogging indicates if we should log all the requests diff --git a/middleware.go b/middleware.go index f16a6584..d7bc7910 100644 --- a/middleware.go +++ b/middleware.go @@ -34,8 +34,6 @@ import ( const ( // normalizeFlags is the options to purell normalizeFlags purell.NormalizationFlags = purell.FlagRemoveDotSegments | purell.FlagRemoveDuplicateSlashes - // httpResponseName is the name of the http response hanlder - httpResponseName = "http.response" ) // entrypointMiddleware is custom filtering for incoming requests @@ -328,14 +326,17 @@ func (r *oauthProxy) headersMiddleware(custom []string) func(http.Handler) http. req.Header.Set("X-Auth-ExpiresIn", user.expiresAt.String()) req.Header.Set("X-Auth-Roles", strings.Join(user.roles, ",")) req.Header.Set("X-Auth-Subject", user.id) - req.Header.Set("X-Auth-Token", user.token.Encode()) req.Header.Set("X-Auth-Userid", user.name) req.Header.Set("X-Auth-Username", user.name) - + // should we add the token header? + if r.config.EnableTokenHeader { + req.Header.Set("X-Auth-Token", user.token.Encode()) + } // add the authorization header if requested if r.config.EnableAuthorizationHeader { req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", user.token.Encode())) } + // inject any custom claims for claim, header := range customClaims { if claim, found := user.claims[claim]; found { diff --git a/server_test.go b/server_test.go index 36ff79d6..5b8e0ef1 100644 --- a/server_test.go +++ b/server_test.go @@ -287,6 +287,46 @@ func TestSkipClientIDEnabled(t *testing.T) { p.RunTests(t, requests) } +func TestAuthTokenHeaderEnabled(t *testing.T) { + p := newFakeProxy(nil) + token := newTestToken(p.idp.getLocation()) + signed, _ := p.idp.signToken(token.claims) + + requests := []fakeRequest{ + { + URI: "/auth_all/test", + RawToken: signed.Encode(), + ExpectedProxyHeaders: map[string]string{ + "X-Auth-Token": signed.Encode(), + }, + ExpectedProxy: true, + ExpectedCode: http.StatusOK, + }, + } + p.RunTests(t, requests) +} + +func TestAuthTokenHeaderDisabled(t *testing.T) { + c := newFakeKeycloakConfig() + c.EnableTokenHeader = false + p := newFakeProxy(c) + token := newTestToken(p.idp.getLocation()) + signed, _ := p.idp.signToken(token.claims) + + requests := []fakeRequest{ + { + URI: "/auth_all/test", + RawToken: signed.Encode(), + ExpectedProxyHeaders: map[string]string{ + "X-Auth-Token": "", + }, + ExpectedProxy: true, + ExpectedCode: http.StatusOK, + }, + } + p.RunTests(t, requests) +} + func newTestService() string { _, _, u := newTestProxyService(nil) return u @@ -344,6 +384,7 @@ func newFakeKeycloakConfig() *Config { EnableAuthorizationHeader: true, EnableLogging: false, EnableLoginHandler: true, + EnableTokenHeader: true, Listen: "127.0.0.1:0", Scopes: []string{}, Verbose: true,