traefik-forward-auth icon indicating copy to clipboard operation
traefik-forward-auth copied to clipboard

How to authenticate endpoints with a path?

Open AndreKR opened this issue 5 years ago • 4 comments

Take the simple-separate-pod example and modify it to have a path:

---
# Ingress
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: whoami
  labels:
    app: whoami
  annotations:
    kubernetes.io/ingress.class: traefik
    traefik.ingress.kubernetes.io/rule-type: PathPrefixStrip # <--- see explanation below
    ingress.kubernetes.io/auth-type: forward
    ingress.kubernetes.io/auth-url: http://traefik-forward-auth:4181
    ingress.kubernetes.io/auth-response-headers: X-Forwarded-User
spec:
  rules:
  - host: whoami.example.com
    http:
      paths:
      - path: /foo/ # <-------------------------------------------- add this
        backend:
          serviceName: whoami
          servicePort: http

Then navigate to https://whoami.example.com/foo/ (replace the host with your actual host). The authentication flow is started and then the user is redirected back to https://whoami.example.com/_oauth.

That page then shows

404 page not found

which makes sense because on https://whoami.example.com/ there is no forward auth configured, only on https://whoami.example.com/foo/.

I couldn't find any configuration to make this work. I believe there are two ways to solve it, but both require changes in Traefik Forward Auth.

Possibility 1: Use X-Forwarded-Prefix

If you add the annotation traefik.ingress.kubernetes.io/rule-type: PathPrefixStrip (see above) to the Ingress, Traefik will strip the /foo/ from the path before forwarding the request to Traefik Forward Auth. It will however add a header X-Forwarded-Prefix containing the /foo/ part. Traefik Forward Auth could simply add this to the redirect URL, so that it becomes https://whoami.example.com/foo/_oauth.

This is actually #49.

Possibility 2: Use Auth-Host mode

I tried switching to the Auth-Host mode. This solution is slightly inferior because it requires all authenticated hosts to run under one common cookie domain. (By the way, there is no error when AuthHost is set but CookieDomain isn't, the AuthHost will simply be ignored, making debugging difficult.)

When AuthHost is set, the authentication itself seems to work, but the following redirect back to the application is missing its path. The solution is simple: Don't discard the path when redirecting to the application.

AndreKR avatar Jun 27 '20 15:06 AndreKR

Hi - thanks for the detailed and well written question :)

You're right - they're two good ways to solve the issue, I'm keen to get #49 merged which would offer quite a nice solution to this.

Another option would be to manually add the path, using the traefik 1.7 as per your example:

---
# Ingress
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: whoami
  labels:
    app: whoami
  annotations:
    kubernetes.io/ingress.class: traefik
    ingress.kubernetes.io/auth-type: forward
    ingress.kubernetes.io/auth-url: http://traefik-forward-auth:4181
    ingress.kubernetes.io/auth-response-headers: X-Forwarded-User
spec:
  rules:
  - host: whoami.example.com
    http:
      paths:
      - path: /foo/
        backend:
          serviceName: whoami
          servicePort: http
      - path: /_oauth
        backend:
          serviceName: whoami
          servicePort: http

?

thomseddon avatar Jun 27 '20 19:06 thomseddon

Interesting idea. I actually have no idea what would happen, but I guess Traefik would just send the request to any of the Ingresses that have this path set? And it doesn't matter which one, because they all ~~end up at the same service~~ trigger the same auth-url? I'll try that out right away.

Edit: Doesn't work, I'm getting a redirect loop: image

AndreKR avatar Jun 27 '20 19:06 AndreKR

I'll have a test with this to see if it's possible

thomseddon avatar Jun 29 '20 20:06 thomseddon

Also, notice that enabling traefik-forward-auth globally (in Kubernetes and traefik2 this is done with the argument "--entrypoints.web.http.middlewares=default-traefik-forward-auth@kubernetescrd"), make the last redirect works. Still don't know why, but experimentally, at least for me, it is like that.

bennesp avatar Feb 26 '21 19:02 bennesp