Skip to content
This repository has been archived by the owner on Dec 7, 2020. It is now read-only.

Commit

Permalink
Echo Router
Browse files Browse the repository at this point in the history
- shifting over to the echo rather than gin web framework
- adding the extra dependencies
- dropped the cors middleware and using the default middles from echo router
- completely removing gin tonic
- adding the Renderer implementation
- loading the templates for the custom pages
- hooking in the drop for the proxy middleware
- updating the readme to reflect the changes
- updating the CHANGELOG to reflect the changes
- updating the authors file
- adding the extra test for api errors and drop refresh cookie
- updated the golang version to v1.8
  • Loading branch information
gambol99 committed Mar 14, 2017
1 parent 0baa898 commit 61b9130
Show file tree
Hide file tree
Showing 181 changed files with 11,265 additions and 13,965 deletions.
1 change: 0 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ services:
- docker
language: go
go:
- 1.7
- 1.8
install:
- go get github.com/tools/godep
Expand Down
1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
Allan Degnan <allan@adegnan.net>
Ben Marvell <madmarv187@gmail.com>
Chris Nesbitt-Smith <chris@cns.me.uk>
Jiten Bhagat <jits@users.noreply.github.com>
johanneslanger <jo.langer@gmail.com>
Rémi Vion <vion.remi@gmail.com>
Rohith <gambol99@gmail.com>
Expand Down
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
#### **3.0.0**

FEATURES
- changed the routing engine from gin to echo
- removed the need for ordered resource
- improved the overall spec of the proxy by removing url inspection and prefix checking
- removed the cors implementating and using the default echo middles, which is more compliant

BREAKING CHANGES:
- the proxy no longer uses prefixes for resources, if you wish to use wildcard urls you need to specify it, i.e. --resource=/ becomes --resource=/* or =admin/ becomes =admin/*

#### **2.0.4**

Expand Down
94 changes: 55 additions & 39 deletions Godeps/Godeps.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ NAME=keycloak-proxy
AUTHOR=gambol99
AUTHOR_EMAIL=gambol99@gmail.com
REGISTRY=quay.io
GOVERSION ?= 1.7.3
GOVERSION ?= 1.8.0
SUDO=
ROOT_DIR=${PWD}
HARDWARE=$(shell uname -m)
Expand Down
35 changes: 23 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,15 @@
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

USAGE:
keycloak-proxy [options]

VERSION:
v2.0.2 (git+sha: 260d2c8-dirty)
v3.0.0 (git+sha: e9482f7-dirty)

AUTHOR:
Rohith <gambol99@gmail.com>
Expand All @@ -47,7 +47,7 @@ GLOBAL OPTIONS:
--discovery-url value discovery url to retrieve the openid configuration [$PROXY_DISCOVERY_URL]
--client-id value client id used to authenticate to the oauth service [$PROXY_CLIENT_ID]
--client-secret value client secret used to authenticate to the oauth service [$PROXY_CLIENT_SECRET]
--redirection-url value redirection url for the oauth callback url [$PROXY_REDIRECTION_URL]
--redirection-url value redirection url for the oauth callback url, defaults to host header is absent [$PROXY_REDIRECTION_URL]
--revocation-url value url for the revocation endpoint to revoke refresh token [$PROXY_REVOCATION_URL]
--skip-openid-provider-tls-verify skip the verification of any TLS communication with the openid provider (default: false)
--scopes value list of scopes requested when authenticating the user
Expand All @@ -68,6 +68,7 @@ GLOBAL OPTIONS:
--filter-frame-deny enable to the frame deny header (default: false)
--content-security-policy value specify the content security policy
--localhost-metrics enforces the metrics page can only been requested from 127.0.0.1 (default: false)
--access-token-duration value fallback cookie duration for the access token when using refresh tokens (default: 720h0m0s)
--cookie-domain value domain the access cookie is available to, defaults host header
--cookie-access-name value name of the cookie use to hold the access token (default: "kc-access")
--cookie-refresh-name value name of the cookie used to hold the encrypted refresh token (default: "kc-state")
Expand All @@ -89,7 +90,7 @@ GLOBAL OPTIONS:
--cors-max-age value max age applied to cors headers (Access-Control-Max-Age) (default: 0s)
--hostnames value list of hostnames the service will respond to
--store-url value url for the storage subsystem, e.g redis://127.0.0.1:6379, file:///etc/tokens.file
--encryption-key value encryption key used to encrpytion the session state
--encryption-key value encryption key used to encryption the session state [$PROXY_ENCRYPTION_KEY]
--log-requests enable http logging of the requests (default: false)
--json-format switch on json logging rather than text (default: false)
--no-redirects do not have back redirects when no authentication is present, 401 them (default: false)
Expand Down Expand Up @@ -154,7 +155,7 @@ resources:
- openvpn:vpn-user
- openvpn:prod-vpn
- test
- uri: /admin
- uri: /admin/*
methods:
- GET
roles:
Expand Down Expand Up @@ -184,13 +185,13 @@ redirection-url: http://127.0.0.1:3000
encryption_key: AgXa7xRcoClDEU0ZDSH4X0XhL5Qy2Z2j
upstream-url: http://127.0.0.1:80
resources:
- uri: /admin
- uri: /admin*
methods:
- GET
roles:
- client:test1
- client:test2
- uri: /backend
- uri: /backend*
roles:
- client:test1
```
Expand All @@ -207,10 +208,20 @@ bin/keycloak-proxy \
--enable-refresh-token=true \
--encryption-key=AgXa7xRcoClDEU0ZDSH4X0XhL5Qy2Z2j \
--upstream-url=http://127.0.0.1:80 \
--resources="uri=/admin|methods=GET|roles=test1,test2" \
--resources="uri=/backend|roles=test1"
--resources="uri=/admin*|methods=GET|roles=test1,test2" \
--resources="uri=/backend*|roles=test1"
```
#### **HTTP Routing**
By default all requests will be proxyed on to the upstream, if you wish to ensure all requests are authentication you can use
```shell
--resource=uri=/*
```
Note the HTTP routing rules following the guidelines from [echo](https://echo.labstack.com/guide/routing). Its also worth nothing the ordering of the resource do not matter, the router will handle that for you.
#### **Google OAuth**
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)*
Expand All @@ -219,7 +230,7 @@ bin/keycloak-proxy \
--discovery-url=https://accounts.google.com/.well-known/openid-configuration \
--client-id=<CLIENT_ID> \
--client-secret=<CLIENT_SECRET> \
--resources="uri=/" \
--resources="uri=/*" \
--verbose=true
```
Expand Down Expand Up @@ -399,7 +410,7 @@ By default the proxy will immediately redirect you for authentication and hand b
#### **White-listed URL's**
Depending on how the application url's are laid out, you might want protect the root / url but have exceptions on a list of paths, i.e. /health etc. Although you should probably fix this by fixing up the paths, you can add excepts to the protected resources. (Note: it's an array, so the order is important)
Depending on how the application url's are laid out, you might want protect the root / url but have exceptions on a list of paths, i.e. /health etc. Although you should probably fix this by fixing up the paths, you can add excepts to the protected resources.
```YAML
resources:
Expand Down Expand Up @@ -441,7 +452,7 @@ A /oauth/logout?redirect=url is provided as a helper to logout the users. Aside
#### **Cross Origin Resource Sharing (CORS)**
You can add CORS header via the --cors-[method] command line or configuration options. By default this will inject CORS header into all response from the /oauth/* and any authentication required redirects, though you can enable these globally for all responses via the --enable-cors-global option.
You can add CORS header via the --cors-[method] command line or configuration options.
* Access-Control-Allow-Origin
* Access-Control-Allow-Methods
Expand Down
5 changes: 2 additions & 3 deletions config_sample.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,11 @@ resources:
- GET
# a list of roles the user must have in order to accces urls under the above
roles:
- openvpn:vpn-user
- openvpn:prod-vpn
- openvpn:vpn-test
- uri: /admin/white_listed
# permits a url prefix through, bypassing the admission controls
white-listed: true
- uri: /admin
- uri: /admin/*
methods:
- GET
roles:
Expand Down
30 changes: 14 additions & 16 deletions cookies.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,12 @@ import (
"net/http"
"strings"
"time"

"github.com/gin-gonic/gin"
)

// dropCookie drops a cookie into the response
func (r *oauthProxy) dropCookie(cx *gin.Context, name, value string, duration time.Duration) {
func (r *oauthProxy) dropCookie(w http.ResponseWriter, host, name, value string, duration time.Duration) {
// step: default to the host header, else the config domain
domain := strings.Split(cx.Request.Host, ":")[0]
domain := strings.Split(host, ":")[0]
if r.config.CookieDomain != "" {
domain = r.config.CookieDomain
}
Expand All @@ -42,31 +40,31 @@ func (r *oauthProxy) dropCookie(cx *gin.Context, name, value string, duration ti
cookie.Expires = time.Now().Add(duration)
}

http.SetCookie(cx.Writer, cookie)
http.SetCookie(w, cookie)
}

// dropAccessTokenCookie drops a access token cookie into the response
func (r *oauthProxy) dropAccessTokenCookie(cx *gin.Context, value string, duration time.Duration) {
r.dropCookie(cx, r.config.CookieAccessName, value, duration)
func (r *oauthProxy) dropAccessTokenCookie(req *http.Request, w http.ResponseWriter, value string, duration time.Duration) {
r.dropCookie(w, req.Host, r.config.CookieAccessName, value, duration)
}

// dropRefreshTokenCookie drops a refresh token cookie into the response
func (r *oauthProxy) dropRefreshTokenCookie(cx *gin.Context, value string, duration time.Duration) {
r.dropCookie(cx, r.config.CookieRefreshName, value, duration)
func (r *oauthProxy) dropRefreshTokenCookie(req *http.Request, w http.ResponseWriter, value string, duration time.Duration) {
r.dropCookie(w, req.Host, r.config.CookieRefreshName, value, duration)
}

// clearAllCookies is just a helper function for the below
func (r *oauthProxy) clearAllCookies(cx *gin.Context) {
r.clearAccessTokenCookie(cx)
r.clearRefreshTokenCookie(cx)
func (r *oauthProxy) clearAllCookies(req *http.Request, w http.ResponseWriter) {
r.clearAccessTokenCookie(req, w)
r.clearRefreshTokenCookie(req, w)
}

// clearRefreshSessionCookie clears the session cookie
func (r *oauthProxy) clearRefreshTokenCookie(cx *gin.Context) {
r.dropCookie(cx, r.config.CookieRefreshName, "", time.Duration(-10*time.Hour))
func (r *oauthProxy) clearRefreshTokenCookie(req *http.Request, w http.ResponseWriter) {
r.dropCookie(w, req.Host, r.config.CookieRefreshName, "", time.Duration(-10*time.Hour))
}

// clearAccessTokenCookie clears the session cookie
func (r *oauthProxy) clearAccessTokenCookie(cx *gin.Context) {
r.dropCookie(cx, r.config.CookieAccessName, "", time.Duration(-10*time.Hour))
func (r *oauthProxy) clearAccessTokenCookie(req *http.Request, w http.ResponseWriter) {
r.dropCookie(w, req.Host, r.config.CookieAccessName, "", time.Duration(-10*time.Hour))
}
Loading

0 comments on commit 61b9130

Please sign in to comment.