thomseddon / traefik-forward-auth

Minimal forward authentication service that provides Google/OpenID oauth based login and authentication for the traefik reverse proxy
MIT License
2.13k stars 408 forks source link

Rules with 'domain' or 'whitelist' don't work as expected #311

Open dannyyy opened 2 years ago

dannyyy commented 2 years ago

I tried different rules and orders to get it work. But there seems to be a major misconfiguration in my manifest or the rule engine is buggy. I appreciate every support I can get.

Expected Result Public: https://whoami.mydomain.com/* should be allowed without authentication Protected: https://whoami.mydomain.com/secret/* must require authentication

Tried Rules and its Results The impact of the following rules has been tested out and logging has been enabled with debug severity.

rule.whoami-secure.action=auth
rule.whoami-secure.rule=Host(`whoami.mydomain.om`) && PathPrefix(`/secure`)
rule.whoami-secure.whitelist=alias@mydomain.com

rule.whoami.action=allow
rule.whoami.rule=Host(`whoami.mydomain.com`)

Public: Request for authentication because the default rule matched. (unexpected) Protected: Request for authentication because the whoami-secure rule matched. (expected)

rule.whoami-secure.action=auth
rule.whoami-secure.rule=Host(`whoami.mydomain.om`) && PathPrefix(`/secure`)
rule.whoami-secure.domain=mydomain.com

rule.whoami.action=allow
rule.whoami.rule=Host(`whoami.mydomain.com`)

Public: Request for authentication because the default rule matched. (unexpected) Protected: Request for authentication because the whoami-secure rule matched. (expected)

rule.whoami-secure.action=auth
rule.whoami-secure.rule=Host(`whoami.mydomain.om`) && PathPrefix(`/secure`)

rule.whoami.action=allow
rule.whoami.rule=Host(`whoami.mydomain.com`)

Public: Unauthorized access possible because the whoami rule matched. (expected) Protected: Request for authentication because the whoami-secure rule matched. But with wrong redirect. The redirect to https://whoami.mydomain.com/_oauth/... is final (rule whoami matches), no cookie set, and no proper redirect to the origin url. (unexpected)

rule.whoami.action=allow
rule.whoami.rule=Host(`whoami.mydomain.com`)

rule.whoami-secure.action=auth
rule.whoami-secure.rule=Host(`whoami.mydomain.om`) && PathPrefix(`/secure`)

Public: Unauthorized access possible because the whoami rule matched. (expected) Protected: Unauthorized access possible because the whoami rule matched. (unexpected)

rule.whoami.action=allow
rule.whoami.rule=Host(`whoami.mydomain.com`)

rule.whoami-secure.action=auth
rule.whoami-secure.rule=Host(`whoami.mydomain.om`) && PathPrefix(`/secure`)
rule.whoami-secure.whitelist=alias@mydomain.com

Public: Unauthorized access possible because the whoami rule matched. (expected) Protected: Unauthorized access possible because the whoami rule matched. (unexpected)

traefik-forward-auth Confifuration My installation / configuration follows the example advanced-separate-pod.

apiVersion: v1
kind: Service
metadata:
  name: traefik-forward-auth
  labels:
    app: traefik-forward-auth
spec:
  type: ClusterIP
  selector:
    app: traefik-forward-auth
  ports:
  - name: auth-http
    port: 4181
    targetPort: 4181

---
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: auth-secure
spec:
  entryPoints:
    - websecure
  routes:
    - match: Host(`auth.mydomain.com`)
      kind: Rule
      services:
        - name: traefik-forward-auth
          port: 4181
  tls:
    certResolver: le

---
apiVersion: v1
kind: Secret
type: Opaque
metadata:
  name: traefik-forward-auth-secrets
data:
  google-client-id: <my-google-client-id>
  google-client-secret: <my-google-client-secret>
  secret: <my-random-secret>

---
apiVersion: v1
kind: ConfigMap
metadata:
  name: traefik-forward-auth-configs
data:
  traefik-forward-auth.ini: |
    <see issue>

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: traefik-forward-auth
  labels:
    app: traefik-forward-auth
spec:
  replicas: 1
  selector:
    matchLabels:
      app: traefik-forward-auth
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: traefik-forward-auth
    spec:
      serviceAccountName: traefik
      terminationGracePeriodSeconds: 60
      containers:
      - image: thomseddon/traefik-forward-auth:2
        name: traefik-forward-auth
        ports:
        - containerPort: 4181
          protocol: TCP
        env:
        - name: CONFIG
          value: "/config/traefik-forward-auth.ini"
        # INSECURE_COOKIE is required if not using a https entrypoint
        # - name: INSECURE_COOKIE
        #   value: "true"
        # Remove COOKIE_DOMAIN if not using auth host mode
        # - name: COOKIE_DOMAIN
        #   value: "mydomain.com"
        # - name: AUTH_HOST
        #   value: "auth.mydomain.com"
        - name: LOG_LEVEL
          value: "debug"
        - name: PROVIDERS_GOOGLE_CLIENT_ID
          valueFrom:
            secretKeyRef:
              name: traefik-forward-auth-secrets
              key: google-client-id
        - name: PROVIDERS_GOOGLE_CLIENT_SECRET
          valueFrom:
            secretKeyRef:
              name: traefik-forward-auth-secrets
              key: google-client-secret
        - name: SECRET
          valueFrom:
            secretKeyRef:
              name: traefik-forward-auth-secrets
              key: secret
        volumeMounts:
        - name: configs
          mountPath: /config/traefik-forward-auth.ini
          subPath: traefik-forward-auth.ini

      volumes:
      - name: configs
        configMap:
          name: traefik-forward-auth-configs
      - name: traefik-forward-auth-secrets
        secret:
          secretName: traefik-forward-auth-secrets
frapit commented 2 years ago

You should update your image to the :latest tag, some bugs concerning whitelists in rules have been wiped out there. In theory the first configuration should get you the desired result, given that the email has been parsed from the token correctly.

dannyyy commented 2 years ago

Unfortunately this does not help. Using the first configuration with the latest image tag results in:

Public request works as expected.

Protected request redirects to Google and after login it only redirects to: https://whoami.mydomain.com/_oauth?state=1234567890%3Agoogle%3Ahttps%3A%2F%2Fwhoami.mydomain.com%2Fsecure%2Fabc&code=41234567890&scope=email+profile+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email+openid&authuser=0&prompt=none traefik-forward-auth is not processing this response and applies the public (whoami) rule. If I navigate again to the /secure endpoint, a second CSRF cookie will be added. Now I have two. With each try an additional cookie will be added. No auto-cleanup.

This is the debug lo:

time="2022-04-16T19:50:02Z" level=debug msg="Authenticating request" cookies="[]" handler=Auth host=whoami.mydomain.com method=GET proto=https rule=whoami-secure source_ip=1.2.3.4 uri=/secure
time="2022-04-16T19:50:02Z" level=debug msg="Set CSRF cookie and redirected to provider login url" csrf_cookie="_forward_auth_csrf_123=123; Path=/; Domain=whoami.mydomain.com; Expires=Sat, 16 Apr 2022 20:50:02 GMT; HttpOnly; Secure" handler=Auth host=whoami.mydomain.com login_url="https://accounts.google.com/o/oauth2/auth?client_id=81234567890.apps.googleusercontent.com&prompt=select_account&redirect_uri=https%3A%2F%2Fwhoami.mydomain.com%2F_oauth&response_type=code&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email&state=12345678890%3Agoogle%3Ahttps%3A%2F%2Fwhoami.mydomain.com%2Fsecure" method=GET proto=https rule=whoami-secure source_ip=1.2.3.4 uri=/secure
time="2022-04-16T19:50:05Z" level=debug msg="Allowing request" cookies="[_forward_auth_csrf_123=123]" handler=Allow host=whoami.mydomain.com method=GET proto=https rule=whoami source_ip=1.2.3.4 uri="/_oauth?state=d7955fbdc6b59f0440d69ab55138547f%3Agoogle%3Ahttps%3A%2F%2Fwhoami.mydomain.com%2Fsecure&code=1234567890&scope=email+profile+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email+openid&authuser=0&prompt=none"
time="2022-04-16T19:50:05Z" level=debug msg="Allowing request" cookies="[_forward_auth_csrf_123=123]" handler=Allow host=whoami.mydomain.com method=GET proto=https rule=whoami source_ip=1.2.3.4 uri=/favicon.ico
time="2022-04-16T19:51:50Z" level=debug msg="Authenticating request" cookies="[_forward_auth_csrf_123=123]" handler=Auth host=whoami.mydomain.com method=GET proto=https rule=whoami-secure source_ip=1.2.3.4 uri=/secure/abc
time="2022-04-16T19:51:50Z" level=debug msg="Set CSRF cookie and redirected to provider login url" csrf_cookie="_forward_auth_csrf_987=987; Path=/; Domain=whoami.mydomain.com; Expires=Sat, 16 Apr 2022 20:51:50 GMT; HttpOnly; Secure" handler=Auth host=whoami.mydomain.com login_url="https://accounts.google.com/o/oauth2/auth?client_id=1234567890.apps.googleusercontent.com&prompt=select_account&redirect_uri=https%3A%2F%2Fwhoami.mydomain.com%2F_oauth&response_type=code&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email&state=1234567890%3Agoogle%3Ahttps%3A%2F%2Fwhoami.mydomain.com%2Fsecure%2Fabc" method=GET proto=https rule=whoami-secure source_ip=1.2.3.4 uri=/secure/abc
time="2022-04-16T19:51:54Z" level=debug msg="Allowing request" cookies="[_forward_auth_csrf_123=123 _forward_auth_csrf_987=987]" handler=Allow host=whoami.mydomain.com method=GET proto=https rule=whoami source_ip=1.2.3.4 uri="/_oauth?state=1234567890%3Agoogle%3Ahttps%3A%2F%2Fwhoami.mydomain.com%2Fsecure%2Fabc&code=1234567890&scope=email+profile+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email+openid&authuser=0&prompt=none"
time="2022-04-16T19:51:54Z" level=debug msg="Allowing request" cookies="[_forward_auth_csrf_123=123 _forward_auth_csrf_987=987]" handler=Allow host=whoami.mydomain.com method=GET proto=https rule=whoami source_ip=1.2.3.4 uri=/favicon.ico
jlmartins-sf commented 2 years ago

@dannyyy have you fix this redirect to google?

rea11st commented 1 year ago

i have the same issue, did u resolve this?

hterik commented 1 year ago

The problem is that buildRoutes() function adds the rule-based routes before adding route for AuthCallbackHandler, leading to the AuthHandler to respond to everything and generating an infinite redirect-route. I believe the order of these should be swapped.