Skip to content
Snippets Groups Projects
Commit fe9654c5 authored by Rohith's avatar Rohith Committed by GitHub
Browse files

- adding the ability to choose proxying the Authorization header (#133)

parent 1342c33e
No related branches found
No related tags found
No related merge requests found
#### **1.2.7**
FIXES:
* Added unit tests for the logout handlers
* Added unit tests for the authorization header handling
FEATURES:
* Allow the user to enable or disable adding the Authorization header
#### **1.2.6** #### **1.2.6**
FIXES: FIXES:
......
...@@ -163,6 +163,10 @@ func getCLIOptions() []cli.Flag { ...@@ -163,6 +163,10 @@ func getCLIOptions() []cli.Flag {
Usage: "specifies the keep-alive period for an active network connection", Usage: "specifies the keep-alive period for an active network connection",
Value: defaults.UpstreamKeepaliveTimeout, Value: defaults.UpstreamKeepaliveTimeout,
}, },
cli.BoolTFlag{
Name: "enable-authorization-header",
Usage: "adds the authorization header to the proxy request",
},
cli.BoolFlag{ cli.BoolFlag{
Name: "enable-refresh-tokens", Name: "enable-refresh-tokens",
Usage: "enables the handling of the refresh tokens", Usage: "enables the handling of the refresh tokens",
...@@ -423,6 +427,9 @@ func parseCLIOptions(cx *cli.Context, config *Config) (err error) { ...@@ -423,6 +427,9 @@ func parseCLIOptions(cx *cli.Context, config *Config) (err error) {
if cx.IsSet("enable-forwarding") { if cx.IsSet("enable-forwarding") {
config.EnableForwarding = cx.Bool("enable-forwarding") config.EnableForwarding = cx.Bool("enable-forwarding")
} }
if cx.IsSet("enable-authorization-header") {
config.EnableAuthorizationHeader = cx.Bool("enable-authorization-header")
}
if cx.IsSet("enable-refresh-tokens") { if cx.IsSet("enable-refresh-tokens") {
config.EnableRefreshTokens = cx.Bool("enable-refresh-tokens") config.EnableRefreshTokens = cx.Bool("enable-refresh-tokens")
} }
......
...@@ -32,6 +32,7 @@ func newDefaultConfig() *Config { ...@@ -32,6 +32,7 @@ func newDefaultConfig() *Config {
Headers: make(map[string]string, 0), Headers: make(map[string]string, 0),
UpstreamTimeout: time.Duration(10) * time.Second, UpstreamTimeout: time.Duration(10) * time.Second,
UpstreamKeepaliveTimeout: time.Duration(10) * time.Second, UpstreamKeepaliveTimeout: time.Duration(10) * time.Second,
EnableAuthorizationHeader: true,
CookieAccessName: "kc-access", CookieAccessName: "kc-access",
CookieRefreshName: "kc-state", CookieRefreshName: "kc-state",
SecureCookie: true, SecureCookie: true,
......
...@@ -24,7 +24,7 @@ import ( ...@@ -24,7 +24,7 @@ import (
) )
var ( var (
release = "v1.2.6" release = "v1.2.7"
gitsha = "no gitsha provided" gitsha = "no gitsha provided"
version = release + " (git+sha: " + gitsha + ")" version = release + " (git+sha: " + gitsha + ")"
) )
...@@ -130,6 +130,9 @@ type Config struct { ...@@ -130,6 +130,9 @@ type Config struct {
// LocalhostMetrics indicated the metrics can only be consume via localhost // LocalhostMetrics indicated the metrics can only be consume via localhost
LocalhostMetrics bool `json:"localhost-only-metrics" yaml:"localhost-only-metrics"` LocalhostMetrics bool `json:"localhost-only-metrics" yaml:"localhost-only-metrics"`
// EnableAuthorizationHeader indicates we should pass the authorization header
EnableAuthorizationHeader bool `json:"enable-authorization-header" yaml:"enable-authorization-header"`
// CookieDomain is a list of domains the cookie is available to // CookieDomain is a list of domains the cookie is available to
CookieDomain string `json:"cookie-domain" yaml:"cookie-domain"` CookieDomain string `json:"cookie-domain" yaml:"cookie-domain"`
// CookieAccessName is the name of the access cookie holding the access token // CookieAccessName is the name of the access cookie holding the access token
......
...@@ -427,7 +427,11 @@ func (r *oauthProxy) headersMiddleware(custom []string) gin.HandlerFunc { ...@@ -427,7 +427,11 @@ func (r *oauthProxy) headersMiddleware(custom []string) gin.HandlerFunc {
cx.Request.Header.Add("X-Auth-ExpiresIn", id.expiresAt.String()) cx.Request.Header.Add("X-Auth-ExpiresIn", id.expiresAt.String())
cx.Request.Header.Add("X-Auth-Token", id.token.Encode()) cx.Request.Header.Add("X-Auth-Token", id.token.Encode())
cx.Request.Header.Add("X-Auth-Roles", strings.Join(id.roles, ",")) cx.Request.Header.Add("X-Auth-Roles", strings.Join(id.roles, ","))
// step: add the authorization header if requested
if r.config.EnableAuthorizationHeader {
cx.Request.Header.Set("Authorization", fmt.Sprintf("Bearer %s", id.token.Encode())) cx.Request.Header.Set("Authorization", fmt.Sprintf("Bearer %s", id.token.Encode()))
}
// step: inject any custom claims // step: inject any custom claims
for claim, header := range customClaims { for claim, header := range customClaims {
......
...@@ -327,6 +327,57 @@ func TestCustomHeadersHandler(t *testing.T) { ...@@ -327,6 +327,57 @@ func TestCustomHeadersHandler(t *testing.T) {
} }
} }
func TestHeaderMiddlewareAuthorizationHeader(t *testing.T) {
cases := []struct {
Identity *userContext
Expected http.Header
Enabled bool
}{
{
Enabled: true,
Identity: &userContext{
email: "gambol99@gmail.com",
},
Expected: http.Header{
"X-Auth-Email": []string{"gambol99@gmail.com"},
"Authorization": []string{"Bearer .."},
},
},
{
Enabled: false,
Identity: &userContext{
email: "gambol99@gmail.com",
},
Expected: http.Header{
"X-Auth-Email": []string{"gambol99@gmail.com"},
"Authorization": []string{""},
},
},
}
for i, x := range cases {
config := newFakeKeycloakConfig()
config.EnableAuthorizationHeader = x.Enabled
// step: create the test proxy
p, _, _ := newTestProxyService(config)
context := newFakeGinContext("GET", "/test_url")
if x.Identity != nil {
context.Set(userContextName, x.Identity)
}
// step: create a middleware handler
handler := p.headersMiddleware([]string{})
handler(context)
// step: and check we have all the headers
for k := range x.Expected {
assert.Equal(t, x.Expected.Get(k), context.Request.Header.Get(k),
"case %d, expected (%s: %s) got: (%s: %s)",
i, k, x.Expected.Get(k), k, context.Request.Header.Get(k))
}
}
}
func TestAdmissionHandlerRoles(t *testing.T) { func TestAdmissionHandlerRoles(t *testing.T) {
proxy := newFakeKeycloakProxyWithResources(t, []*Resource{ proxy := newFakeKeycloakProxyWithResources(t, []*Resource{
{ {
......
...@@ -275,7 +275,6 @@ func (r *oauthProxy) createForwardingProxy() error { ...@@ -275,7 +275,6 @@ func (r *oauthProxy) createForwardingProxy() error {
// Run starts the proxy service // Run starts the proxy service
// //
func (r *oauthProxy) Run() error { func (r *oauthProxy) Run() error {
var err error
tlsConfig := &tls.Config{} tlsConfig := &tls.Config{}
// step: are we doing mutual tls? // step: are we doing mutual tls?
...@@ -299,6 +298,7 @@ func (r *oauthProxy) Run() error { ...@@ -299,6 +298,7 @@ func (r *oauthProxy) Run() error {
// step: create the listener // step: create the listener
var listener net.Listener var listener net.Listener
var err error
switch strings.HasPrefix(r.config.Listen, "unix://") { switch strings.HasPrefix(r.config.Listen, "unix://") {
case true: case true:
socket := strings.Trim(r.config.Listen, "unix://") socket := strings.Trim(r.config.Listen, "unix://")
......
...@@ -128,16 +128,19 @@ func getFakeRealmAccessToken(t *testing.T) jose.JWT { ...@@ -128,16 +128,19 @@ func getFakeRealmAccessToken(t *testing.T) jose.JWT {
func newFakeKeycloakConfig() *Config { func newFakeKeycloakConfig() *Config {
return &Config{ return &Config{
DiscoveryURL: "127.0.0.1:8080",
ClientID: fakeClientID, ClientID: fakeClientID,
ClientSecret: fakeSecret, ClientSecret: fakeSecret,
CookieAccessName: "kc-access",
CookieRefreshName: "kc-state",
DiscoveryURL: "127.0.0.1:8080",
EnableAuthorizationHeader: true,
EnableRefreshTokens: false,
EncryptionKey: "AgXa7xRcoClDEU0ZDSH4X0XhL5Qy2Z2j", EncryptionKey: "AgXa7xRcoClDEU0ZDSH4X0XhL5Qy2Z2j",
SkipTokenVerification: true, LogRequests: true,
Scopes: []string{}, Scopes: []string{},
EnableRefreshTokens: false,
SecureCookie: false, SecureCookie: false,
CookieAccessName: "kc-access", SkipTokenVerification: false,
CookieRefreshName: "kc-state", Verbose: false,
Resources: []*Resource{ Resources: []*Resource{
{ {
URL: fakeAdminRoleURL, URL: fakeAdminRoleURL,
...@@ -194,11 +197,8 @@ func newTestProxyService(config *Config) (*oauthProxy, *fakeOAuthServer, string) ...@@ -194,11 +197,8 @@ func newTestProxyService(config *Config) (*oauthProxy, *fakeOAuthServer, string)
} }
// step: set the config // step: set the config
config.LogRequests = true
config.SkipTokenVerification = false
config.DiscoveryURL = auth.getLocation() config.DiscoveryURL = auth.getLocation()
config.RevocationEndpoint = auth.getRevocationURL() config.RevocationEndpoint = auth.getRevocationURL()
config.Verbose = false
// step: create a proxy // step: create a proxy
proxy, err := newProxy(config) proxy, err := newProxy(config)
...@@ -231,7 +231,10 @@ func newFakeKeycloakProxyWithResources(t *testing.T, resources []*Resource) *oau ...@@ -231,7 +231,10 @@ func newFakeKeycloakProxyWithResources(t *testing.T, resources []*Resource) *oau
} }
func TestNewKeycloakProxy(t *testing.T) { func TestNewKeycloakProxy(t *testing.T) {
proxy, err := newProxy(newFakeKeycloakConfig()) cfg := newFakeKeycloakConfig()
cfg.DiscoveryURL = newFakeOAuthServer().getLocation()
proxy, err := newProxy(cfg)
assert.NoError(t, err) assert.NoError(t, err)
assert.NotNil(t, proxy) assert.NotNil(t, proxy)
assert.NotNil(t, proxy.config) assert.NotNil(t, proxy.config)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment