docker-composetraefiktraefik-middleware

How to use Traefik ForwardAuth in Docker Compose?


I'm trying to adapt this Docker Compose example to use Traefik's ForwardAuth middleware, using https://github.com/thomseddon/traefik-forward-auth/blob/master/examples/traefik-v2/swarm/docker-compose-auth-host.yml as an example.

I have the following docker-compose.yml:

version: "3.3"

services:
  traefik:
    image: "traefik:v3.1"
    container_name: "traefik"
    command:
      - "--log.level=DEBUG"
      - "--api.insecure=true"
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--entryPoints.web.address=:80"
    ports:
      - "80:80"
      - "8080:8080"
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock:ro"

  whoami:
    image: "traefik/whoami"
    container_name: "simple-service"
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.whoami.rule=Host(`whoami.localhost`)"
      - "traefik.http.routers.whoami.entrypoints=web"

  traefik-forward-auth:
    build: ./auth
    labels:
      - "traefik.http.routers.traefik-forward-auth.rule=Host(`auth.localhost.com`)"
      - "traefik.http.middlewares.traefik-forward-auth.forwardauth.address=http://traefik-forward-auth:4181"
      - "traefik.http.middlewares.traefik-forward-auth.forwardauth.authResponseHeaders=X-Forwarded-User"
      - "traefik.http.services.traefik-forward-auth.loadbalancer.server.port=4181"

With the following directory structure:

.
├── auth
│   ├── Dockerfile
│   ├── authserver.go
│   └── go.mod
└── docker-compose.yml

where authserver.go is a simplified authorization server that requires the Authorization header to be Bearer me:

package main

import (
    "log"
    "net/http"
    "strings"
)

func main() {
    http.HandleFunc("/auth", func(w http.ResponseWriter, r *http.Request) {
        if strings.TrimSpace(strings.Replace(r.Header.Get("Authorization"), "Bearer", "", 1)) != "me" {
            http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
            return
        }
    })
    log.Fatal(http.ListenAndServe(":4181", nil))
}

Here is its Dockerfile:

FROM golang:1.23

WORKDIR /app
COPY go.mod ./
RUN go mod download
COPY *.go ./
RUN CGO_ENABLED=0 GOOS=linux go build -o /authserver
EXPOSE 8080
CMD ["/authserver"]

The problem is that the auth middleware seems to not be active, that is, if I run

docker-compose build && docker-compose up

and navigate to whoami.localhost in my browser, I see a response:

enter image description here

whereas I would expect to get a 401 response due to the Authorization header being absent.

It is a bit unclear to me from the configuration example in the documentation,

enter image description here

which container this label should be applied to: is it the auth server or the container that ForwardAuth middleware should be applied to? The example I linked earlier suggests it is the former, but I would have thought the latter. Any ideas on how to fix this example so that requests to whoami.localhost require an authorization header?


Solution

  • You need to assign the declared traefik-forward-auth middlewares to the target service in the labels on the target router:

          - "traefik.http.routers.whoami.middlewares=traefik-forward-auth"