Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multiple Requests cause CSRF overwrite #113

Closed
thomseddon opened this issue Apr 24, 2020 · 6 comments
Closed

Multiple Requests cause CSRF overwrite #113

thomseddon opened this issue Apr 24, 2020 · 6 comments
Labels
bug Something isn't working

Comments

@thomseddon
Copy link
Owner

thomseddon commented Apr 24, 2020

As raised by @bekoeppel in #31 (comment) there is an issue whereby subsequent requests will cause CSRF cookies to be overwritten:

I got the same errors and was able to reproduce it as follows:

  • traefik-forward-auth configured in Host Mode
  • Tab A: open an application that makes requests to its backend every second to refreshing its data
  • Wait until the authentication session expires
  • Tab A keeps making requests, which fail because the session expired. From my understanding, this is issuing new _forward_auth_csrf cookies every second
  • Tab B: open another application, go through the OIDC login to the consent screen. When I was redirected back to my auth backend, I got Not authorized and saw in the log Error validating csrf cookie: CSRF cookie does not match state.

Closing Tab A, so that it would not make requests and issue new _forward_auth_csrf cookies then allowed me to log in to the second application in tab B.

I'm opening this issue to track possible solutions, my initial thoughts are:

  • Add random string to each CSRF cookie name, which is also prepended to the state value so the server knows what cookie to be looking for
  • Persist CSRF cookie values on the server

I will have a look to see what other approaches have been adopted elsewhere

@thomseddon thomseddon added the bug Something isn't working label Apr 24, 2020
@tekand
Copy link

tekand commented May 26, 2020

I experience the same issue, with the exception that it also happens when the application you load on Tab A and Tab B is the same. I think the biggest problem with the behavior is that you cannot 'fix' it by refreshing the browser tab, it needs to be closed completely. Once you have several applications running under the same auth host, it is a daunting task. Of course it is possible to increase the $LIFETIME, but I believe this is only a workaround.

@thomseddon
Copy link
Owner Author

Good point, I've thought about this a little and my current thinking is to append a short random string to the CSRF cookie name, for example _forward_auth_csrf_9867118a.

I'll need to do a little more reading to ensure this is viable.

@tekand
Copy link

tekand commented May 27, 2020

Sounds good to me. Let me know if you need any beta testing. :)

@tekand
Copy link

tekand commented May 27, 2020

Or a different idea is to send 401 to non-authorized non-html requests instead of redirecting to the login page. Like mesosphere did in their fork.

https://github.com/mesosphere/traefik-forward-auth/blob/870f90429ea24e4afe2f94697a62c56d9858d114/internal/server.go#L351

@mwitkow
Copy link

mwitkow commented Sep 2, 2020

It seems the CSRF validation on a different tab is something that is easy to hit when running Home Assistant behind Traefik+Forward Auth (see here). It seems that Home Assistant single page app uses websockets, and on pressing "Retry" it seems to do something like you describe with multiple tabs. I get prompted to choose a Google account and then get the "Not authorized" error due to CSRF state mismatch

Sep 02 04:08:41 wiregate docker[1864508]: time="2020-09-02T08:08:41Z" level=warning msg="Error validating csrf cookie" csrf_cookie="_traefik_forward_auth_csrf=21c8ede5e95659c2f92afef8c050f906" error="CSRF cookie does not match state" handler=AuthCallback host=auth.example.com method=GET proto=https rule=default source_ip=X.Y.Z.Z uri="/_oauth?state=4c4d9f06447300690dc68a7aa7c41da9%3Agoogle%3Ahttps%3A%2F%2Fhome.example.com%2F&code=4%2F3wHkAqCsNYSeyL6Zhnm4pq_-xweJ-EDaY2oQGOGEMOXHsYFCIwmd8OZejVD7lFmJPbx0LpJsQFhoLnLcIITZLMM&scope=email+profile+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile+openid+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email&authuser=0&prompt=none"

IIRC, having worked on OAuth2 flows before, the CSRF cookie id was the solution we went with as well.

@thomseddon
Copy link
Owner Author

Now fixed in #187 & pegged for release in 2.3

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants