Skip to content

Commit

Permalink
Merge pull request #58 from p53/tests-token-encryption-and-headers
Browse files Browse the repository at this point in the history
Refactor tests
  • Loading branch information
p53 authored Feb 19, 2021
2 parents 36b650c + a73933b commit 2319809
Show file tree
Hide file tree
Showing 2 changed files with 272 additions and 91 deletions.
257 changes: 167 additions & 90 deletions middleware_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,40 +41,42 @@ const (
)

type fakeRequest struct {
BasicAuth bool
Cookies []*http.Cookie
Expires time.Duration
FormValues map[string]string
Groups []string
HasCookieToken bool
HasLogin bool
HasToken bool
Headers map[string]string
Method string
NotSigned bool
OnResponse func(int, *resty.Request, *resty.Response)
Password string
ProxyProtocol string
ProxyRequest bool
RawToken string
Redirects bool
Roles []string
SkipClientIDCheck bool
SkipIssuerCheck bool
TokenClaims map[string]interface{}
URI string
URL string
Username string
ExpectedCode int
ExpectedContent func(body string, testNum int)
ExpectedContentContains string
ExpectedCookies map[string]string
ExpectedHeaders map[string]string
ExpectedLocation string
ExpectedNoProxyHeaders []string
ExpectedProxy bool
ExpectedProxyHeaders map[string]string
ExpectedCookiesValidator map[string]func(*testing.T, *Config, string) bool
BasicAuth bool
Cookies []*http.Cookie
Expires time.Duration
FormValues map[string]string
Groups []string
HasCookieToken bool
HasLogin bool
HasToken bool
Headers map[string]string
Method string
NotSigned bool
OnResponse func(int, *resty.Request, *resty.Response)
Password string
ProxyProtocol string
ProxyRequest bool
RawToken string
Redirects bool
Roles []string
SkipClientIDCheck bool
SkipIssuerCheck bool
TokenClaims map[string]interface{}
URI string
URL string
Username string
ExpectedCode int
ExpectedContent func(body string, testNum int)
ExpectedContentContains string
ExpectedCookies map[string]string
ExpectedHeaders map[string]string
ExpectedLocation string
ExpectedNoProxyHeaders []string
ExpectedProxy bool
ExpectedProxyHeaders map[string]string
ExpectedProxyHeadersValidator map[string]func(*testing.T, *Config, string)
ExpectedCookiesValidator map[string]func(*testing.T, *Config, string) bool
ExpectedLoginCookiesValidator map[string]func(*testing.T, *Config, string) bool
}

type fakeProxy struct {
Expand Down Expand Up @@ -116,6 +118,7 @@ func (f *fakeProxy) getServiceURL() string {
}

// RunTests performs a series of requests against a fake proxy service
// nolint:funlen
func (f *fakeProxy) RunTests(t *testing.T, requests []fakeRequest) {
defer func() {
f.idp.Close()
Expand Down Expand Up @@ -264,6 +267,17 @@ func (f *fakeProxy) RunTests(t *testing.T, requests []fakeRequest) {
}
}
}
if c.ExpectedProxyHeadersValidator != nil && len(c.ExpectedProxyHeadersValidator) > 0 {
for k, v := range c.ExpectedProxyHeadersValidator {
headers := upstream.Headers
switch v {
case nil:
assert.NotNil(t, v, "Validation function is nil, forgot to configure?")
default:
v(t, f.config, headers.Get(k))
}
}
}
if len(c.ExpectedNoProxyHeaders) > 0 {
for _, k := range c.ExpectedNoProxyHeaders {
assert.Empty(t, upstream.Headers.Get(k), "case %d, header: %s was not expected to exist", i, k)
Expand All @@ -288,13 +302,42 @@ func (f *fakeProxy) RunTests(t *testing.T, requests []fakeRequest) {
assert.Equal(t, cookie.Value, v, "case %d, expected cookie value: %s, got: %s", i, v, cookie.Value)
}
}
}
if len(c.ExpectedCookiesValidator) > 0 {
for k, v := range c.ExpectedCookiesValidator {
cookie := findCookie(k, resp.Cookies())

if !assert.NotNil(t, cookie, "case %d, expected cookie %s not found", i, k) {
continue
}

if v != nil {
assert.True(
t,
v(t, f.config, cookie.Value),
"case %d, invalid cookie value: %s in expected cookie validator",
i,
cookie.Value,
)
}
}
}
if len(c.ExpectedLoginCookiesValidator) > 0 {
for k, v := range c.ExpectedLoginCookiesValidator {
cookie, ok := f.cookies[k]

if !assert.True(t, ok, "case %d, expected cookie %s not found", i, k) {
continue
}

if v != nil {
assert.True(t, v(t, f.config, cookie.Value), "case %d, invalid cookie value: %s", i, cookie.Value)
assert.True(
t,
v(t, f.config, cookie.Value),
"case %d, invalid cookie value in login cookie validator: %s",
i,
cookie.Value,
)
}
}
}
Expand Down Expand Up @@ -1191,59 +1234,34 @@ func TestCrossSiteHandler(t *testing.T) {
}
}

func TestCheckRefreshTokens(t *testing.T) {
func TestRefreshTokenEncryption(t *testing.T) {
cfg := newFakeKeycloakConfig()
cfg.EnableRefreshTokens = true
cfg.EncryptionKey = testEncryptionKey
fn := func(no int, req *resty.Request, resp *resty.Response) {
if no == 0 {
<-time.After(1000 * time.Millisecond)
}
}
p := newFakeProxy(cfg, &fakeAuthConfig{})
p.idp.setTokenExpiration(1000 * time.Millisecond)

requests := []fakeRequest{
{
URI: fakeAuthAllURL,
HasLogin: true,
Redirects: true,
OnResponse: fn,
ExpectedProxy: true,
ExpectedCode: http.StatusOK,
URI: fakeAuthAllURL,
HasLogin: true,
Redirects: true,
OnResponse: delay,
ExpectedProxy: true,
ExpectedCode: http.StatusOK,
ExpectedLoginCookiesValidator: map[string]func(*testing.T, *Config, string) bool{cfg.CookieRefreshName: checkRefreshTokenEncryption},
},
{
URI: fakeAuthAllURL,
Redirects: false,
ExpectedProxy: true,
ExpectedCode: http.StatusOK,
ExpectedCookies: map[string]string{cfg.CookieAccessName: ""},
URI: fakeAuthAllURL,
Redirects: false,
ExpectedProxy: true,
ExpectedCode: http.StatusOK,
ExpectedCookiesValidator: map[string]func(*testing.T, *Config, string) bool{cfg.CookieRefreshName: checkRefreshTokenEncryption},
},
}
p.RunTests(t, requests)
}

func TestCheckEncryptedCookie(t *testing.T) {
cfg := newFakeKeycloakConfig()
cfg.EnableRefreshTokens = true
cfg.EnableEncryptedToken = true
cfg.Verbose = true
cfg.EnableLogging = true
cfg.EncryptionKey = testEncryptionKey
testEncryptedToken(t, cfg)
}

func TestCheckForcedEncryptedCookie(t *testing.T) {
cfg := newFakeKeycloakConfig()
cfg.EnableRefreshTokens = true
cfg.EnableEncryptedToken = false
cfg.ForceEncryptedCookie = true
cfg.Verbose = true
cfg.EnableLogging = true
cfg.EncryptionKey = testEncryptionKey
testEncryptedToken(t, cfg)
}

func delay(no int, req *resty.Request, resp *resty.Response) {
if no == 0 {
<-time.After(1000 * time.Millisecond)
Expand Down Expand Up @@ -1284,29 +1302,88 @@ func checkRefreshTokenEncryption(t *testing.T, cfg *Config, value string) bool {
return err == nil
}

func testEncryptedToken(t *testing.T, cfg *Config) {
p := newFakeProxy(cfg, &fakeAuthConfig{})
p.idp.setTokenExpiration(1000 * time.Millisecond)
func TestAccessTokenEncryption(t *testing.T) {
cfg := newFakeKeycloakConfig()

requests := []fakeRequest{
testCases := []struct {
Name string
ProxySettings func(c *Config)
ExecutionSettings []fakeRequest
}{
{
URI: fakeAuthAllURL,
HasLogin: true,
Redirects: true,
OnResponse: delay,
ExpectedProxy: true,
ExpectedCode: http.StatusOK,
Name: "TestEnableEncryptedToken",
ProxySettings: func(c *Config) {
c.EnableRefreshTokens = true
c.EnableEncryptedToken = true
c.Verbose = true
c.EnableLogging = true
c.EncryptionKey = testEncryptionKey
},
ExecutionSettings: []fakeRequest{
{
URI: fakeAuthAllURL,
HasLogin: true,
Redirects: true,
OnResponse: delay,
ExpectedProxy: true,
ExpectedCode: http.StatusOK,
ExpectedLoginCookiesValidator: map[string]func(*testing.T, *Config, string) bool{cfg.CookieAccessName: checkAccessTokenEncryption},
},
{
URI: fakeAuthAllURL,
Redirects: false,
ExpectedProxy: true,
ExpectedCode: http.StatusOK,
ExpectedCookies: map[string]string{cfg.CookieAccessName: ""},
ExpectedCookiesValidator: map[string]func(*testing.T, *Config, string) bool{cfg.CookieAccessName: checkAccessTokenEncryption},
},
},
},
{
URI: fakeAuthAllURL,
Redirects: false,
ExpectedProxy: true,
ExpectedCode: http.StatusOK,
ExpectedCookies: map[string]string{cfg.CookieAccessName: ""},
ExpectedCookiesValidator: map[string]func(*testing.T, *Config, string) bool{cfg.CookieAccessName: checkAccessTokenEncryption},
Name: "ForceEncryptedCookie",
ProxySettings: func(c *Config) {
c.EnableRefreshTokens = true
c.EnableEncryptedToken = false
c.ForceEncryptedCookie = true
c.Verbose = true
c.EnableLogging = true
c.EncryptionKey = testEncryptionKey
},
ExecutionSettings: []fakeRequest{
{
URI: fakeAuthAllURL,
HasLogin: true,
Redirects: true,
OnResponse: delay,
ExpectedProxy: true,
ExpectedCode: http.StatusOK,
ExpectedLoginCookiesValidator: map[string]func(*testing.T, *Config, string) bool{cfg.CookieAccessName: checkAccessTokenEncryption},
},
{
URI: fakeAuthAllURL,
Redirects: false,
ExpectedProxy: true,
ExpectedCode: http.StatusOK,
ExpectedCookies: map[string]string{cfg.CookieAccessName: ""},
ExpectedCookiesValidator: map[string]func(*testing.T, *Config, string) bool{cfg.CookieAccessName: checkAccessTokenEncryption},
},
},
},
}
p.RunTests(t, requests)

for _, testCase := range testCases {
testCase := testCase
c := cfg
t.Run(
testCase.Name,
func(t *testing.T) {
testCase.ProxySettings(c)
p := newFakeProxy(c, &fakeAuthConfig{})
p.idp.setTokenExpiration(1000 * time.Millisecond)
p.RunTests(t, testCase.ExecutionSettings)
},
)
}
}

func TestCustomHeadersHandler(t *testing.T) {
Expand Down
Loading

0 comments on commit 2319809

Please sign in to comment.