Integrating Google OAuth with Traefik
I stumbled upon a really cool project: Traefik Forward Auth that provides Google OAuth based Login and Authentication for Traefik.
This means that you can secure your Traefik backend services by using Google for authentication to access your backends. Authorizing who can logon, get's managed on the forward proxy.
If you have not worked with Traefik, Traefik is one amazing dynamic and modern reverse proxy / load balancer built for micro services.
What are we doing today
In this demonstration we will setup a new google application, setup the forward-auth proxy and spin up a service that we will use google to authenticate against to access our application on Docker Swarm.
Pre-Requirements
Docker Swarm: We will be running this demonstration on Docker Swarm, you can follow this guide if you don't have a swarm provisioned yet.
DNS Setup: auth.domain.com, traefik.domain.com and whoami-debug.domain.com has an A record that is pointing to the public ip address of your docker swarm manager node.
Google Project
We will create a new google project, head over to https://console.developers.google.com and search for "credentials api", you should see the "IAM Service Account Credentials API", go ahead and select it:
You should now see the following:
Once you enable the API, create a New Project by selecting it on the right hand corner:
Go ahead and provide a descriptive name, in my case I called my project "my-traefik-oauth-proxy", once you provided a name, select "Create":
From the "OAuth consent screen", read through the sections, and provide the following:
- application name
- authorized domains (eg. example.com)
Then hit save:
From the "Credentials" section, select create credentials, and from the drop down select "OAuth client id":
We will be creating a "Web application", provide the "Name" of the application identifier and provide the "Authorized redirect URI's".
For example, if we want to protect your application: "https://mydemo.example.com", we will set the authorized redirect uri to "http://auth.example.com/_auth" as an example:
After you create the OAuth client, you will receive your client id and client secret, which we will need to provide to our traefik-forward-proxy service: (be sure to keep these credentials in a safe place)
Traefik
In this example I will use the domain example.com.
Let's start writing our docker-compose.yml
, which will consist of our traefik reverse proxy service and our traefik-forward-auth service.
I will explain the values that we require below the yaml:
version: '3.7'
services:
traefik:
image: traefik:1.7.14
ports:
- target: 80
published: 80
mode: host
- target: 443
published: 443
mode: host
command: >
--acme
--acme.storage=/certs/acme.json
--acme.entryPoint=https
--acme.httpChallenge.entryPoint=http
--acme.onHostRule=true
--acme.onDemand=false
--acme.acmelogging=true
--acme.email=${EMAIL:-root@localhost}
--docker
--docker.swarmMode
--docker.domain=${DOMAIN:-localhost}
--docker.watch
--defaultentrypoints=http,https
--entrypoints='Name:http Address::80'
--entrypoints='Name:https Address::443 TLS'
--logLevel=INFO
--accessLog
--metrics
--metrics.prometheus
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- traefik_certs:/certs
networks:
- public
deploy:
mode: replicated
replicas: 1
placement:
constraints:
- node.role == manager
update_config:
parallelism: 1
delay: 10s
restart_policy:
condition: on-failure
labels:
- "traefik.docker.network=public"
- "traefik.port=8080"
- "traefik.backend=traefik"
- "traefik.enable=true"
- "traefik.frontend.rule=Host:traefik.${DOMAIN:-localhost}"
- "traefik.frontend.headers.SSLRedirect=true"
- "traefik.frontend.entryPoints=http,https"
traefik-forward-auth:
image: thomseddon/traefik-forward-auth
environment:
- CLIENT_ID=your-client-id
- CLIENT_SECRET=your-client-secret
- OIDC_ISSUER=https://accounts.google.com
- SECRET=a-very-random-generated-key
- AUTH_HOST=auth.example.com
- COOKIE_DOMAINS=example.com
- WHITELIST=your-gmail-address@gmail.com
networks:
- public
deploy:
mode: replicated
replicas: 1
placement:
constraints:
- node.role==manager
resources:
limits:
memory: 128M
labels:
- traefik.frontend.rule=Host:auth.${DOMAIN:-localhost}
- traefik.frontend.auth.forward.address=http://traefik-forward-auth:4181
- traefik.frontend.auth.forward.trustForwardHeader=true
- traefik.enable=true
- traefik.port=4181
- traefik.tags=public
- traefik.backend=traefik-forward-auth
- traefik.docker.network=public
- traefik.redirectorservice.frontend.entryPoints=http
- traefik.redirectorservice.frontend.redirect.entryPoint=https
- traefik.webservice.frontend.entryPoints=https
networks:
public:
driver: overlay
name: public
volumes:
traefik_certs: {}
For our Traefik service we require a valid EMAIL environment variable, which will be used for creating the certificate, and a DOMAIN which will by default map your traefik service to traefik.example.com
if example.com was your domain.
Let's go ahead and set that as your environment variables:
$ export EMAIL=your-email@domain.com
$ export DOMAIN=example.com
For our Traefik Forward-Auth service, we require the CLIENT_ID
and CLIENT_SECRET
which we got from Google, the SECRET
will be a random secret key, which you can generate with openssl rand -hex 16
, the AUTH_HOST
being auth.example.com
if your domain is example.com, COOKIE_DOMAINS
will be your domain and WHITELIST
will be the email addresses that you would like to authorize.
In summary, these are the environment that we would want to set in our compose:
...
environment:
- CLIENT_ID=your-client-id
- CLIENT_SECRET=your-client-secret
- OIDC_ISSUER=https://accounts.google.com
- SECRET=a-very-random-generated-key
- AUTH_HOST=auth.example.com
- COOKIE_DOMAINS=example.com
- WHITELIST=your-gmail-address@gmail.com
...
Once we have everything in place we can deploy our stack:
$ docker stack deploy -c docker-compose.yml proxy
Creating network public
Creating service proxy_traefik-forward-auth
Creating service proxy_traefik
Integrating Google Auth with a Web Service
Now that we have our Traefik proxy and OAuth forwarder running, we would like to protect a web service by integrating google sign-in onto our application.
Since we have authorized one gmail address as a whitelist, upon successful login via gmail from the mentioned address, we will be directed to our web service.
To protect your web application with google oauth, we simple just add 3 lines to our deploy labels of the service that we want authentication enabled on:
- traefik.frontend.auth.forward.address=http://traefik-forward-auth:4181
- traefik.frontend.auth.forward.authResponseHeaders=X-Forwarded-User
- traefik.frontend.auth.forward.trustForwardHeader=true
A full compose that we will populate to docker-compose.app.yml
:
version: '3.7'
services:
whoami:
image: containous/whoami
networks:
- public
deploy:
labels:
- traefik.frontend.rule=Host:whoami-debug.${DOMAIN}
- traefik.port=80
- traefik.tags=public
- traefik.backend=whoami
- traefik-docker.network=public
- traefik.frontend.auth.forward.address=http://traefik-forward-auth:4181
- traefik.frontend.auth.forward.authResponseHeaders=X-Forwarded-User
- traefik.frontend.auth.forward.trustForwardHeader=true
- traefik.redirectorservice.frontend.entryPoints=http
- traefik.redirectorservice.frontend.redirect.entryPoint=https
- traefik.webservice.frontend.entryPoints=https
networks:
public:
external: true
Deploy our web app:
$ docker stack deploy -c docker-compose.app.yml web
Creating service web_whoami
When accessing https://whoami-debug.domain.com we will be redirected to https://accounts.google.com as you can see:
Upon successful login, you will be redirected to auth.domain.com then directed to your web application:
Thank You
And there you have it, simple and easy authentication & authorization to your traefik backends using the oauth protocol.
Please have a look at thomseddon/traefik-forward-auth and make sure to star the project if you find it useful.