diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8c24b5ce13f629ea042976968111c963aec417c9..3c1f5b18c53689062cb79b822132ede8cc503e2a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -12,6 +12,7 @@ FEATURES
 * the order of the resources are no longer important, the framework will handle the routing
 * improved the overall spec of the proxy by removing URL inspection and prefix checking
 * removed the CORS implementation and using the default echo middles, which is more compliant
+* added the --enable-encrypted-token option to enable encrypting the access token:wq
 
 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 8c3ca1d273c5e2af7a254e82cb664a3244e6ce23..135bc9266489f3a6788a49ed55b83307d02520e3 100644
--- a/README.md
+++ b/README.md
@@ -25,7 +25,7 @@
 Keycloak-proxy is a proxy service which at the risk of stating the obvious integrates with the [Keycloak](https://github.com/keycloak/keycloak) authentication service. Although technically the service has no dependency on Keycloak itself and would quite happily work with any OpenID provider. The service supports both access tokens in browser cookie or bearer tokens.
 
 ```shell
-[jest@starfury keycloak-proxy]$ bin/keycloak-proxy --help
+[jest@starfury keycloak-proxy]$ bin/keycloak-proxy help
 NAME:
    keycloak-proxy - is a proxy using the keycloak service for auth and authorization
 
@@ -33,7 +33,7 @@ USAGE:
    keycloak-proxy [options]
 
 VERSION:
-   v2.1.0 (git+sha: f74c713)
+   v2.1.0 (git+sha: 960c2e5-dirty, built: 25/04/2017)
 
 AUTHOR:
    Rohith <gambol99@gmail.com>
@@ -55,6 +55,7 @@ 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-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)
@@ -230,13 +231,13 @@ Note the HTTP routing rules following the guidelines from [echo](https://echo.la
 
 Although the role extensions do require a Keycloak IDP or at the very least a IDP that produces a token which contains roles, there's nothing stopping you from using it against any OpenID providers, such as Google. Go to the Google Developers Console and create a new application *(via "Enable and Manage APIs -> Credentials)*. Once you've created the application, take the client id, secret and make sure you've added the callback url to the application scope *(using the default this would be http://127.0.0.1:3000/oauth/callback)*
 
-``` shell
+```shell
 bin/keycloak-proxy \
-    --discovery-url=https://accounts.google.com/.well-known/openid-configuration \
-    --client-id=<CLIENT_ID> \
-    --client-secret=<CLIENT_SECRET> \
-    --resources="uri=/*" \
-    --verbose=true
+  --discovery-url=https://accounts.google.com/.well-known/openid-configuration \
+  --client-id=<CLIENT_ID> \
+  --client-secret=<CLIENT_SECRET> \
+  --resources="uri=/*" \
+  --verbose=true
 ```
 
 Open a browser an go to http://127.0.0.1:3000 and you should be redirected to Google for authenticate and back the application when done and you should see something like the below.
@@ -259,7 +260,6 @@ Example setup:
 You have collection of micro-services which are permitted to speak to one another; you've already setup the credentials, roles, clients etc in Keycloak, providing granular role controls over issue tokens.
 
 ```YAML
-# kubernetes pod example
 - name: keycloak-proxy
   image: quay.io/gambol99/keycloak-proxy:latest
   args:
@@ -287,7 +287,7 @@ Receiver side you could setup the keycloak-proxy (--no=redirects=true) and permi
 
 #### **Forwarding Signing HTTPS Connect**
 
-Handling HTTPS requires man in the middling the TLS connection. By default if no -tls-ca-cert and -tls-ca-key is provided the proxy will use the default certificate. If you wish to verify the trust, you'll need to generate a CA, for example
+Handling HTTPS requires man in the middling the TLS connection. By default if no -tls-ca-cert and -tls-ca-key is provided the proxy will use the default certificate. If you wish to verify the trust, you'll need to generate a CA, for example.
 
 ```shell
 [jest@starfury keycloak-proxy]$ openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout ca.key -out ca.pem
@@ -312,6 +312,10 @@ The proxy supports http listener, though the only real requirement for this woul
 --enable-https-redirection
 ```
 
+#### **Access Token Encryption**
+
+By default the session token *(i.e. access/id token)* is placed into a cookie in plaintext. If prefer you to encrypt the session cookie using --enable-encrypted-token and --encryption-key options. Note, the access token forwarded in the X-Auth-Token header to upstream is unaffected.
+
 #### **Upstream Headers**
 
 On protected resources the upstream endpoint will receive a number of headers added by the proxy, along with an custom claims.
diff --git a/config.go b/config.go
index c3b02ccbed2710570aa166b1312ccaf3973d868c..da329a0fad94abb17a4b329d322cb152f7a05dac 100644
--- a/config.go
+++ b/config.go
@@ -120,8 +120,11 @@ func (r *Config) isValid() error {
 					return errors.New("the security filter must be switch on for this feature: hostnames")
 				}
 			}
+			if r.EnableEncryptedToken && r.EncryptionKey == "" {
+				return errors.New("you have not specified an encryption key for encoding the access token")
+			}
 			if r.EnableRefreshTokens && r.EncryptionKey == "" {
-				return errors.New("you have not specified a encryption key for encoding the session state")
+				return errors.New("you have not specified an encryption key for encoding the session state")
 			}
 			if r.EnableRefreshTokens && (len(r.EncryptionKey) != 16 && len(r.EncryptionKey) != 32) {
 				return fmt.Errorf("the encryption key (%d) must be either 16 or 32 characters for AES-128/AES-256 selection", len(r.EncryptionKey))
diff --git a/config_sample.yml b/config_sample.yml
index 5e9fe5a37036de9869769d02abb11bd3ddbb7d14..67ccfe6df0f3e3c1eb47576f584da554c5b6e68f 100644
--- a/config_sample.yml
+++ b/config_sample.yml
@@ -14,6 +14,8 @@ enable-refresh-tokens: true
 enable-logging: true
 # log in json format
 enable-json-logging: true
+# should the access token be encrypted - you need an encryption-key if 'true'
+enable-encrypted-token: false
 # do not redirec the request, simple 307 it
 no-redirects: false
 # the location of a certificate you wish the proxy to use for TLS support
@@ -55,22 +57,22 @@ add-claims:
 - name
 # a collection of resource i.e. urls that you wish to protect
 resources:
-  - uri: /admin/test
-    # the methods on this url that should be protected, if missing, we assuming all
-    methods:
-      - GET
-    # a list of roles the user must have in order to accces urls under the above
-    roles:
-      - openvpn:vpn-test
-  - uri: /admin/white_listed
-    # permits a url prefix through, bypassing the admission controls
-    white-listed: true
-  - uri: /admin/*
-    methods:
-      - GET
-    roles:
-      - openvpn:vpn-user
-      - openvpn:prod-vpn
+- uri: /admin/test
+  # the methods on this url that should be protected, if missing, we assuming all
+  methods:
+  - GET
+  # a list of roles the user must have in order to accces urls under the above
+  roles:
+    - openvpn:vpn-test
+- uri: /admin/white_listed
+  # permits a url prefix through, bypassing the admission controls
+  white-listed: true
+- uri: /admin/*
+  methods:
+  - GET
+  roles:
+    - openvpn:vpn-user
+    - openvpn:prod-vpn
 
 # an array of origins (Access-Control-Allow-Origin)
 cors-origins: []
diff --git a/doc.go b/doc.go
index ae6fc265ed8d1b60822d7ba80ab280e34154a412..a75b0390a5b4d1becfe8862e66aa0f4fdadf669b 100644
--- a/doc.go
+++ b/doc.go
@@ -76,6 +76,8 @@ var (
 	ErrRefreshTokenExpired = errors.New("the refresh token has expired")
 	// ErrNoTokenAudience indicates their is not audience in the token
 	ErrNoTokenAudience = errors.New("the token does not audience in claims")
+	// ErrDecryption indicates we can't decrypt the token
+	ErrDecryption = errors.New("failed to decrypt token")
 )
 
 // Resource represents a url resource to protect
@@ -119,6 +121,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"`
 
+	// 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
 	EnableLogging bool `json:"enable-logging" yaml:"enable-logging" usage:"enable http logging of the requests"`
 	// EnableJSONLogging is the logging format
@@ -189,12 +193,12 @@ type Config struct {
 	CorsHeaders []string `json:"cors-headers" yaml:"cors-headers" usage:"set of headers to add to the CORS access control (Access-Control-Allow-Headers)"`
 	// CorsExposedHeaders are the exposed header fields
 	CorsExposedHeaders []string `json:"cors-exposed-headers" yaml:"cors-exposed-headers" usage:"expose cors headers access control (Access-Control-Expose-Headers)"`
-	// CorsCredentials set the creds flag
+	// CorsCredentials set the credentials flag
 	CorsCredentials bool `json:"cors-credentials" yaml:"cors-credentials" usage:"credentials access control header (Access-Control-Allow-Credentials)"`
 	// CorsMaxAge is the age for CORS
 	CorsMaxAge time.Duration `json:"cors-max-age" yaml:"cors-max-age" usage:"max age applied to cors headers (Access-Control-Max-Age)"`
 
-	// Hostname is a list of hostname's the service should response to
+	// Hostnames is a list of hostname's the service should response to
 	Hostnames []string `json:"hostnames" yaml:"hostnames" usage:"list of hostnames the service will respond to"`
 
 	// Store is a url for a store resource, used to hold the refresh tokens
diff --git a/handlers.go b/handlers.go
index a976db4e691e17704fe29838fb45bb44aebaaded..1fce917c1084f90838ca1a88471cbd991631991b 100644
--- a/handlers.go
+++ b/handlers.go
@@ -137,79 +137,78 @@ func (r *oauthProxy) oauthAuthorizationHandler(cx echo.Context) error {
 
 // oauthCallbackHandler is responsible for handling the response from oauth service
 func (r *oauthProxy) oauthCallbackHandler(cx echo.Context) error {
-	// step: is token verification switched on?
 	if r.config.SkipTokenVerification {
 		return cx.NoContent(http.StatusNotAcceptable)
 	}
-	// step: ensure we have a authorization code to exchange
+	// step: ensure we have a authorization code
 	code := cx.QueryParam("code")
 	if code == "" {
 		return cx.NoContent(http.StatusBadRequest)
 	}
 
-	// step: create a oauth client
 	client, err := r.getOAuthClient(r.getRedirectionURL(cx))
 	if err != nil {
 		log.WithFields(log.Fields{"error": err.Error()}).Errorf("unable to create a oauth2 client")
-
 		return cx.NoContent(http.StatusInternalServerError)
 	}
 
-	// step: exchange the authorization for a access token
 	resp, err := exchangeAuthenticationCode(client, code)
 	if err != nil {
 		log.WithFields(log.Fields{"error": err.Error()}).Errorf("unable to exchange code for access token")
-
 		return r.accessForbidden(cx)
 	}
 
-	// step: parse decode the identity token
+	// Flow: once we exchange the authorization code we parse the ID Token; we then check for a access token,
+	// if a access token is present and we can decode it, we use that as the session token, otherwise we default
+	// to the ID Token.
 	token, identity, err := parseToken(resp.IDToken)
 	if err != nil {
 		log.WithFields(log.Fields{"error": err.Error()}).Errorf("unable to parse id token for identity")
-
 		return r.accessForbidden(cx)
 	}
+	access, id, err := parseToken(resp.AccessToken)
+	if err == nil {
+		token = access
+		identity = id
+	} else {
+		log.WithFields(log.Fields{"error": err.Error()}).Warn("unable to parse the access token, using id token only")
+	}
 
-	// step: verify the token is valid
+	// step: check the access token is valid
 	if err = verifyToken(r.client, token); err != nil {
 		log.WithFields(log.Fields{"error": err.Error()}).Errorf("unable to verify the id token")
-
 		return r.accessForbidden(cx)
 	}
+	accessToken := token.Encode()
 
-	// step: attempt to decode the access token else we default to the id token
-	access, id, err := parseToken(resp.AccessToken)
-	if err != nil {
-		log.WithFields(log.Fields{"error": err.Error()}).Errorf("unable to parse the access token, using id token only")
-	} else {
-		token = access
-		identity = id
+	// step: are we encrypting the access token?
+	if r.config.EnableEncryptedToken {
+		if accessToken, err = encodeText(accessToken, r.config.EncryptionKey); err != nil {
+			log.WithFields(log.Fields{"error": err.Error()}).Error("unable to encode the access token")
+			return cx.NoContent(http.StatusInternalServerError)
+		}
 	}
 
 	log.WithFields(log.Fields{
 		"email":    identity.Email,
 		"expires":  identity.ExpiresAt.Format(time.RFC3339),
 		"duration": time.Until(identity.ExpiresAt).String(),
-	}).Infof("issuing access token for user, email: %s", identity.Email)
+	}).Info("issuing access token for user")
 
 	// step: does the response has a refresh token and we are NOT ignore refresh tokens?
 	if r.config.EnableRefreshTokens && resp.RefreshToken != "" {
-		// step: encrypt the refresh token
-		encrypted, err := encodeText(resp.RefreshToken, r.config.EncryptionKey)
+		var encrypted string
+		encrypted, err = encodeText(resp.RefreshToken, r.config.EncryptionKey)
 		if err != nil {
 			log.WithFields(log.Fields{"error": err.Error()}).Errorf("failed to encrypt the refresh token")
-
 			return cx.NoContent(http.StatusInternalServerError)
 		}
-
 		// drop in the access token - cookie expiration = access token
-		r.dropAccessTokenCookie(cx.Request(), cx.Response().Writer, token.Encode(),
-			r.getAccessCookieExpiration(token, resp.RefreshToken))
+		r.dropAccessTokenCookie(cx.Request(), cx.Response().Writer, accessToken, r.getAccessCookieExpiration(token, resp.RefreshToken))
 
 		switch r.useStore() {
 		case true:
-			if err := r.StoreRefreshToken(token, encrypted); err != nil {
+			if err = r.StoreRefreshToken(token, encrypted); err != nil {
 				log.WithFields(log.Fields{"error": err.Error()}).Warnf("failed to save the refresh token in the store")
 			}
 		default:
@@ -222,7 +221,7 @@ func (r *oauthProxy) oauthCallbackHandler(cx echo.Context) error {
 			}
 		}
 	} else {
-		r.dropAccessTokenCookie(cx.Request(), cx.Response().Writer, token.Encode(), time.Until(identity.ExpiresAt))
+		r.dropAccessTokenCookie(cx.Request(), cx.Response().Writer, accessToken, time.Until(identity.ExpiresAt))
 	}
 
 	// step: decode the state variable
@@ -245,19 +244,15 @@ func (r *oauthProxy) oauthCallbackHandler(cx echo.Context) error {
 // loginHandler provide's a generic endpoint for clients to perform a user_credentials login to the provider
 func (r *oauthProxy) loginHandler(cx echo.Context) error {
 	errorMsg, code, err := func() (string, int, error) {
-		// step: check if the handler is disable
 		if !r.config.EnableLoginHandler {
 			return "attempt to login when login handler is disabled", http.StatusNotImplemented, errors.New("login handler disabled")
 		}
-
-		// step: parse the client credentials
 		username := cx.Request().PostFormValue("username")
 		password := cx.Request().PostFormValue("password")
 		if username == "" || password == "" {
 			return "request does not have both username and password", http.StatusBadRequest, errors.New("no credentials")
 		}
 
-		// step: get the client
 		client, err := r.client.OAuthClient()
 		if err != nil {
 			return "unable to create the oauth client for user_credentials request", http.StatusInternalServerError, err
@@ -271,7 +266,6 @@ func (r *oauthProxy) loginHandler(cx echo.Context) error {
 			return "unable to request the access token via grant_type 'password'", http.StatusInternalServerError, err
 		}
 
-		// step: parse the token
 		_, identity, err := parseToken(token.AccessToken)
 		if err != nil {
 			return "unable to decode the access token", http.StatusNotImplemented, err
@@ -306,12 +300,10 @@ func emptyHandler(cx echo.Context) error {
 	return nil
 }
 
-//
 // logoutHandler performs a logout
 //  - if it's just a access token, the cookie is deleted
 //  - if the user has a refresh token, the token is invalidated by the provider
 //  - optionally, the user can be redirected by to a url
-//
 func (r *oauthProxy) logoutHandler(cx echo.Context) error {
 	// the user can specify a url to redirect the back
 	redirectURL := cx.QueryParam("redirect")
@@ -321,7 +313,6 @@ func (r *oauthProxy) logoutHandler(cx echo.Context) error {
 	if err != nil {
 		return cx.NoContent(http.StatusBadRequest)
 	}
-
 	// step: can either use the id token or the refresh token
 	identityToken := user.token.Encode()
 	if refresh, err := r.retrieveRefreshToken(cx.Request(), user); err == nil {
@@ -340,15 +331,12 @@ func (r *oauthProxy) logoutHandler(cx echo.Context) error {
 		}()
 	}
 
-	// step: get the revocation endpoint from either the idp and or the user config
 	revocationURL := defaultTo(r.config.RevocationEndpoint, r.idp.EndSessionEndpoint.String())
-
 	// step: do we have a revocation endpoint?
 	if revocationURL != "" {
 		client, err := r.client.OAuthClient()
 		if err != nil {
 			log.WithFields(log.Fields{"error": err.Error()}).Errorf("unable to retrieve the openid client")
-
 			return cx.NoContent(http.StatusInternalServerError)
 		}
 
@@ -364,19 +352,17 @@ func (r *oauthProxy) logoutHandler(cx echo.Context) error {
 			log.WithFields(log.Fields{"error": err.Error()}).Errorf("unable to construct the revocation request")
 			return cx.NoContent(http.StatusInternalServerError)
 		}
-
 		// step: add the authentication headers and content-type
 		request.SetBasicAuth(encodedID, encodedSecret)
 		request.Header.Set("Content-Type", "application/x-www-form-urlencoded")
 
-		// step: attempt to make the
 		response, err := client.HttpClient().Do(request)
 		if err != nil {
 			log.WithFields(log.Fields{"error": err.Error()}).Errorf("unable to post to revocation endpoint")
 			return nil
 		}
 
-		// step: add a log for debugging
+		// step: check the response
 		switch response.StatusCode {
 		case http.StatusNoContent:
 			log.WithFields(log.Fields{
@@ -390,7 +376,6 @@ func (r *oauthProxy) logoutHandler(cx echo.Context) error {
 			}).Errorf("invalid response from revocation endpoint")
 		}
 	}
-
 	// step: should we redirect the user
 	if redirectURL != "" {
 		return r.redirectToURL(redirectURL, cx)
@@ -426,7 +411,6 @@ func (r *oauthProxy) tokenHandler(cx echo.Context) error {
 // healthHandler is a health check handler for the service
 func (r *oauthProxy) healthHandler(cx echo.Context) error {
 	cx.Response().Writer.Header().Set(versionHeader, getVersion())
-
 	return cx.String(http.StatusOK, "OK\n")
 }
 
diff --git a/middleware.go b/middleware.go
index 282fdb8c63edfbf5273b454d547564c987be7089..2e5d6d58512f8b3c174d46944ff8435a46650131 100644
--- a/middleware.go
+++ b/middleware.go
@@ -97,8 +97,6 @@ func (r *oauthProxy) metricsMiddleware() echo.MiddlewareFunc {
 		},
 		[]string{"code", "method"},
 	)
-
-	// step: register the metric with prometheus
 	prometheus.MustRegisterOrGet(statusMetrics)
 
 	return func(next echo.HandlerFunc) echo.HandlerFunc {
@@ -118,26 +116,20 @@ func (r *oauthProxy) authenticationMiddleware(resource *Resource) echo.Middlewar
 			// step: grab the user identity from the request
 			user, err := r.getIdentity(cx.Request())
 			if err != nil {
-				log.WithFields(log.Fields{
-					"error": err.Error(),
-				}).Errorf("no session found in request, redirecting for authorization")
-
+				log.WithFields(log.Fields{"error": err.Error()}).Errorf("no session found in request, redirecting for authorization")
 				return r.redirectToAuthorization(cx)
 			}
-			// step: inject the user into the context
 			cx.Set(userContextName, user)
 
 			// step: skip if we are running skip-token-verification
 			if r.config.SkipTokenVerification {
 				log.Warnf("skip token verification enabled, skipping verification - TESTING ONLY")
-
 				if user.isExpired() {
 					log.WithFields(log.Fields{
 						"client_ip":  clientIP,
 						"username":   user.name,
 						"expired_on": user.expiresAt.String(),
 					}).Errorf("the session has expired and verification switch off")
-
 					return r.redirectToAuthorization(cx)
 				}
 			} else {
@@ -150,7 +142,6 @@ func (r *oauthProxy) authenticationMiddleware(resource *Resource) echo.Middlewar
 							"client_ip": clientIP,
 							"error":     err.Error(),
 						}).Errorf("access token failed verification")
-
 						return r.accessForbidden(cx)
 					}
 
@@ -161,7 +152,6 @@ func (r *oauthProxy) authenticationMiddleware(resource *Resource) echo.Middlewar
 							"email":      user.name,
 							"expired_on": user.expiresAt.String(),
 						}).Errorf("session expired and access token refreshing is disabled")
-
 						return r.redirectToAuthorization(cx)
 					}
 
@@ -178,7 +168,6 @@ func (r *oauthProxy) authenticationMiddleware(resource *Resource) echo.Middlewar
 							"email":     user.email,
 							"error":     err.Error(),
 						}).Errorf("unable to find a refresh token for user")
-
 						return r.redirectToAuthorization(cx)
 					}
 
@@ -196,7 +185,6 @@ func (r *oauthProxy) authenticationMiddleware(resource *Resource) echo.Middlewar
 						default:
 							log.WithFields(log.Fields{"error": err.Error()}).Errorf("failed to refresh the access token")
 						}
-
 						return r.redirectToAuthorization(cx)
 					}
 					// get the expiration of the new access token
@@ -223,9 +211,8 @@ func (r *oauthProxy) authenticationMiddleware(resource *Resource) echo.Middlewar
 							}
 						}(user.token, token, refresh)
 					}
-					// step: update the with the new access token
+					// update the with the new access token and inject into the context
 					user.token = token
-					// step: inject the user into the context
 					cx.Set(userContextName, user)
 				}
 			}
@@ -248,18 +235,6 @@ func (r *oauthProxy) admissionMiddleware(resource *Resource) echo.MiddlewareFunc
 			}
 			user := cx.Get(userContextName).(*userContext)
 
-			// step: check the audience for the token is us
-			if r.config.ClientID != "" && !user.isAudience(r.config.ClientID) {
-				log.WithFields(log.Fields{
-					"client_id":  r.config.ClientID,
-					"email":      user.email,
-					"expired_on": user.expiresAt.String(),
-					"issuer":     user.audience,
-				}).Warnf("access token audience is not us, redirecting back for authentication")
-
-				return r.accessForbidden(cx)
-			}
-
 			// step: we need to check the roles
 			if roles := len(resource.Roles); roles > 0 {
 				if !hasRoles(resource.Roles, user.roles) {
@@ -336,8 +311,6 @@ func (r *oauthProxy) headersMiddleware(custom []string) echo.MiddlewareFunc {
 
 	return func(next echo.HandlerFunc) echo.HandlerFunc {
 		return func(cx echo.Context) error {
-
-			// step: retrieve the user context if any
 			if user := cx.Get(userContextName); user != nil {
 				id := user.(*userContext)
 				cx.Request().Header.Set("X-Auth-Email", id.email)
@@ -352,7 +325,6 @@ func (r *oauthProxy) headersMiddleware(custom []string) echo.MiddlewareFunc {
 				if r.config.EnableAuthorizationHeader {
 					cx.Request().Header.Set("Authorization", fmt.Sprintf("Bearer %s", id.token.Encode()))
 				}
-
 				// step: inject any custom claims
 				for claim, header := range customClaims {
 					if claim, found := id.claims[claim]; found {
diff --git a/middleware_test.go b/middleware_test.go
index 5cc7ce24856a4ec2acd118873c778b053fab4be7..1efb527b0eb87677042323e58cd94966761c4ed6 100644
--- a/middleware_test.go
+++ b/middleware_test.go
@@ -203,7 +203,7 @@ func (f *fakeProxy) RunTests(t *testing.T, requests []fakeRequest) {
 		}
 		status := resp.StatusCode()
 		if c.ExpectedCode != 0 {
-			assert.Equal(t, c.ExpectedCode, status, "case %d, expected: %d, got: %d", i, c.URI, c.ExpectedCode, status)
+			assert.Equal(t, c.ExpectedCode, status, "case %d, expected status code: %d, got: %d", i, c.ExpectedCode, status)
 		}
 		if c.ExpectedLocation != "" {
 			l := resp.Header().Get("Location")
@@ -376,12 +376,11 @@ func TestStrangeAdminRequests(t *testing.T) {
 			ExpectedProxy: true,
 			ExpectedCode:  http.StatusOK,
 		},
-		{ // check for it works
-			URI:           "//admin//test",
-			HasToken:      true,
-			Roles:         []string{fakeAdminRole},
-			ExpectedProxy: true,
-			ExpectedCode:  http.StatusOK,
+		{ // check for is doens't work
+			URI:          "//admin//test",
+			HasToken:     true,
+			Roles:        []string{"bad"},
+			ExpectedCode: http.StatusForbidden,
 		},
 		{
 			URI:          "/help/../admin/test/21",
diff --git a/oauth.go b/oauth.go
index a9f390653871dab5aa545a22dbeae87add0fab47..018ee96890ee127c5a644154ce3d2c5b67f156be 100644
--- a/oauth.go
+++ b/oauth.go
@@ -89,9 +89,8 @@ func getUserinfo(client *oauth2.Client, endpoint string, token string) (jose.Cla
 	if err != nil {
 		return nil, err
 	}
-	req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", token))
+	req.Header.Set(authorizationHeader, fmt.Sprintf("Bearer %s", token))
 
-	// step: make the request
 	resp, err := client.HttpClient().Do(req)
 	if err != nil {
 		return nil, err
diff --git a/server.go b/server.go
index 1a7ad3a3d3e65dd9252412b6568876c4f3a9bf14..8666596cd09b1e64c1598822538712eb96bc17bc 100644
--- a/server.go
+++ b/server.go
@@ -182,7 +182,7 @@ func (r *oauthProxy) createReverseProxy() error {
 	// step: provision in the protected resources
 	for _, x := range r.config.Resources {
 		if x.URL[len(x.URL)-1:] == "/" {
-			log.Warnf("the resource url: %s is not a prefix, you probably want %s* or %s* to protect the xs", x.URL, x.URL, strings.TrimRight(x.URL, "/"))
+			log.Warnf("the resource url: %s is not a prefix, you probably want %s* or %s* to protect the resource", x.URL, x.URL, strings.TrimRight(x.URL, "/"))
 		}
 	}
 	for _, x := range r.config.Resources {
@@ -200,6 +200,10 @@ func (r *oauthProxy) createReverseProxy() error {
 	if r.config.RedirectionURL == "" {
 		log.Warnf("no redirection url has been set, will use host headers")
 	}
+	if r.config.EnableEncryptedToken {
+		log.Info("session access tokens will be encrypted")
+	}
+
 	engine.Use(r.proxyMiddleware())
 
 	return nil
diff --git a/server_test.go b/server_test.go
index 8ded623b606df00e447ec2348ed05d37121a2511..3106ddb6926c19024734aee9d66981a4393eb682 100644
--- a/server_test.go
+++ b/server_test.go
@@ -89,7 +89,7 @@ func TestReverseProxyHeaders(t *testing.T) {
 	signed, _ := p.idp.signToken(token.claims)
 	requests := []fakeRequest{
 		{
-			URI:           fakeAuthAllURL,
+			URI:           "/auth_all/test",
 			RawToken:      signed.Encode(),
 			ExpectedProxy: true,
 			ExpectedProxyHeaders: map[string]string{
@@ -198,6 +198,34 @@ func TestProxyProtocol(t *testing.T) {
 	newFakeProxy(c).RunTests(t, requests)
 }
 
+func TestTokenEncryption(t *testing.T) {
+	c := newFakeKeycloakConfig()
+	c.EnableEncryptedToken = true
+	c.EncryptionKey = "US36S5kubc4BXbfzCIKTQcTzG6lvixVv"
+	requests := []fakeRequest{
+		{
+			URI:           "/auth_all/test",
+			HasLogin:      true,
+			ExpectedProxy: true,
+			Redirects:     true,
+			ExpectedProxyHeaders: map[string]string{
+				"X-Auth-Email":    "gambol99@gmail.com",
+				"X-Auth-Userid":   "rjayawardene",
+				"X-Auth-Username": "rjayawardene",
+				"X-Forwarded-For": "127.0.0.1",
+			},
+			ExpectedCode: http.StatusOK,
+		},
+		// the token must be encrypted
+		{
+			URI:          "/auth_all/test",
+			HasToken:     true,
+			ExpectedCode: http.StatusUnauthorized,
+		},
+	}
+	newFakeProxy(c).RunTests(t, requests)
+}
+
 func newTestService() string {
 	_, _, u := newTestProxyService(nil)
 	return u
@@ -255,7 +283,6 @@ func newFakeKeycloakConfig() *Config {
 		Listen:            "127.0.0.1:0",
 		EnableAuthorizationHeader: true,
 		EnableLoginHandler:        true,
-		EncryptionKey:             "AgXa7xRcoClDEU0ZDSH4X0XhL5Qy2Z2j",
 		Scopes:                    []string{},
 		Resources: []*Resource{
 			{
diff --git a/session.go b/session.go
index b7e42d298200db15db43acb107f63ca90bfc6719..312a360fac2686d9b08dd59c49d5a8a1099108f5 100644
--- a/session.go
+++ b/session.go
@@ -31,6 +31,11 @@ func (r *oauthProxy) getIdentity(req *http.Request) (*userContext, error) {
 	if err != nil {
 		return nil, err
 	}
+	if r.config.EnableEncryptedToken {
+		if access, err = decodeText(access, r.config.EncryptionKey); err != nil {
+			return nil, ErrDecryption
+		}
+	}
 	token, err := jose.ParseJWT(access)
 	if err != nil {
 		return nil, err
diff --git a/session_test.go b/session_test.go
index d684336730dd16370edb6c6c2f6e411e52b96db5..841b94f7a67c9a7040c9852761d20642fe571136 100644
--- a/session_test.go
+++ b/session_test.go
@@ -45,11 +45,6 @@ func TestGetIndentity(t *testing.T) {
 				Header: http.Header{},
 			},
 		},
-		{
-			Request: &http.Request{
-				Header: http.Header{},
-			},
-		},
 	}
 
 	for i, c := range testCases {
diff --git a/utils.go b/utils.go
index 11f92dd5b44627c2f61d4fe2e7eaebfe0b5d6502..350a78b9c46d89fdfa68255fb111d0e6079e9f0f 100644
--- a/utils.go
+++ b/utils.go
@@ -67,7 +67,6 @@ var (
 
 // readConfigFile reads and parses the configuration file
 func readConfigFile(filename string, config *Config) error {
-	// step: read in the contents of the file
 	content, err := ioutil.ReadFile(filename)
 	if err != nil {
 		return err