oauth2-proxy / oauth2-proxy

A reverse proxy that provides authentication with Google, Azure, OpenID Connect and many more identity providers.
https://oauth2-proxy.github.io/oauth2-proxy
MIT License
9.43k stars 1.55k forks source link

Not redirecting to subpath after login using Traefik's 401 errors middleware #1297

Open lanmarti opened 3 years ago

lanmarti commented 3 years ago

Expected Behavior

  1. Attempt to access service on subpath example.domain/sub/path
  2. Get redirected to oauth2-proxy on example.domain/oauth2/auth
  3. Log in through auth provider
  4. Get redirected to example.domain/sub/path

Current Behavior

  1. Attempt to access service on subpath example.domain/sub/path
  2. Get redirected to oauth2-proxy on example.domain/oauth2/auth
  3. Log in through auth provider
  4. Get redirected to example.domain instead of example.domain/sub/path

Steps to Reproduce (for bugs)

  1. Use following config values for oauth2-proxy
    oauth2_proxy.cfg: |-
    provider = "oidc"
    provider_display_name = "Keycloak"
    redirect_url = "https://example.domain/oauth2/callback"
    oidc_issuer_url = "https://example.domain/auth/"
    cookie_secure = false
    reverse_proxy = true
    email_domains = [ "*" ]
    upstreams = [ "file:///dev/null" ]
    pass_access_token = true
    pass_authorization_header = true
    set_authorization_header = true
    set_xauthrequest = true
    pass_user_headers = true
    whitelist_domains= [ ".example.domain" ]
  2. Set up traefik middlewares and ingresses as currently described in the docs: https://oauth2-proxy.github.io/oauth2-proxy/docs/configuration/overview#forwardauth-with-401-errors-middleware In kubernetes CRD form:
    apiVersion: traefik.containo.us/v1alpha1
    kind: Middleware
    metadata:
    name: auth-headers
    spec:
    headers:
    sslRedirect: true
    stsSeconds: 315360000
    browserXssFilter: true
    contentTypeNosniff: true
    forceSTSHeader: true
    stsIncludeSubdomains: true
    stsPreload: true
    frameDeny: true
    ---
    apiVersion: traefik.containo.us/v1alpha1
    kind: Middleware
    metadata:
    name: oauth-auth
    spec:
    forwardAuth:
    address: https://example.domain/oauth2/auth
    trustForwardHeader: true
    ---
    apiVersion: traefik.containo.us/v1alpha1
    kind: Middleware
    metadata:
    name: oauth-errors
    spec:
    errors:
    status:
      - "401-403"
    service:
      name: oauth2-proxy
      port: 80
    query: "/oauth2/sign_in"
    ---
    apiVersion: traefik.containo.us/v1alpha1
    kind: IngressRoute
    metadata:
    name: oauth2-proxy
    spec:
    entryPoints:
    - websecure
    routes:
    - match: PathPrefix(`/oauth2/`)
    kind: Rule
    services:
    - name: oauth2-proxy
      port: 80
    middlewares:
    - name: auth-headers
  3. Expose a service
    apiVersion: traefik.containo.us/v1alpha1
    kind: IngressRoute
    metadata:
    name: subpath-test
    spec:
    entryPoints:
    - websecure
    routes:
    - match: PathPrefix(`/foo/bar`)
    kind: Rule
    services:
    - name: bar
      port: 8080
    middlewares:
    - name: oauth-errors
      namespace: traefik-v2
    - name: oauth-auth
      namespace: traefik-v2
  4. Navigate to example.domain/foo/bar, follow login flow

Context

There seem to be quite a few issues related to Oauth2 Proxy and Traefik, however the closest I could find to my current issue is https://github.com/oauth2-proxy/oauth2-proxy/issues/397 which is over a year old. Besides the environment traefik is running in, the issue is very similar. https://github.com/oauth2-proxy/oauth2-proxy/issues/1255 seems somewhat similar as well, but I'm currently not using skip-provider-button.

As there are several issues related to Traefik + Oauth2 Proxy both here and on Traefik's github page, I might have missed potential solutions, but from what I've read so far it seems like the only workaround at the moment is to create a middleware that attaches the X-Auth-Request-Redirect header manually. As Traefik is currently not offering dynamic headers, this has to be done per service. Both https://github.com/oauth2-proxy/oauth2-proxy/issues/397 and https://github.com/oauth2-proxy/oauth2-proxy/issues/46#issuecomment-687155032 seem to use custom middlewares for each service to solve the issue, which is far from ideal. https://github.com/traefik/traefik/issues/6839 might eventually provide a generic solution from Traefik's site, although I'm not completely sure if this is a surefire fix.

An attempt was made at providing the correct functionality from Traefik's side: https://github.com/traefik/traefik/pull/6835 however developers did not like the oauth2-proxy specific approach.

I've posted this here as oauth2-proxy seems more inclined to adopt Traefik specific fixes than the other way around.

Your Environment

Multiple services are hosted on the same domain, but under different subpaths.

JoelSpeed commented 3 years ago

As far as I know this should be fixed now, we introduced some logic to read the headers that traefik sets to identify which path we should be redirecting to.

Are there any logs in OAuth2 Proxy that suggest where/why it might not be redirecting as expected?

lanmarti commented 3 years ago

"/oauth2/start?rd=https%3A%2F%2Fexample.com%2F" is the only relevant line I can find, at first glance.

[2021/09/06 12:26:54] [stored_session.go:76] Error loading cookied session: cookie "_oauth2_proxy" not present, removing session
10.244.2.1 - 531acacd-ae45-44e6-a2c8-b8009f2d2e16 - - [2021/09/06 12:26:54] example.com GET - "/oauth2/auth" HTTP/1.1 "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:91.0) Gecko/20100101 Firefox/91.0" 401 13 0.035
10.244.3.0 - 893d7453-d0b0-43f7-a736-f416b4caf2ba - - [2021/09/06 12:26:54] example.com GET - "/oauth2/sign_in" HTTP/1.1 "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:91.0) Gecko/20100101 Firefox/91.0" 200 8097 0.008
10.244.3.0 - f3e67a84-5693-40b2-85a0-006e84a8996d - - [2021/09/06 12:27:23] example.com GET - "/oauth2/start?rd=https%3A%2F%2Fexample.com%2F" HTTP/1.1 "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:91.0) Gecko/20100101 Firefox/91.0" 302 360 0.029
10.244.3.0 - f112ed0a-06cd-479e-8083-aaeeaeae8f4b - john@doe.com [2021/09/06 12:27:24] [AuthSuccess] Authenticated via OAuth2: Session{email:john@doe.com user:cc6bcc9d-aaab-410c-aa76-3542eedecdb5 PreferredUsername:john@doe.com token:true id_token:true created:2021-09-06 12:27:24.066213931 +0000 UTC m=+2694877.895889139 expires:2021-09-06 12:32:24.065686079 +0000 UTC m=+2695177.895361295 refresh_token:true groups:[/cluster-admin /developer/trusted-developer]}
10.244.3.0 - f112ed0a-06cd-479e-8083-aaeeaeae8f4b - - [2021/09/06 12:27:23] example.com GET - "/oauth2/callback?state=AIL6V_oQavAMrp5uJGCQ8MNf8dhveDtyybP4MwYBres%3Ahttps%3A%2F%2Fexample.com%2F&session_state=7b2f3c18-4cea-4cf5-a6fc-29ac1be6c5f3&code=2718689c-f1ae-4f8d-b45f-33f4eb2051d8.7b2f3c18-4cea-4cf5-a6fc-29ac1be6c5f3.2b988a94-90d2-4534-8b61-ed08cb057e8a" HTTP/1.1 "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:91.0) Gecko/20100101 Firefox/91.0" 302 50 0.108

I removed the GETs to /ping from the logs for readability, replaced our domain name with example.com , as well as replaced my email address, but everything else is left untouched. The logs above are obtained by navigating to example.com/logs, which should result in redirecting to our Kibana service after logging in.

pinarruiz commented 2 years ago

I am facing the same issue, a workaround would be to use the headers middleware for each service, which is far away from a good solution.

JoelSpeed commented 2 years ago

You've got the rd parameter in there, so it looks like we aren't even using the Traefik checks here. Have you got the whitelist-domain option set? That should allow you to set the redirect to your domain if configured correctly.

If you have the ability to try out the master branch, we have much more logic around this stuff which I don't think has made it to a release just yet, including increased logging which may help identify the issue

lanmarti commented 2 years ago

I have the 'whitelist_domains' set to our main domain, starting with a dot to allow subdomains (.maindomain.com), as per the docs. Just to make sure, I've now tested it with a fixed subdomain(subdomian.maindomain.com) as well, but the issue is still there.

I cloned the master branch, build the docker image (docker build -f .\Dockerfile -t lanmarti/oauth2-proxy .) and set up a deployment to use that image instead, but the logging output seems to be identical to the official v7. Are there any flags that need to be set, or do you have more details on how to generate the image?

JoelSpeed commented 2 years ago

So looks to me like, whatever is injecting "/oauth2/start?rd=https%3A%2F%2Fexample.com%2F" is not injecting the path. Looking at the rd value here, you are only setting the redirect to the root of the domain (%2F being /). So you need to remove that rd parameter to allow the traefik headers to take precedence in the redirect fetching logic.

Otherwise, you need to update whatever is injecting the rd paremeter to also include the path as well, how you'll do that I'm not sure though.

Looking at your config, it seems you are sending the auth error to /oauth2/sign_in, which will then show the login selection right? Have you tried skipping this and just having /oauth2/start as the error handler? This is what we would normally do.

lanmarti commented 2 years ago

I replaced /oauth2/sign_in with /oauth2/start in the oauth-errors middleware. From the user's point of view, nothing has changed, except that instead of a graphic and a login button, there now is a 'Found' url that redirects to our Keycloak when clicked, like the button used to do.

The logs are slightly different now, there is no rd parameter present anymore, but redirecting after login still does not work.

10.244.2.0 - 84b5fc04-0c37-49b7-b831-5e954493578a - - [2021/10/05 06:54:53] example.com GET - "/oauth2/auth" HTTP/1.1 "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:92.0) Gecko/20100101 Firefox/92.0" 401 13 0.000
[2021/10/05 06:54:53] [stored_session.go:77] Error loading cookied session: cookie "_oauth2_proxy" not present, removing session
10.244.1.0 - a4e28fba-aa13-4d78-a18f-b66f62d7af09 - - [2021/10/05 06:54:53] example.com GET - "/oauth2/start" HTTP/1.1 "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:92.0) Gecko/20100101 Firefox/92.0" 302 360 0.000
10.244.1.0 - 52d06dc8-07f1-4397-9814-68e74a1d7e49 - john@doe.com [2021/10/05 06:55:33] [AuthSuccess] Authenticated via OAuth2: Session{email:john@doe.com user:cc6bcc9d-aaab-410c-aa76-3542eedecdb5 PreferredUsername:john@doe.com token:true id_token:true created:2021-10-05 06:55:33.728152323 +0000 UTC m=+80583.709032201 expires:2021-10-05 07:00:33.727315944 +0000 UTC m=+80883.708195821 refresh_token:true groups:[/cluster-admin /developer/trusted-developer]}
10.244.1.0 - 52d06dc8-07f1-4397-9814-68e74a1d7e49 - - [2021/10/05 06:55:33] example.com GET - "/oauth2/callback?state=BuIzLuRu9zrkN3myaC-9g7RwcMEGyo8pHh1c2JLjFe4%3Ahttps%3A%2F%2Fexample.com%2F&session_state=37e63c20-d673-40a7-abad-3f5ffa541c2a&code=4487c28d-3536-4b5a-9685-68df7ed95ca1.37e63c20-d673-40a7-abad-3f5ffa541c2a.2b988a94-90d2-4534-8b61-ed08cb057e8a" HTTP/1.1 "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:92.0) Gecko/20100101 Firefox/92.0" 302 50 0.027
JoelSpeed commented 2 years ago

There was another issue reporting the same from traefik recently, might be worth a search as I don't have it handy right now.

The fact that traefik is showing the found page is wrong, it should instead honour the redirect and send your user onto the login page.

Where are you being redirected to after login with this configuration?

lanmarti commented 2 years ago

I was still being redirected to the root, i.e. subdomain.example.com.

Are you referring to https://github.com/oauth2-proxy/oauth2-proxy/issues/1322 ? That issue mentions the skip-provider-button configuration option, so I tried: setting it to false, setting it to true and not setting it at all, restarting the pod after every configuration change. In all three cases I got the Found. text when using /start instead of /sign_in. When using /sign_in, setting skip-provider-button to true gives me the same Found. link, not setting it, or setting it to false gives me the oauth2 proxy logo and a Sign in with Keycloak button.

I've looked through some other issues, but I'm even more confused now. In https://github.com/oauth2-proxy/oauth2-proxy/issues/1355#issuecomment-920853257 a working traefik/oauth2-proxy setup is described, yet they don't use the error middleware at all. If I try a similar setup, with the ingress only specifying the forward-auth middleware instead of both error and forward-auth, I just end up with an unauthorized message and a single log entry:

10.244.2.0 - e8028522-47ce-411d-b805-895ecb91215d - - [2021/10/06 06:50:48] subdomain.example.com GET - "/oauth2/auth" HTTP/1.1 "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:92.0) Gecko/20100101 Firefox/92.0" 401 13 0.000

I'm running Traefik with default options, excluding an extra entrypoint, a forced https redirect and some TLS options, none of which seem to be relevant for this issue.

JoelSpeed commented 2 years ago

Yes that's the issue I was referring to, as you can see from my comments there, OAuth2 Proxy is behaving as expected in this case, something about the Traefik configuration is wrong. Unfortunately, I'm not a traefik user, so I don't think I'll be able to help you here

lanmarti commented 2 years ago

I've posted the issue over at Traefik's forum, but looking at the lack of response on similar issues over there, I don't exactly have high hopes for a meaningful reply.

Earlier in the thread you said the following:

So looks to me like, whatever is injecting "/oauth2/start?rd=https%3A%2F%2Fexample.com%2F" is not injecting the path. Looking at the rd value here, you are only setting the redirect to the root of the domain (%2F being /). So you need to remove that rd parameter to allow the traefik headers to take precedence in the redirect fetching logic.

Otherwise, you need to update whatever is injecting the rd paremeter to also include the path as well, how you'll do that I'm not sure though.

Do you have any clue on which component provides the rd parameter, i.e. is it Traefik, Oauth2-proxy, or something entirely different?

In the logs from my working traefik-forward-auth setup, a proxy auth component created specifically for Traefik, I can see my original url being sent as part of the state from the forward auth component to Keycloak (our OIDC provider) and then again in the callback. These are the logs for a request to sub.domain.com/monitoring/prometheus/graph:

time="2021-10-20T13:13:31Z" level=debug msg="Set CSRF cookie and redirected to provider login url" csrf_cookie="_forward_auth_csrf=6f6dc18df84a100c97674769e50ab040; Path=/; Domain=sub.domain.com; Expires=Thu, 21 Oct 2021 01:13:31 GMT; HttpOnly; Secure" handler=Auth host=sub.domain.com login_url="https://sub.domain.com/auth/realms/main/protocol/openid-connect/auth?client_id=general-forward-auth&redirect_uri=https%3A%2F%2Fsub.domain.com%2F_oauth&response_type=code&scope=openid+profile+email&state=6f6dc18df84a100c97674769e50ab040%3Aoidc%3Ahttps%3A%2F%2Fsub.domain.com%2Fmonitoring%2Fprometheus%2Fgraph" method=GET proto=https rule=default source_ip=10.244.5.0 uri=/monitoring/prometheus/graph
time="2021-10-20T13:22:16Z" level=debug msg="Handling callback" cookies="[_forward_auth_csrf=6f6dc18df84a100c97674769e50ab040]" handler=AuthCallback host=sub.domain.com method=GET proto=https rule=default source_ip=10.244.2.1 uri="/_oauth?state=6f6dc18df84a100c97674769e50ab040%3Aoidc%3Ahttps%3A%2F%2Fsub.domain.com%2Fmonitoring%2Fprometheus%2Fgraph&session_state=6ffd61cf-d29e-4adb-a81d-58c075c65b65&code=0957b9ed-5ebd-43b4-ade8-4153ff5b6f10.6ffd61cf-d29e-4adb-a81d-58c075c65b65.176da2fa-65b4-4171-bf2e-22a4a44a2860"
time="2021-10-20T13:22:17Z" level=info msg="Successfully generated auth cookie, redirecting user." handler=AuthCallback host=sub.domain.com method=GET proto=https provider=oidc redirect="https://sub.domain.com/monitoring/prometheus/graph" rule=default source_ip=10.244.2.1 uri="/_oauth?state=6f6dc18df84a100c97674769e50ab040%3Aoidc%3Ahttps%3A%2F%2Fsub.domain.com%2Fmonitoring%2Fprometheus%2Fgraph&session_state=6ffd61cf-d29e-4adb-a81d-58c075c65b65&code=0957b9ed-5ebd-43b4-ade8-4153ff5b6f10.6ffd61cf-d29e-4adb-a81d-58c075c65b65.176da2fa-65b4-4171-bf2e-22a4a44a2860" user=john@doe.com

On their github page, the following is mentioned:

Supports multiple domains/subdomains by dynamically generating redirect_uri's

I'm guessing this is what does not work with Oauth2-proxy? Where traefik-forward-auth provides the redirect url themselves, oauth2-proxy expects Traefik to provide the redirect url?

You also said:

You've got the rd parameter in there, so it looks like we aren't even using the Traefik checks here.

I did a quick search for 'traefik check' in the code, but couldn't find anything relevant. Can you clarify what these checks are or point me in the right direction to find these checks?

Thanks for all the help you've provided so far.

JoelSpeed commented 2 years ago

i think the issue might be that you are redirecting to the /oauth2/sign_in page. This currently can't detect the traefik configuration as far as I'm aware. You'll need to use /oauth2/start instead which skips the login button and should be able to read the headers from traefik

niksauer commented 2 years ago

You'll need to use /oauth2/start instead [..]

Doesn't work for me unfortunately. Here's my setup:

apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
  name: traefik-internal-oauth-auth
  namespace: default
spec:
  forwardAuth:
    address: https://oauth-internal.XXX.com/oauth2/auth
    trustForwardHeader: true

---
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
  name: traefik-internal-oauth-errors
  namespace: default
spec:
  errors:
    status:
      - "401-403"
    service:
      name: oauth2-proxy
      port: 4180
    query: "/oauth2/start"

----
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
  name: traefik-security-headers
  namespace: default
spec:
  headers:
    # https://doc.traefik.io/traefik/middlewares/headers/
    frameDeny: true # X-Frame-Options: DENY
    contentTypeNosniff: true # X-Content-Type-Options: nosniff
    browserXssFilter: true # X-XSS-Protection: 1; mode=block
    forceSTSHeader: true
    stsSeconds: 63072000 # Strict-Transport-Security: max-age=63072000
    stsIncludeSubdomains: true # Strict-Transport-Security: max-age=63072000; includeSubDomains
    contentSecurityPolicy: frame-ancestors 'self' *.XXX.com

----
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: traefik-routes-default
  namespace: default
spec:
  entryPoints:
    - http
  routes:
    - match: Host(`apidev.XXX.com`) && PathPrefix(`/internal`)
      kind: Rule
      services:
        - name: XXX-web-api-canary
          port: 80
          kind: TraefikService
      middlewares:
        - name: traefik-security-headers
        - name: traefik-compress
        - name: traefik-internal-oauth-errors
        - name: traefik-internal-oauth-auth
lanmarti commented 2 years ago

@JoelSpeed I haven't had the time to investigate this further properly, but unless I'm reading things incorrectly, you've suggested /oauth2/start instead of /oauth2/sign_in earlier in this thread (https://github.com/oauth2-proxy/oauth2-proxy/issues/1297#issuecomment-933555649) already, which didn't seem to cause any significant changes (https://github.com/oauth2-proxy/oauth2-proxy/issues/1297#issuecomment-934130135).

@niksauer Considering Joel thinks the problem lies with some incorrect Traefik configuration, is there anything special about your Traefik setup? The only thing that is unusual for my setup (that I can think of) is that we run (nearly) all of our services on the same subdomain.

xoxys commented 2 years ago

I'm also using Traefik and running into the same issue. My Traefik config is pretty basic, using /oauth2/start also results in the Found link rendered instead of a proper redirect.

boutobza commented 2 years ago

The same issue for me as well even when i use /oauth2/start in the error middleware my use case is described here https://stackoverflow.com/questions/70497915/oauth2-proxy-returns-a-white-webpage-with-found-link-instead-of-the-provider-a

Any news about this issue please ?

xoxys commented 2 years ago

A workaround might be a custom theme file that is using <meta http-equiv="Refresh" content="1;url=/oauth2/start" />. Not tested yet, but that's how it works on Keycloak.

pathmissing commented 2 years ago

@xoxys Had a similar idea. One issue is that you lose any information about where to redirect after the login succeeds. If you use oauth2-proxy with multiple subdomains this might not be desired. What worked for me: Use a custom template (as described in #1507) and instead of adding a meta redirect, use javascript to set your current url as redirect target ("rd") and submit the form automatically. This assumes that your url remains unchanged.

This is an ugly hack but I currently don't see any better way. It seems to me that as long as traefik doesn't allow changing the status code from 401 to 302 with a custom middleware any redirects coming from oauth2-proxy will have no effect.

ADN182 commented 2 years ago

Hi, after further investigation, i found a "missing" part on my Traefik configuration. In fact i try to find oauth2 config to redirect to my website after login but no way always redirect behind oauth2 home page. After apply this paramerter in my traefik config it's finaly work's.

Indeed the problem is not on oauth2 config but if the forwarded-headers in traefik is not activated i will not fowarde the X-Fowarded-URI that permit to oauth2 to rediredt to your website after authentification.

I use that config for oauth2-proxy oauth2-proxy.cfg : email_domains = [ "*" ] upstreams = [ "static://202" ] reverse_proxy = "true" redirect_url = "https://mydomain/oauth2/callback" pass_access_token = "true" pass_authorization_header = "true" set_authorization_header = "true" set_xauthrequest = "true" cookie_domains = ".mydomain" whitelist_domains = ".mydomain" skip_provider_button = "true" cookie_secure = "true"

Traefik config (command) : --entryPoints.web.forwardedHeaders.insecure --entryPoints.websecure.forwardedHeaders.insecure

I hope that thing permit to help.

lanmarti commented 2 years ago

@ADN182 Glad to hear you got something working. How did you configure your ingress and middlewares? Could you share the manifests?

I've tested your config with the forwardedHeaders flag in combination with the middlewares and IngressRoute in my original post, but the issue is still there for me.

ADN182 commented 2 years ago

Hi @lanmarti,

Below my Middleware / IngressRoute Configuration. Don't forger i use the ForwardAuth with static upstreams configuration not this one ForwardAuth with 401 errors middleware

---
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
  name: auth-headers
spec:
  headers:
    sslRedirect: true
    stsSeconds: 315360000
    browserXssFilter: true
    contentTypeNosniff: true
    forceSTSHeader: true
    sslHost: mydomain.com
    stsIncludeSubdomains: true
    stsPreload: true
    frameDeny: true
---
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
  name: oauth2-auth-redirect
  namespace: traefik-system
spec:
  forwardAuth:
    address: 'https://auth.mydomain.com/'
    trustForwardHeader: true
    authResponseHeaders:
      - X-Auth-Request-Access-Token
      - Authorization
---
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: oauth2-proxy
spec:
  entryPoints:
    - websecure
  routes:
    - match: "Host(`auth.mydomain.com`) && PathPrefix(`/oauth2/`)"
      kind: Rule
      services:
        - kind: Service
          name: oauth2-proxy
          port: 80
      middlewares:
        - name: auth-headers
  tls:
    secretName: wildcard-mydomain.com-cert-tls
---
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: oauth2-proxy-redirect-app
spec:
  entryPoints:
    - websecure
  routes:
    - match: "Host(`traefik.mydomain.com`, `myapp.mydomain.com`) && PathPrefix(`/oauth2/`)"
      kind: Rule
      services:
        - kind: Service
          name: oauth2-proxy
          port: 80
      middlewares:
        - name: auth-headers
  tls:
    secretName: wildcard-mydomain.com-cert-tls
---
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: dashboard
spec:
  entryPoints:
  - web
  - websecure
  routes:
  - kind: Rule
    match: Host(`traefik.mydomain.com`) && (PathPrefix(`/dashboard`) || PathPrefix(`/api`))
    services:
    - kind: TraefikService
      name: api@internal
    middlewares:
       - name: oauth2-auth-redirect
  tls:
    secretName: wildcard-mydomain.com-cert-tls
lanmarti commented 2 years ago

@ADN182 thanks! I've manged to get it working using the static upstreams configuration and the forwardedHeaders flag. As I'm not completely sure what the consequences are of trusting forwarded headers in this setup, I've used forwardedHeaders.trustedIPs with the network range for my kubernetes pods instead of the more general forwardedHeaders.insecure.

While I'm still interested in getting the errors middleware to work, as that does not require a separate (sub)domain, my original issue is technically resolved now.

niksauer commented 2 years ago

Can this please be reopened since it does not work with the 401 errors middleware?

maltegrosse commented 2 years ago

running into the same issues.... using keycloak 17, traefik 2.7 rc2 and oauth proxy 7.2.1

looking at the examples at https://github.com/oauth2-proxy/oauth2-proxy/tree/master/contrib/local-environment , most of the yml files are older one year and as I followed few discussion here, within this year the traefik support changed by multiple PRs.

is it possible to provide an updated example? perfect would be the combination of keycloak and traefik.

Edited: skip_provider_button = "true" made the trick - without it gets suck in some redirects...

JoelSpeed commented 2 years ago

This project is run by volunteers in their spare time so we don't have a lot of time to keep things like the local environments up to date, these are typically community maintained (especially the keycloak and traefik examples), if you can get the local environment working and update it, a PR would be most welcome

maltegrosse commented 2 years ago

@JoelSpeed true, but as I am not an expert, I better not consider a PR :)

But I got a proof-of-concept for a dyndns service running, for anyone interested: https://github.com/benjaminbear/docker-ddns-server/issues/16#issuecomment-1098401651

(suggestions, feedback, adoptions and PRs for oauth2-proxy docs based on this example more than welcome :)

Art3mK commented 2 years ago

+1 for this. I've got auth working fine with static upstream configuration without errors middleware, but problem is that I'm trying to add allowed_groups to /oauth2/auth endpoint for forwardauth middleware. IIUC this can't work without redirects/errors middleware, as oauth2-proxy will just return 401 for all requests. Does anyone have any ideas how to embedd allowed_groups query param into forwardauth middleware with that static upstreams config?

Unfortunately I wasn't able to get auth working at all with errors middleware and querying /oauth2/start or /oauth2/sign_in on 401-403. I'm getting empty page with "Found" link and CSRF token mismatch error after I press that.

Does anyone got working setup for error middleware? Any help will be appretiated.

jonananas commented 2 years ago

I am using the hack above for now, i.e using a custom template for sign_in where I set rd=window.location. I copied the template files from https://github.com/oauth2-proxy/oauth2-proxy/tree/master/pkg/app/pagewriter, configure them with

      - "OAUTH2_PROXY_CUSTOM_TEMPLATES_DIR=/templates"

and just added

(function() {
  var inputs = document.getElementsByName('rd');
  for (var i = 0; i < inputs.length; i++)
    inputs[i].value = window.location;
})();

You need to correctly configure WHITELIST_DOMAINS as well. This makes all my subdomains work with the same oauth2-proxy callback.

I'm haven't taken the time to figure out how to set the Redirect parameter correctly, but hopefully someone will shed the light on that eventually :)

github-actions[bot] commented 2 years ago

This issue has been inactive for 60 days. If the issue is still relevant please comment to re-activate the issue. If no action is taken within 7 days, the issue will be marked closed.

copolycube commented 2 years ago

The hack from @jonananas (Thanks !) is still required to make this work.

mariaWitch commented 2 years ago

+1 that this be reopened as an active issue. This still hasn't been resolved in the over 3 years since issues with traefik were first reported.

JoelSpeed commented 2 years ago

I've reopened this, but, as this project is volunteer run, and none of the maintainers use the project anymore, nor do we use Traefik, this will need someone from the community to invest some time into fixing

protyposis commented 2 years ago

@JoelSpeed please excuse my slightly off-topic question, but does "the project" refer to oauth2-proxy in general? If the maintainers don't use it anymore, is there a recommended alternative?

JoelSpeed commented 2 years ago

The project refers to OAuth2 Proxy yes. This project has been a passion project for a long time, we still want to maintain it and provide guidance where we can but we can only do so when our schedules permit it. Typically my evenings and weekends I try to spend some time on the project but I can't as often as I would like and I don't get to do much on the code side anymore either.

I'm not sure about alternatives no. The real solution is to bring in some new maintainers but finding people willing and able to be a maintainer is difficult.

github-actions[bot] commented 1 year ago

This issue has been inactive for 60 days. If the issue is still relevant please comment to re-activate the issue. If no action is taken within 7 days, the issue will be marked closed.

copolycube commented 1 year ago

The latest workaround is still required to bypass this issue.

croneter commented 1 year ago

Please reopen this issue, dear @JoelSpeed, it's still a hassle if not outright impossible to use the traefik errors middleware - which is necessary if you want to control access per subdomain by allowed_groups

croneter commented 1 year ago

I am using the hack above for now, i.e using a custom template for sign_in where I set rd=window.location. I copied the template files from https://github.com/oauth2-proxy/oauth2-proxy/tree/master/pkg/app/pagewriter, configure them with

      - "OAUTH2_PROXY_CUSTOM_TEMPLATES_DIR=/templates"

and just added

(function() {
  var inputs = document.getElementsByName('rd');
  for (var i = 0; i < inputs.length; i++)
    inputs[i].value = window.location;
})();

You need to correctly configure WHITELIST_DOMAINS as well. This makes all my subdomains work with the same oauth2-proxy callback.

I'm haven't taken the time to figure out how to set the Redirect parameter correctly, but hopefully someone will shed the light on that eventually :)

This combination of traefik, oauth2-proxy and the need to control subdomains by allowed_groups is driving me nuts 😞.

@jonananas could you kindly explain where exactly you added this code in sign_in.html? I've got zero front-end-dev-experience

(function() {
  var inputs = document.getElementsByName('rd');
  for (var i = 0; i < inputs.length; i++)
    inputs[i].value = window.location;
})();

Thanks!

maltegrosse commented 1 year ago

@croneter for me it works when I enable login button… skip provider button ends up in not redirecting …. So I gave up and just show the button :)

copolycube commented 1 year ago

Hello, @croneter if it helps, this is how I am using the sign_in.hml trick using docker-compose: (PS: a more complete example is here, but it dates from a few month back https://gist.github.com/copolycube/dc6a52812fea19361f5aa5b0f3d514dd )

  traefik:
    image: traefik:latest
    container_name: "traefik"
    command:
      - --log.level=DEBUG
      - --api.dashboard=true
      [...]<depends on your needs....[...]
    networks:
      - internal
      - docker-proxy-internal

    labels:
      [...]<depends on your needs....[...]
      traefik.http.middlewares.oauth-chain.chain.middlewares: default-https,oauth-signin,oauth-verify

# https://oauth2-proxy.github.io/oauth2-proxy/docs/configuration/oauth_provider#gitlab-auth-provider
# https://alex.thom.ae/2020/01/12/deploy-traefik-prometheus-grafana-oauth2_proxy-docker-compose/
  oauth:
          #image: quay.io/pusher/oauth2_proxy:${OAUTH2_PROXY_VERSION}
    image: quay.io/oauth2-proxy/oauth2-proxy:v7.2.1
    container_name: "oauth"
    restart: always
    healthcheck:
      test: ["CMD", "wget", "--tries=1", "--spider", "http://oauth:4180/ping"]
      interval: 60s
      timeout: 10s
    labels:
      ai.ix.expose: 'true'
      traefik.enable: 'true'
      traefik.http.middlewares.oauth-verify.forwardAuth.address: http://oauth:4180/oauth2/auth
      traefik.http.middlewares.oauth-verify.forwardAuth.trustForwardHeader: 'true'
      traefik.http.middlewares.oauth-verify.forwardAuth.authResponseHeaders: "X-Auth-Request-User,X-Auth-Request-Email,Set-Cookie,X-Auth-Request-Access-Token,Authorization,X-Auth-Request-Redirect"
      traefik.http.middlewares.oauth-signin.errors.service: oauth@docker
      traefik.http.middlewares.oauth-signin.errors.status: '401'
      traefik.http.middlewares.oauth-signin.errors.query: /oauth2/sign_in
      traefik.http.routers.oauth.entrypoints: websecure
      traefik.http.routers.oauth.rule: Host(`oauth.${DOMAIN?err}`) || PathPrefix(`/oauth2`)
      traefik.http.routers.oauth.tls.certResolver: myresolver
      traefik.http.routers.oauth.service: oauth@docker
      traefik.http.services.oauth.loadbalancer.server.port: '4180'
    volumes:
      - "./oauth_templates:/templates"
    environment:
            # https://oauth2-proxy.github.io/oauth2-proxy/docs/configuration/overview/#environment-variables
      OAUTH2_PROXY_PROVIDER: gitlab
      OAUTH2_PROXY_EMAIL_DOMAINS: '*'
      OAUTH2_PROXY_GITLAB_GROUP: "${OAUTH2_PROXY_GITLAB_GROUP}"
      OAUTH2_PROXY_CLIENT_ID: "${OAUTH2_PROXY_CLIENT_ID?err}"
      OAUTH2_PROXY_CLIENT_SECRET: "${OAUTH2_PROXY_CLIENT_SECRET?err}"
      OAUTH2_PROXY_COOKIE_DOMAINS: "${DOMAIN?err}"
      OAUTH2_PROXY_COOKIE_REFRESH: '1h'
      OAUTH2_PROXY_COOKIE_SECURE: 'true'
      OAUTH2_PROXY_COOKIE_SECRET: "${OAUTH2_PROXY_COOKIE_SECRET?err}"
      OAUTH2_PROXY_FOOTER: '-'
      OAUTH2_PROXY_HTTP_ADDRESS: '0.0.0.0:4180'
      OAUTH2_PROXY_PASS_BASIC_AUTH: 'false'
      OAUTH2_PROXY_PASS_USER_HEADERS: 'true'
      OAUTH2_PROXY_REVERSE_PROXY: 'true'
      OAUTH2_PROXY_SET_AUTHORIZATION_HEADER: 'true'
      OAUTH2_PROXY_SET_XAUTHREQUEST: 'true'
      OAUTH2_PROXY_WHITELIST_DOMAIN: '.${DOMAIN?err}'
      OAUTH2_PROXY_WHITELIST_DOMAINS: '.${DOMAIN?err}'
      OAUTH2_PROXY_REDIRECT_URL: "https://oauth.${DOMAIN?err}/oauth2/callback"
      OAUTH2_PROXY_INSECURE_OIDC_SKIP_NONCE: 'false'
      # Customize login page - next four
      OAUTH2_PROXY_CUSTOM_TEMPLATES_DIR: "/templates"
      OAUTH2_PROXY_CUSTOM_SIGN_IN_LOGO: "/templates/logo.png"
      OAUTH2_PROXY_BANNER: "Welcome to this server ${DOMAIN?err}"
      OAUTH2_PROXY_FOOTER: "-"
    networks:
      - internal
      - docker-proxy-internal
jonananas commented 1 year ago

I am using the hack above for now, i.e using a custom template for sign_in where I set rd=window.location. I copied the template files from https://github.com/oauth2-proxy/oauth2-proxy/tree/master/pkg/app/pagewriter, configure them with

@jonananas could you kindly explain where exactly you added this code in sign_in.html? I've got zero front-end-dev-experience

(function() {
  var inputs = document.getElementsByName('rd');
  for (var i = 0; i < inputs.length; i++)
    inputs[i].value = window.location;
})();

Sure, have a look at https://github.com/jonananas/traefik-oauth2-proxy/blob/7f6327ef23ac3be222d2b2516baf271efb9f35b3/oauth_templates/sign_in.html#L69.

alex0ptr commented 1 year ago

My team ran into a similar issue and tried solutions from here. I'm leaving my solution here for others who end up here too:

  1. Instead of calling any of the /oauth2/* endpoints we just use / for forward auth. As the documentation states:

    All other endpoints will be proxied upstream when authenticated.

  2. Now define an upstream that returns 2xx with --upstream static://204.
  3. Finally enable --skip-provider-button.

Now traefik will do forward auth against / and when the user is unauthenticated we get an immediate redirect. If the user is authenticated the proxy responds with 204 and traefik will call the real service for the site.

This is kinda obvious if you read the documentation carefully. The oauth2/auth is really only suitable for nginx and I think this how my team ended up here.

Hope that helps.

maxlerebourg commented 1 year ago

I am using the hack above for now, i.e using a custom template for sign_in where I set rd=window.location. I copied the template files from https://github.com/oauth2-proxy/oauth2-proxy/tree/master/pkg/app/pagewriter, configure them with

@jonananas could you kindly explain where exactly you added this code in sign_in.html? I've got zero front-end-dev-experience

(function() {
  var inputs = document.getElementsByName('rd');
  for (var i = 0; i < inputs.length; i++)
    inputs[i].value = window.location;
})();

Sure, have a look at https://github.com/jonananas/traefik-oauth2-proxy/blob/7f6327ef23ac3be222d2b2516baf271efb9f35b3/oauth_templates/sign_in.html#L69.

This hack could be done in the OAUTH2_PROXY_FOOTER environnement variable like :

OAUTH2_PROXY_FOOTER = "<script>(function(){var rd=document.getElementsByName('rd');for(var i=0;i<rd.length;i++)rd[i].value=window.location.toString().split('/oauth2')[0]})()</script>"
curlup commented 5 months ago

I was getting all the same issues - and also getting 404 as in #1355 when I tried a different setup.

Here what worked for me (more or less I think what @alex0ptr suggested):

  1. Only forward auth middleware forwarding to /oauth2/ (no /auth and no middleware errors 40x redirect with ?rd={url} - rd just works OOB) - this is so you dont get "Found." thing.
  2. OAUTH2_PROXY_UPSTREAMS=static://200 (note plural UPSTREAMS, coz it's multival env var. And note 200 not 204 so less dumb errors "204 doznt allow body" in logs) - this is so you don't get 404 as in #1355
  3. OAUTH2_PROXY_REVERSE_PROXY=true - coz we're behind traefik
  4. OAUTH2_PROXY_SKIP_PROVIDER_BUTTON=true - so we get redirect right away without Oauth2-proxy login form first.

Note that if you wanna do access control via /oauth2/auth?allowed_groups=X you can not do just /oauth/?allowed_groups in the same forward auth, but you can do a second forwardAuth middleware with /oauth2/auth?allowed_groups=X and it will work (with an overhead of two auth requests per user request, but still).

github-actions[bot] commented 3 months ago

This issue has been inactive for 60 days. If the issue is still relevant please comment to re-activate the issue. If no action is taken within 7 days, the issue will be marked closed.

niksauer commented 3 months ago

Still not fixed :(

github-actions[bot] commented 1 month ago

This issue has been inactive for 60 days. If the issue is still relevant please comment to re-activate the issue. If no action is taken within 7 days, the issue will be marked closed.

niksauer commented 1 month ago

Comment to not close