traefik icon indicating copy to clipboard operation
traefik copied to clipboard

Forward authentication response headers

Open plaisted opened this issue 7 years ago • 13 comments

Do you want to request a feature or report a bug?

Feature

What did you expect to see?

It would be useful to allow headers returned from the forward authentication HTTP endpoint to be added to the final HTTP response. This would allow scenarios where the forward authentication endpoint can refresh authentication credentials and add the new credentials as a header/cookie.

This can be accomplished with a new configuration for http forward auth of "addHeadersToResponse" or similar.

Example:

addHeadersToResponse = ["Set-Cookie"]

This would result in any cookies added from HTTP forward auth response to be returned with the final response to the requesting client.

End-to-End example.

  1. Traefik receives request to entrypoint with forward auth.
  2. Traefik forward request to auth HTTP URI
  3. JWT is used as a cookie for authentication. Forward auth server validates JWT, but expiration of JWT is soon.
  4. Forward auth server requests new JWT for user and uses "Set-Cookie" header to overwrite previous JWT. Returns 20* response telling Traefik to continue routing.
  5. Request is routed to correct frontend/backend and response obtained.
  6. Forward auth middleware adds "Set-Cookie" header to outgoing response with new JWT.
  7. New JWT cookie is used for subsequent requests.

plaisted avatar Jul 23 '18 15:07 plaisted

Duplicate of #3515

Fixed by #3521

ldez avatar Jul 23 '18 16:07 ldez

@ldez I don't think this is a duplicate. Unless I'm missing something that solution allows headers to be added to the request that is sent to the backend. The use case above requires the headers to be added to the outgoing response.

plaisted avatar Jul 23 '18 16:07 plaisted

I could really use this.

We use a Rails server for authentication, and use forward authentication to convert the cookie to a JWT for other services. This works great, but doesn't allow the cookie to get updated.

My Kubernetes Ingress configuration looks like this

kind: Ingress
apiVersion: extensions/v1beta1
metadata:
  name: example
  annotations:
    kubernetes.io/ingress.class: traefik
    ingress.kubernetes.io/auth-type: forward
    ingress.kubernetes.io/auth-url: http://example-rails.default/authenticate
    ingress.kubernetes.io/auth-response-headers: Authorization
    ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
    - host: example.com
      http:
        paths:
          - path: /api
            backend:
              serviceName: example
              servicePort: 80

A possible workaround is to add Set-Cookie to ingress.kubernetes.io/auth-response-headers and then have the service copy the header to the response itself; but that requires that the service know about the cookie. In this case, I want the service to only know about JWTs.

cptaffe avatar Aug 31 '18 16:08 cptaffe

http://example-rails.default/authenticate

ingress.kubernetes.io/auth-url: http://example-rails.default/authenticate

Is the auth-url is k8s inner service address? Using inner service address as auth-url don't work! Are you encounter?Thanks

0x457 avatar Nov 19 '18 05:11 0x457

@0x457 using a k8s service url does work, I have a service using this with oauth2-proxy.

cptaffe avatar Nov 19 '18 14:11 cptaffe

How to use oauth2-proxy? Are there any examples?

0x457 avatar Nov 26 '18 08:11 0x457

@0x457 using a k8s service url does work, I have a service using this with oauth2-proxy.

Where's some example about oauth2-proxy? 👍

0x457 avatar Nov 27 '18 05:11 0x457

Hi. I have the same issue here. I want to use an external bot protection service which return a 200 or 401 according to the user agent / source IP etc.. It Also set a Cookie via the Set-Cookie Header which is not forwarded to the client response but only to the application backend. Ideally Traefik should merge the cookies set by the application with the cookies set by the auth forward service.

seuf avatar Apr 04 '19 15:04 seuf

We have the same issue, with our forwardAuth service to manipulate the cookies. Would like to propose as a draft #4730 (cannot tag because issue is closed)

yoadwo avatar Dec 04 '19 11:12 yoadwo

Hi, I'm gonna try to solve this soon, just wanted to clarify something before writing code:

I've just dived to the problem with overwriting headers. So, what I think is we have 3 cases:

  • Set-Cookie header is allowed to be set multiple times for different cookie names. rfc6265. So there should not be problem with that.
  • Set-Cookie sent from forwardAuth service should be overwritten by target service in case they have same cookie names.
  • For all the other headers values must be concatenated

Is this this the right behaviour?

iamolegga avatar May 29 '20 19:05 iamolegga

Any progress on this? I am using it on Swarm and have the same issue. For now I am leaving my services without refreshing the cookies.

adlion avatar May 31 '20 19:05 adlion

We're stumbling over the same issue right now, and need to set refreshed access tokens from our forward-auth middleware backend. We're currently running a workaround with sending a 307 redirect to the same URI to set headers which works surprisingly well, but we'd prefer to set the cookie directly, without the forward that will probably break some APIs.

My analysis of the situation so far (enumeration just for easier discussion):

  1. in general, the HTTP RFCs do not have a requirement on "repeated" headers, unless a proxy may not change their order; adding them seems fine
  2. there is a requirement on duplicate set-cookie headers on the same cookie key, which should not be sent following RFC 6265
  • we could prefer the auth server cookies
  • we could prefer backend cookies
  • we could leave the choice to the administrator/middleware configuration
  1. a rather naïve implementation like the one in #6893 will not be able to fulfill RFC 6265, but a proper wrapping response writer would be required to handle this
  2. traefik already has such a wrapper in the header middleware pkg/middlewares/headers/responsewriter.go (which does not (yet) conform to RFC 6265 either, though; at least I did not find any code indicating so)
  3. this cannot be easily reused yet, as the configuration happens in unexported fields/functions (ie. newResponseModifier)

My proposal would be to:

  1. implement RFC6265 compliant behavior for the header plugin, which following discussion in #6893 is a bug
  2. reuse the already implemented and tested responsewriter.go by exporting required fields/methods
  • should the code be moved to some kind of util package in this case? I did not find an obvious place yet
  1. add configuration to the forward auth plugin to define what cookies should be merged
  • probably somewhat aligned to how the add header plugin does the configuration
  • we need to think about, which headers should come first (backend or auth server), which also implies which system will potentially be able to override cookies from the other

If we can agree on this concept, I'd be ready to jump in with the required code.

CC @ldez @jbdoumenjou since you discussed previous approaches on this issue.

JensErat avatar Aug 10 '21 13:08 JensErat

As we have the same requirements than the others here: Any news on the issue ? What about the proposal of @JensErat ?

AFAIS all posts here needs the "set-cookie" header, so only merge cookies (instead of headers) would be sufficient. Using all configured cookies from auth response and the remaining (i.e. without the configured ones) cookies from backend would satisfy:

  1. No duplicate cookie names according to RFC
  2. As the cookies from auth server has higher priority, the backend can't overwrite the security relevant cookies from auth server.

tgunsch avatar Apr 01 '22 10:04 tgunsch

Hello ! I'm also in need of such a feature!

I'm using docker with services accessible on *.maison (ex: grafana.maison), cross-domain cookies don't work, I need my middleware to be able to pass a Set-Cookie to the user (so that the middleware can control the cookies).

Edit : the https://plugins.traefik.io/plugins/63b899ec3038a467c0ee9cb5/add-response-header plugin seems to do the trick for a certain amount of overload; in my case, I could also use sub-domains, but being local, that would mess up the URLs

codeberht avatar Jan 01 '24 16:01 codeberht

Closed by #8924

kevinpollet avatar Jan 25 '24 14:01 kevinpollet