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

Always try to clear CSRF cookie

Open thomseddon opened this issue 3 years ago • 13 comments

This should be done immediately after extracting the cookie

thomseddon avatar Oct 15 '20 20:10 thomseddon

Just experienced a mystifying issue with the CSRF cookie complaining. Incognito window worked fine, but I couldn't get my browser state to login for ~ 10 minutes. I tried clearing cookies on the only domain I could get to (sso.mydomian.com - points at the forwardauth container), but it seemed like the cookie was cached at (myapp.mydomain.com), since each new request there had a csrf cookie attached.

  • Navigate to myapp.mydomain.com, in network devtools, this request had: Cookie: _forward_auth_csrf=xxxx
  • Redirect to IDP and login
  • Redirect back to sso.mydomain.com, get Not Authorized in the browser
  • Error message in forward auth container:
time="2020-12-30T07:18:32Z" level=warning msg="Error validating csrf cookie" csrf_cookie="_forward_auth_csrf=xxx" error="CSRF cookie does not match state" handler=AuthCallback host=sso.mydomain.com method=GET proto=https rule=default source_ip=1.2.3.4 uri="/__oauth__?code=xxx&state=yyy%3Aoidc%3Ahttps%3A%2F%2Fmyapp.mydomain.com%2F"

Then suddenly it started working again. Not sure what triggered the change 🤷‍♂️ But wanted to report since it seemed somewhat related to a "bad" CSRF cookie

EDIT: Actually, I think I know what this may have been. My staging domain is a subdomain of my primary domain (staging.sso.mydomain.com). The forward auth csrf cookie was not being set to a different name on staging / production, and that + domain collision at sso.mydomain.com may have been part of the contributing factor here... (I had the same problem with the primary cookie at one point, and did not think to rename the csrf cookie until now).

EDIT2: I actually think this may have been entirely my fault. I am pretty sure I briefly had a bad DNS record that was sending prod traffic to staging 😑 I suspect when that record got cleaned up and propagated, things resolved. Probably worth disregarding 😄

colearendt avatar Dec 30 '20 07:12 colearendt

I am getting a similar error, works in a new session but fails when already logged in:

time="2020-12-30T21:13:47Z" level=warning msg="Error validating csrf cookie" csrf_cookie="_forward_auth_csrf=<redacted>" error="CSRF cookie does not match state" handler=AuthCallback host=auth.sub.domain.com method=GET proto=https rule=default source_ip=<my public ip> uri="/_oauth?state=<redacted>%2F&code=<redacted>&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"
tfa:
    image: thomseddon/traefik-forward-auth:2-arm
    environment:
      - PROVIDERS_GOOGLE_CLIENT_ID=${GOOGLE_CLIENT_ID}
      - PROVIDERS_GOOGLE_CLIENT_SECRET=${GOOGLE_CLIENT_SECRET}
      - SECRET=${AUTH_JWT_SECRET}
      - COOKIE_DOMAIN=${BS_URL} #sub domain
      - AUTH_HOST=auth.${BS_URL}
      - LOG_LEVEL=${LOG_LEVEL}
      - WHITELIST=${WHITELIST}
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.tfa.rule=Host(`auth.${BS_URL}`)"
      - "traefik.http.routers.tfa.entrypoints=websecure"
      - "traefik.http.routers.tfa.service=tfa"
      - "traefik.http.routers.tfa.tls.certresolver=bs"
      - "traefik.http.middlewares.tfa.forwardauth.address=http://tfa:4181"
      - "traefik.http.middlewares.tfa.forwardauth.authResponseHeaders=X-Forwarded-User"
      - "traefik.http.services.tfa.loadbalancer.server.port=4181"
      - "traefik.http.routers.tfa.middlewares=tfa"

This works great in icognito, fails in already logged in session.

whizzzkid avatar Dec 30 '20 21:12 whizzzkid

That sounds to me like a cookie issue. I have seen it when my cookie domain or auth host were wrong. It can also be related to SSL if you are setting insecure cookies - I.e. if a proxy is terminating SSL and traefik-forward-auth is listening HTTP. Make sure to set the X-Forwarded-Porto: https header in cases like this.

Alternatively I would debug the auth request that returns a set-cookie response and then the “Not Authorized” request and what cookies are set for it / in your browser. There is likely a mismatch.

Hope that helps!

Sent from my iPhone

On Dec 30, 2020, at 4:23 PM, Nishant Arora [email protected] wrote:



I am getting a similar error, works in a new session but fails when already logged in:

time="2020-12-30T21:13:47Z" level=warning msg="Error validating csrf cookie" csrf_cookie="_forward_auth_csrf=" error="CSRF cookie does not match state" handler=AuthCallback host=auth.sub.domain.com method=GET proto=https rule=default source_ip= uri="/_oauth?state=%2F&code=&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"

tfa: image: thomseddon/traefik-forward-auth:2-arm environment: - PROVIDERS_GOOGLE_CLIENT_ID=${GOOGLE_CLIENT_ID} - PROVIDERS_GOOGLE_CLIENT_SECRET=${GOOGLE_CLIENT_SECRET} - SECRET=${AUTH_JWT_SECRET} - COOKIE_DOMAIN=${BS_URL} #sub domain - AUTH_HOST=auth.${BS_URL} - LOG_LEVEL=${LOG_LEVEL} - WHITELIST=${WHITELIST} labels: - "traefik.enable=true" - "traefik.http.routers.tfa.rule=Host(auth.${BS_URL})" - "traefik.http.routers.tfa.entrypoints=websecure" - "traefik.http.routers.tfa.service=tfa" - "traefik.http.routers.tfa.tls.certresolver=bs" - "traefik.http.middlewares.tfa.forwardauth.address=http://tfa:4181" - "traefik.http.middlewares.tfa.forwardauth.authResponseHeaders=X-Forwarded-User" - "traefik.http.services.tfa.loadbalancer.server.port=4181" - "traefik.http.routers.tfa.middlewares=tfa"

This works great in icognito, fails in already logged in session.

— You are receiving this because you commented. Reply to this email directly, view it on GitHubhttps://github.com/thomseddon/traefik-forward-auth/issues/198#issuecomment-752762816, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AFQBVVUWETI7734IUCCYAR3SXOK6RANCNFSM4SSOAPCQ.

colearendt avatar Dec 30 '20 23:12 colearendt

I am having this same issue. It seems to be after a good 24 hours before users will see the issue. I am using AUTH_HOST and have double checked all the parameters are correct. Basically results in CSRF cookie does not match state error

snowzach avatar Feb 18 '21 21:02 snowzach

Not a smoking gun yet but it seems to happen only in Firefox and possibly related to having multiple Google accounts logged in.

snowzach avatar Feb 22 '21 19:02 snowzach

I doubt this will help but FWIW:

This returns 401:
https://myauthhost.domain.net/_oauth?state=3ec2e130e45526c0e7f372621d4183a4:google:https://thingImAuthingTo.domain.net/&code=4/JIBBERISHAUTHSTUFFS&scope=email%20profile%20openid%20https://www.googleapis.com/auth/userinfo.profile%20https://www.googleapis.com/auth/userinfo.email&authuser=2&hd=domain.com&prompt=none

I can see the CSRF cookie clearly does not match the state value in the URL above. Happy to do a little more research if someone can hint me what to look for.

Note, my authhost is domain.net my email domain is domain.com (which is in the hd parameter of the URL)

snowzach avatar Feb 22 '21 19:02 snowzach

Could it be that when you try to initially access the site, it sets the cookie but then redirects you to login, the login then sets a new cookie and after login it redirects you back to the original site which looks for the original cookie that does no longer match?

Perhaps after a login we need to clear the state value for the original login cookie?

time="2021-02-23T14:57:53Z" level=debug msg="Authenticating request" cookies="[domain_forward_auth_csrf=f583fc2753c7af47d6bd3176920a940d]" handler=Auth host=protected.domain.net method=GET proto=https rule=default source_ip=172.20.0.20 uri=/
time="2021-02-23T14:57:53Z" level=debug msg="Set CSRF cookie and redirected to provider login url" csrf_cookie="domain_forward_auth_csrf=a0a3c823122e4837b9c82f00f701c783; Path=/; Domain=domain.net; Expires=Wed, 24 Feb 2021 02:57:53 GMT; HttpOnly; Secure" handler=Auth host=protected.domain.net login_url="https://accounts.google.com/o/oauth2/auth?client_id=945201490766-n2g8007g10cpnqeh6e1q3huo2i0kpat8.apps.googleusercontent.com&prompt=select_account&redirect_uri=https%3A%2F%2Fauth.domain.net%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=a0a3c823122e4837b9c82f00f701c783%3Agoogle%3Ahttps%3A%2F%2Fprotected.domain.net%2F" method=GET proto=https rule=default source_ip=172.20.0.20 uri=/
time="2021-02-23T14:57:54Z" level=debug msg="Authenticating request" cookies="[domain_forward_auth_csrf=a0a3c823122e4837b9c82f00f701c783]" handler=Auth host=protected.domain.net method=GET proto=https rule=default source_ip=172.20.0.20 uri=/pwa-worker.js
time="2021-02-23T14:57:54Z" level=debug msg="Set CSRF cookie and redirected to provider login url" csrf_cookie="domain_forward_auth_csrf=194fbda8cf424dd18275495cb423c489; Path=/; Domain=domain.net; Expires=Wed, 24 Feb 2021 02:57:54 GMT; HttpOnly; Secure" handler=Auth host=protected.domain.net login_url="https://accounts.google.com/o/oauth2/auth?client_id=945201490766-n2g8007g10cpnqeh6e1q3huo2i0kpat8.apps.googleusercontent.com&prompt=select_account&redirect_uri=https%3A%2F%2Fauth.domain.net%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=194fbda8cf424dd18275495cb423c489%3Agoogle%3Ahttps%3A%2F%2Fprotected.domain.net%2Fpwa-worker.js" method=GET proto=https rule=default source_ip=172.20.0.20 uri=/pwa-worker.js
time="2021-02-23T14:57:55Z" level=debug msg="Handling callback" cookies="[domain_forward_auth_csrf=194fbda8cf424dd18275495cb423c489]" handler=AuthCallback host=auth.domain.net method=GET proto=https rule=default source_ip=172.20.0.2 uri="/_oauth?state=a0a3c823122e4837b9c82f00f701c783:google:https://protected.domain.net/&code=4/0AY0e-g5KgF7b0rCDjCPk3faGMP0Dh7LvnyX9HGDenazvgG5aFxO4rfqy1hrgIwEG8HQLBQ&scope=email%20profile%20https://www.googleapis.com/auth/userinfo.profile%20https://www.googleapis.com/auth/userinfo.email%20openid&authuser=1&hd=domain.com&prompt=none"
time="2021-02-23T14:57:55Z" level=warning msg="Error validating csrf cookie" csrf_cookie="domain_forward_auth_csrf=194fbda8cf424dd18275495cb423c489" error="CSRF cookie does not match state" handler=AuthCallback host=auth.domain.net method=GET proto=https rule=default source_ip=172.20.0.2 uri="/_oauth?state=a0a3c823122e4837b9c82f00f701c783:google:https://protected.domain.net/&code=4/JIBBERISH&scope=email%20profile%20https://www.googleapis.com/auth/userinfo.profile%20https://www.googleapis.com/auth/userinfo.email%20openid&authuser=1&hd=domain.com&prompt=none"

snowzach avatar Feb 23 '21 15:02 snowzach

Yeah, it looks like when you try to redirect the second time presumably from the middleware being on the auth endpoint, it sets a new cookie but the callback from Google comes back with the first state value and not the state you used when you redirect the second time.

snowzach avatar Feb 23 '21 15:02 snowzach

Could you potentially fix this by not setting a new cookie when the host it is hitting is the AUTH_HOST?

snowzach avatar Feb 23 '21 15:02 snowzach

Okay... I am going farther down the rabbit hole here.... The issue appears to be that the service I am protecting behind the proxy (Jitsi Meet in this case) has a Progressive Web App worker. When I attempt to access the web page, it works correctly. The problem is that the browser immediately tries to also connect the progressive web-app javascript. This generates another request which is then also redirected by traefik-forward-auth but it also changes my cookie again such that when the original web request comes back, it does not match. I think the correct way forward here will to be to whitelist the progressive web app javascript so it does not hit TFA.

Edit: Confirmed... that fixed it...

snowzach avatar Feb 23 '21 16:02 snowzach

I also stumbled about the problem @snowzach mentioned: Firefox and Safari (both in Non-incognito-mode) seem to request additional resources from the secured domain, without being explicitly asked for, so the CSRF cookie is being overridden and the returning original request from upstream OIDC provider will fail with

time="2021-04-06T13:45:56Z" level=warning msg="Error validating csrf cookie" csrf_cookie="_forward_auth_csrf=<RETRACTED>" error="CSRF cookie does not match state" handler=AuthCallback host=<RETRACTED> method=GET proto=https rule=default source_ip=10.0.0.2 uri="/_oauth?code=<RETRACTED>&state=<RETRACTED>"

Chrome is working fine though.

slinstaedt avatar Apr 06 '21 14:04 slinstaedt

Hi, I also had this issue, which thanks to @snowzach and @slinstaedt I realized my config was working fine on a browser other than firefox, but I also realized that the latest tag is a lot more recent than the tag 2 which I was using before, not sure which version it contains, so I tried it out and I don't have this issue anymore.

So if this comment can help it seems the tag latest is different than all the latest version tagged, unlike what is usually used with docker image.

DameniMilo avatar Apr 07 '21 07:04 DameniMilo

Using latest image instead of 2 did the trick for me. With the 2 image I have infinite loop redirecting

SebastienTolron avatar Aug 20 '21 08:08 SebastienTolron