diff --git a/Makefile b/Makefile index 03b1dbfb0f4c8d7e4d0c81521c8e00c648d725f1..2cf36b792aa1a38b956faed3285b38d5a2798c52 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,6 @@ NAME=keycloak-proxy +AUTHOR=gambol99 HARDWARE=$(shell uname -m) VERSION=$(shell awk '/Version =/ { print $$3 }' doc.go | sed 's/"//g') DEPS=$(shell go list -f '{{range .TestImports}}{{.}} {{end}}' ./...) @@ -20,6 +21,10 @@ static: mkdir -p bin CGO_ENABLED=0 GOOS=linux godep go build -a -tags netgo -ldflags '-w' -o bin/${NAME} +docker: static + @echo "--> Building the docker image" + sudo docker build -t docker.io/${AUTHOR}/${NAME}:${VERSION} . + release: static mkdir -p release gzip -c bin/${NAME} > release/${NAME}_${VERSION}_linux_${HARDWARE}.gz diff --git a/handlers.go b/handlers.go index ac712c6e40b0b5c67be2cd9fa4966bc4cd832171..99847e591e13fd33f4891fdbf9133db552528800 100644 --- a/handlers.go +++ b/handlers.go @@ -17,9 +17,8 @@ package main import ( "net/http" - "net/http/httputil" - "time" "strings" + "time" "github.com/gin-gonic/gin" "github.com/golang/glog" @@ -33,6 +32,7 @@ import ( // c) proxyHandler is responsible for handling the reverse proxy to the upstream endpoint // +/* // loggingHandler is logging middleware func (r *KeycloakProxy) loggingHandler() gin.HandlerFunc { return func(cx *gin.Context) { @@ -42,6 +42,7 @@ func (r *KeycloakProxy) loggingHandler() gin.HandlerFunc { } } } +*/ // authenticationHandler is responsible for verifying the access token func (r *KeycloakProxy) authenticationHandler(cx *gin.Context) { @@ -152,7 +153,7 @@ func (r *KeycloakProxy) proxyHandler(cx *gin.Context) { // step: add the default headers cx.Request.Header.Set("X-Forwarded-For", cx.Request.RemoteAddr) - + // step: is this connection upgrading? if isUpgradedConnection(cx.Request) { glog.V(10).Infof("upgrading the connnection to %s", cx.Request.Header.Get(headerUpgrade)) diff --git a/oauth.go b/oauth.go index 6307bd3ac81337d3e6edc11b90ad3751d5d49117..6bc8fe3872c8b5b370d60d9ccad6f2581a2d0e8f 100644 --- a/oauth.go +++ b/oauth.go @@ -112,19 +112,19 @@ func (r *KeycloakProxy) callbackHandler(cx *gin.Context) { return } - glog.Infof("retrieved the refresh token for user: %s, expires at: %s", identity, ident.ExpiresAt) + glog.Infof("retrieved the refresh token for user: %s, expires at: %s", identity.Email, ident.ExpiresAt) // step: create the state session state := &SessionState{ refreshToken: response.RefreshToken, } - max_session := time.Now().Add(r.config.MaxSessionDuration) - switch max_session.After(ident.ExpiresAt) { + maxSession := time.Now().Add(r.config.MaxSessionDuration) + switch maxSession.After(ident.ExpiresAt) { case true: state.expireOn = ident.ExpiresAt default: - state.expireOn = max_session + state.expireOn = maxSession } if err := r.createSessionState(state, cx); err != nil { @@ -154,7 +154,6 @@ func (r *KeycloakProxy) refreshAccessToken(refreshToken string) (jose.JWT, time. return jose.JWT{}, time.Time{}, err } - return token, identity.ExpiresAt, nil } diff --git a/server.go b/server.go index 99c6f83c2c7ec34a608d98a5ea763d507b0f62bb..ff56ff6e729ea7a4e6aa982955fe373a9bc2ee37 100644 --- a/server.go +++ b/server.go @@ -58,8 +58,6 @@ func NewProxy(cfg *Config) (*KeycloakProxy, error) { glog.V(3).Infof("initializing the http router, listening: %s", cfg.Listen) service.router = gin.Default() - service.router.Use(service.loggingHandler()) - for _, resource := range cfg.Resources { glog.Infof("protecting resource: %s", resource) for _, method := range resource.Methods { @@ -97,7 +95,7 @@ func (r *KeycloakProxy) Run() error { // redirectToURL redirects the user and aborts the context func (r KeycloakProxy) redirectToURL(url string, cx *gin.Context) { - glog.V(10).Infof("redirecting the client to: %s", url) + glog.Infof("redirecting the client to: %s", url) cx.Redirect(http.StatusTemporaryRedirect, url) cx.Abort() } diff --git a/session.go b/session.go index b82a256fbc309cf200be2796434eb1e1e9a7a4be..80b5d42c0d022ef2928b20bf4d03e5f4af70000b 100644 --- a/session.go +++ b/session.go @@ -58,7 +58,7 @@ func (r *KeycloakProxy) refreshUserSessionToken(cx *gin.Context) (jose.JWT, erro } // step: inject the refreshed access token - glog.V(10).Infof("injecting the refreshed access token into seesion, expires on: %s", expires) + glog.Infof("injecting the refreshed access token into seesion, expires on: %s", expires) // step: create the session if err := r.createSession(token, expires, cx); err != nil { @@ -144,7 +144,7 @@ func (r *KeycloakProxy) getUserContext(token jose.JWT) (*UserContext, error) { // createSession creates a session cookie with the access token func (r *KeycloakProxy) createSession(token jose.JWT, expires time.Time, cx *gin.Context) error { - glog.V(10).Infof("creating a user session cookie, expires on: %s, token: %s", expires, token) + glog.V(10).Infof("creating a user session cookie, expires on: %s, token: %s", expires, token.Encode()) http.SetCookie(cx.Writer, createSessionCookie(token.Encode(), cx.Request.Host, expires)) return nil @@ -220,7 +220,7 @@ func createSessionCookie(token, hostname string, expires time.Time) *http.Cookie Expires: expires, HttpOnly: true, // Secure: true, - Value: token, + Value: token, } } @@ -244,4 +244,4 @@ func clearSessionState(cx *gin.Context) { // clearSession clears the session cookie func clearSession(cx *gin.Context) { http.SetCookie(cx.Writer, createSessionCookie("", cx.Request.Host, time.Now())) -} \ No newline at end of file +} diff --git a/session_test.go b/session_test.go index d087cb87a8f5c1cfc99ffae674f7098462e6438b..696b8db49b4b3f67bff43c72cdce266fe0a29e04 100644 --- a/session_test.go +++ b/session_test.go @@ -14,3 +14,52 @@ limitations under the License. */ package main + +import ( + "testing" + "time" + + "github.com/stretchr/testify/assert" +) + +func TestGetUserContext(t *testing.T) { + +} + +func TestEncodeState(t *testing.T) { + proxy := newFakeKeycloakProxy(t) + + state := &SessionState{ + refreshToken: "this is a fake session", + expireOn: time.Now(), + } + + session, err := proxy.encodeState(state) + assert.NotEmpty(t, session) + assert.NoError(t, err) +} + +func TestDecodeState(t *testing.T) { + proxy := newFakeKeycloakProxy(t) + + fakeToken := "this is a fake session" + fakeExpiresOn := time.Now() + + state := &SessionState{ + refreshToken: fakeToken, + expireOn: fakeExpiresOn, + } + + session, err := proxy.encodeState(state) + assert.NotEmpty(t, session) + if err != nil { + t.Errorf("the encodeState() should not have handed an error") + t.FailNow() + } + + decoded, err := proxy.decodeState(session) + assert.NotNil(t, decoded, "the session should not have been nil") + if assert.NoError(t, err, "the decodeState() should not have thrown an error") { + assert.Equal(t, fakeToken, decoded.refreshToken, "the token should been the same") + } +} diff --git a/util_test.go b/util_test.go index f74a22f8a29882f4486a9efd593d5921b1d51e60..07b2f7d04e10436e18859ef424ce302fdb2c1207 100644 --- a/util_test.go +++ b/util_test.go @@ -26,10 +26,6 @@ import ( "github.com/stretchr/testify/assert" ) -func TestIsValidMethod(t *testing.T) { - -} - func TestEncryptDataBlock(t *testing.T) { testCase := []struct { Text string