This demonstrates how to wire up gatekeeper with keycloak.
docker-compose up -d
Watch the logs with docker-compose logs -f
.
After everything has started, point your browser to
- https://whoami.localhost (you should see your request)
- https://keycloak.localhost (you should see keycloak - log in with
admin
andpassword
) - https://whoami.localhost/get (you should be redirected to keycloak, where you have to login)
A user with
- username =
user
- password =
password
has been automatically created for you (see ./config/keycloak/setup.sh
)
We use docker-compose to bring up a group of services in this demo - keycloak, gatekeeper and whoami. This setup uses the OAuth 2.0 Authorization Code flow.
- whoami is a simple service that echoes the content of the request.
- whoami allows us to inspect the contents of the request, especially the headers that were inserted by gatekeeper
- whoami serves as the app that you want to add authentication and authorization for
- in OAuth terms, whoami is half of a resource server: the resource in the resource server
- keycloak is, in OAuth terms, our authorization provider
- gatekeeper needs to be able to communicate with keycloak's well-known configuration endpoint over https to get keycloak's public key. The public key will be used to verify any tokens in requests
- gatekeeper guards the app, whoami
- In OAuth terms, gatekeeper is both
- a client, because it handles exchanging the authorization code for the access token with the authorization provider (Keycloak) and handles token refreshing
- half of a resource server, because it checks for a valid access token before permitting access to the upstream app (whoami)
- This two-in-one nature is pretty common - Ambassador's OAuth2 filter does this too
- In OAuth terms, gatekeeper is both
- caddy is present mostly as a convenient
- request router: it allows both keycloak and whoami (the app) to appear to run on port 443 to the browser on your host
- tls certificate provider: caddy provides a self-signed a certificate to
terminate TLS for both keycloak and the app
- gatekeeper, by design, must make HTTPS connections to the authorization provider
- gatekeeper does this by calling Keycloak through caddy
In your production setup, you should
- have Keycloak as a central service external to your app
- establish trust between gatekeeper and your app, such as
- by putting gatekeeper and your app in a docker network and allow network access to your app only through gatekeeper
- using firewalls to only allow network access to your app through gatekeeper
- using mTLS between gatekeeper and your app
In short, you should only allow access to your app through gatekeeper. This ensures that
- all accesses to your app are authenticated and authorized by gatekeeper
- your app can rely on gatekeeper completely for authentication and authorization
See
./config/keycloak/setup.sh
for all the config that was done
- An
applications
realm is created.whoami
will be added as a client in this realm - A user is created in the applications realm
See
./config/gatekeeper/setup.sh
for all the config that was done
- whoami is added as a client (client in OAuth2 terms)
- whoami has
redirectUris
set tohttps://whoami.localhost/oauth/callback*
- If Keycloak only accepts
redirectUris
pointing back towhoami
, we can be sure that attackers cannot abuse thewhoami
client to collect auth codes by redirecting clients to malicious servers that are attacker-controlled
- If Keycloak only accepts
- The
defaultClientScopes
set means if our user has profile information, email or roles set, Keycloak will include this information in the token- Inspect what each client scope maps into the token by looking at
Client Scopes
on the left navbar on Keycloak
- Inspect what each client scope maps into the token by looking at
- The
optionalClientScopes
set means that thewhoami
client can optionally request foraddress
orphone
using--scopes
in gatekeeper, and the mappers associated with theaddress
orphone
scopes will be applied on the token
Inspect your token: point your browser to https://whoami.localhost/get, then copy
X-Auth-Token
and inspect it at jwt.io
-
Add a client scope for
whoami
, with a mapper that maps the client name (whoami
) into theaud
field of the token- gatekeeper checks that the access token has
whoami
in theaud
field before permitting it
- gatekeeper checks that the access token has
-
Associates this client scope with the client
whoami
-
Adds any requested client roles (in this case
read
andwrite
)- Client roles can be used for authorization rules in gatekeeper
Most of gatekeeper's config is in ./config/gatekeeper/config.yml
, except for
--client-secret
, which is specified on the command line in
./config/gatekeeper/start.sh
Look in ./config/gatekeeper/config.yml
for commented configuration!
- If you're on linux,
*.localhost
redirects to localhost, so you don't have to fiddle with DNS or/etc/hosts
- You can get chrome to accept self-signed SSL certs on localhost. Just enable this chrome flag: chrome://flags/#allow-insecure-localhost