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

Getting csrf_attack exception in callback but only on Safari and Safari Mobile #86

Open
nicolasblanco opened this issue Oct 22, 2021 · 12 comments
Labels

Comments

@nicolasblanco
Copy link

Hello folks.

Right now I'm getting:

%Ueberauth.Failure.Error{
      message: "Cross-Site Request Forgery attack",
      message_key: :csrf_attack
    }

but only on Safari and Safari Mobile.

Everything is working fine on Chrome and Firefox.
I'm trying to inspect what is done differently in this browser...

@nicolasblanco
Copy link
Author

I tried to debug the issue and basically it looks like the strategy is writing the ueberauth.state cookie but after the Google redirection, the private function get_state_cookie(conn) in Ueberauth.Strategy is returning nil.

It looks like the server is not getting everything for some reasons.

The weird thing is that it's only happening on my side with latest Safari and Safari Mobile.

@Hanspagh Hanspagh added the bug label Oct 25, 2021
@fedme
Copy link

fedme commented Oct 27, 2021

I am seeing the same problem sporadically but I can't pinpoint it to a specific browser/os. @nicolasblanco were you able to find the exact cause of the issue?

@kayuapi
Copy link

kayuapi commented Nov 9, 2021

I faced similar issue in chrome today, the code was working fine last month.

Then I tried using https in my dev environment and makes the GOOGLE_REDIRECT_URI to point to https and it worked again.

@nicolasblanco
Copy link
Author

I faced similar issue in chrome today, the code was working fine last month.

Then I tried using https in my dev environment and makes the GOOGLE_REDIRECT_URI to point to https and it worked again.

On my side I was getting this exception both on local dev and on production where all my servers and redirect links are on HTTPS, so it's not only related to HTTPS in my opinion.

Also, I'm getting this exception all times and not sporadically on Safari and Safari Mobile.

@aj-foster
Copy link
Contributor

If anyone is still experiencing this issue, I would be curious to know whether the browser is sending the ueberauth.state_param cookie. Specifically, is the SameSite behavior of the cookie preventing it from being sent during the callback? This could explain the differences across browsers and when, for example, redirects are involved.

@mithereal
Copy link

mithereal commented Sep 26, 2022

still have this issue, tried changing samesite to none; strict but still had the same issues, fails in all browsers, the default on most browsers changed from none to lax by default so im thinking the problem has something to do with that samesite=Lax is appended to the set-cookie header

@aj-foster
Copy link
Contributor

If you have the opportunity, can you open the network inspector (in the settings, "preserve logs"), and copy the Set-Cookie response header here? That would help us diagnose this.

Changing SameSite to None may not work if your endpoint thinks it is operating over http instead of https. Plug will automatically set the "Secure" attribute on the cookie accordingly. This can happen, for example, if you terminate SSL and do not have a header informing Plug of the original protocol.

@mithereal
Copy link

heres the entire auth flow
GET /auth/github HTTP/2
Host: localhost:4000
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:105.0) Gecko/20100101 Firefox/105.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,/;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Cookie: __session_key=SFMyNTY.g3QAAAABbQAAAAtfY3NyZl90b2tlbm0AAAAYTWkwTmZFblZjY1RxUUZteG5zM0hBT0M2.SzEZMNeVO2tZ_mbesbYqxo-6Fj7a7lkvmotEt2-YH2s
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: none
Sec-Fetch-User: ?1
TE: trailers

HTTP/2 302 Found
cache-control: max-age=0, private, must-revalidate
content-length: 201
date: Tue, 27 Sep 2022 02:08:41 GMT
location: https://github.com/login/oauth/authorize?client_id=Iv1.2f81a316e8262411&redirect_uri=&response_type=code&scope=user%3Aemail
server: Cowboy
x-request-id: FxiVkzxMn5QMd6IAADKB
X-Firefox-Spdy: h2

GET /login/oauth/authorize?client_id=Iv1.2f81a316e8262411&redirect_uri=&response_type=code&scope=user%3Aemail HTTP/2
Host: github.com
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:105.0) Gecko/20100101 Firefox/105.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,/;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Cookie: logged_in=yes; _device_id=5fbf2f360cab16a32d6a8f8417b44291; _octo=GH1.1.1513978513.1647913957; _gh_sess=%2FjlXawGKZuualvO4NI4LyeRgOjm7wtoSoHUxiqhAAAhAUPz4NHxhFFvp5VQvc5hZ9pU73uJgh7xgphi9lKXbba%2BtzesBHPgNnzku5XF3OlLFHVdNpoyHNB4W08L2Un9DmIQOnd2o7frou5lu1TnlOPMvFaST10kRahBigF1SBARisKtTnt04HtKbuR0in0f9eLHI8BUPLyDoXa%2FVUZvHbP0%2Fbt3QaM3qpynk1Mmr4UvmoMdDV4S1BgwJvi0UX7jFOSsDPtxVuqxrMZHNYgqQLWtgQQAmk1Hf9rueeLr7LuCICjpZPfijfQIDDxni930cz49C%2BOXAh4ExxoV7%2BGIphjaKCCKj7zXN5ar9oyMEj%2FMupETTlo9VtOoRuZnitBevIExYAE%2BCog9TFXL825aVWpcdrGUUvOtdP2No19%2FEvhTN0O7aD5NIiVsdFwkEW3coVuDtOsXaJoSjJjzW%2FoWgH2AJY00KirMCdkGHkoHGo%2FOsRaqC7zVCqGu5vZUF%2Ba1Gtq3ua4qpOQhO9EZjO2Uv2Ey0V2GaA4ihURZmUw8zfvQ7eLhvlBmL3o%2BEO6hU1m0dr0NCp7Rp3sDBUHV9tIdO8uW1q75ko3RnPsowdyu4N%2BFNAliZD2MRzwlaqMgmJw3CHQTWPdtkL8B08XsnHdeGX2GofffAShfxRGI3TzQmDmPCrl30fISNKYbArfvduIHp%2Byr6BUninrAwbTA7MatrA%2FfcFc6UkgROIke4nE1QbY0TXo4rmDE%2Bxoj%2BN%2F%2FjkIUj2yzqFw%3D%3D--sy1j6t86FZihZ579--RB9MLS28G1QEPFbXrriIFg%3D%3D; preferred_color_mode=dark; tz=America%2FPhoenix; user_session=nW1v9Ibh_RL3-OPoW5NBb42bbgBKSELFrsXT-rNaEICs0MtG; tz=America%2FPhoenix; color_mode=%7B%22color_mode%22%3A%22dark%22%2C%22light_theme%22%3A%7B%22name%22%3A%22light%22%2C%22color_mode%22%3A%22light%22%7D%2C%22dark_theme%22%3A%7B%22name%22%3A%22dark%22%2C%22color_mode%22%3A%22dark%22%7D%7D; dotcom_user=xxxx; has_recent_activity=1
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: none
Sec-Fetch-User: ?1
TE: trailers

HTTP/2 302 Found
server: GitHub.com
date: Tue, 27 Sep 2022 02:08:42 GMT
content-type: text/html; charset=utf-8
location: https://localhost:4000/auth/github/callback?code=9898f57bd64bc1506454
cache-control: no-cache
set-cookie: has_recent_activity=1; path=/; expires=Tue, 27 Sep 2022 03:08:41 GMT; secure; HttpOnly; SameSite=Lax
_gh_sess=hfYl0QqOWujjGQFARv9%2B63S1vJUH7MyyQD9s0yMq6gy9006E274XaADc2us052bDa6sl3qFNpoSo8T0XvmXPiNnfrcpDCoggLHbzIwA4kApC4T%2FLBNAVMBzC40pXYa1fcXZKiBxFXi%2FyCT60eNeux2uDUWMWf%2BX3uMOLwoJ9zgZZp%2F%2BpiGD7SZsqMVajqeYf7bcoD6iVN0TQgyhvv%2FfBdPiUgVcMo%2FYMZsn7rPj6%2FoC0wbUgFiLrHSc9OAZtDYrXS%2BO3pySZWRkXB4bT3hhIIqPHg7Q7tdEtncTyHzw6GBWcwbg4Rf6FstEoMvYNejbBMc%2FP7R49vovIV8lwOoEg2HPNTdYd2jw8D%2BoxMjHxrUkJ0q6GLFrKKcUCSwtosxjEUhru2%2BKIyuAAx9KklBcaMiyA%2F929rwQy4XUO8cT7cpJfZbuaMcpaGUBZ4K6Aplsqm1nYDFPeod3k48EgMLC9se0ROtmkwwgXLRq6tHKMvRea%2BAGkghBZ4LKb0OAl9jw4%2BF%2F3lnKqQqJsijBlPPcgEXbISVr7GdDE6eOdOPMsgpVpetAo6UiIN%2Bk9nnfvHaPAX8v2GizRW3ddrFVPIhqLALkjYEJ63NQQwdhgYkf9qJG4KphLNo1wNedRRm7asYtzZHLkEKdJH3pYnqvbKg1OQk%2FCbB%2BLLrFi9grjjSSlU56Pgsr6sBxEPCdRaRJ%2FV6LdkjQ1HtSS%2Btne0Px53bHJ%2Ftsi09%2FPcQgTzVgEpjqBdO7fgk%2BO2ZapSUGziY0Kt9yazTyAjw%3D%3D--nhCYGi5RFwDxND%2FK--YikD4xFKOjC%2BPu2BBw3elQ%3D%3D; path=/; secure; HttpOnly; SameSite=Lax
strict-transport-security: max-age=31536000; includeSubdomains; preload
x-frame-options: sameorigin
x-content-type-options: nosniff
x-xss-protection: 0
referrer-policy: origin-when-cross-origin, strict-origin-when-cross-origin
expect-ct: max-age=2592000, report-uri="https://api.github.com/_private/browser/errors"
content-security-policy: default-src 'none'; base-uri 'self'; block-all-mixed-content; child-src github.com/assets-cdn/worker/ gist.github.com/assets-cdn/worker/; connect-src 'self' uploads.github.com objects-origin.githubusercontent.com www.githubstatus.com collector.github.com raw.githubusercontent.com api.github.com github-cloud.s3.amazonaws.com github-production-repository-file-5c1aeb.s3.amazonaws.com github-production-upload-manifest-file-7fdce7.s3.amazonaws.com github-production-user-asset-6210df.s3.amazonaws.com cdn.optimizely.com logx.optimizely.com/v1/events .actions.githubusercontent.com wss://.actions.githubusercontent.com online.visualstudio.com/api/v1/locations github-production-repository-image-32fea6.s3.amazonaws.com github-production-release-asset-2e65be.s3.amazonaws.com insights.github.com wss://alive.github.com; font-src github.githubassets.com; form-action 'self' github.com gist.github.com objects-origin.githubusercontent.com; frame-ancestors 'self'; frame-src render.githubusercontent.com viewscreen.githubusercontent.com notebooks.githubusercontent.com; img-src 'self' data: github.githubassets.com identicons.github.com github-cloud.s3.amazonaws.com secured-user-images.githubusercontent.com/ github-production-user-asset-6210df.s3.amazonaws.com customer-stories-feed.github.com spotlights-feed.github.com *.githubusercontent.com; manifest-src 'self'; media-src github.com user-images.githubusercontent.com/ secured-user-images.githubusercontent.com/; script-src github.githubassets.com; style-src 'unsafe-inline' github.githubassets.com; worker-src github.com/assets-cdn/worker/ gist.github.com/assets-cdn/worker/
vary: X-PJAX, X-PJAX-Container, Turbo-Visit, Turbo-Frame, Accept-Encoding, Accept, X-Requested-With
x-github-request-id: B9EC:7635:128D3B7:1B88D70:63325AA6
X-Firefox-Spdy: h2

GET /auth/github/callback?code=9898f57bd64bc1506454 HTTP/2
Host: localhost:4000
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:105.0) Gecko/20100101 Firefox/105.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,/;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Cookie: __session_key=SFMyNTY.g3QAAAABbQAAAAtfY3NyZl90b2tlbm0AAAAYTwTmZFblZjY1RxUUZteG5zM0hBT0M2.SzEZMNeVO2tZ_mbesbYqxo-6Fj7a7lkvmotEt2-YH2s
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: none
Sec-Fetch-User: ?1
TE: trailers

HTTP/2 302 Found
cache-control: max-age=0, private, must-revalidate
content-length: 145
content-type: text/html; charset=utf-8
cross-origin-window-policy: deny
date: Tue, 27 Sep 2022 02:08:42 GMT
location: /
server: Cowboy
x-content-type-options: nosniff
x-download-options: noopen
x-frame-options: SAMEORIGIN
x-permitted-cross-domain-policies: none
x-request-id: FxiVk1HsPB-s0ZQAABmJ
x-xss-protection: 1; mode=block
set-cookie: __session_key=SFMyNTY.g3QAAAACbQAAAAtfY3NyZl90b2tlbm0AAAAYTWkwTmZFblZjY1RxUUZteG5zM0hBT0M2bQAAAA1waG9lbml4X2ZsYXNodAAAAAFtAAAABWVycm9ybQAAAEBGYWlsZWQgdG8gYXV0aGVudGljYXRlLiBUaGUgY29kZSBwYXNzZWQgaXMgaW5jb3JyZWN0IG9yIGV4cGlyZWQu.2Orzj45gMW4Gikb8W--pPL0LLNAxI3i7BuOED9-zhA0; path=/; secure; HttpOnly
ueberauth.state_param=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT; max-age=0; secure; HttpOnly
X-Firefox-Spdy: h2

@aj-foster
Copy link
Contributor

(Note: the above requests show a request for GitHub OAuth, not Google. Still going to look through it.)

Looking at the above, and searching specifically for ueberauth.state_param, I see the following in the last request:

ueberauth.state_param=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT; max-age=0; secure; HttpOnly

This is where Ueberauth clears the state cookie after the callback is complete (regardless of success or failure). I don't see where this state cookie is being set during the request phase. If you go to the network tab and look at the original request to /auth/github, under the Cookies tab, the browser will likely show you the ueberauth.state_param cookie with a warning about why it isn't being set. You may need to check a box to display rejected cookies.

Sidenote: for safety, I recommend logging out of the GitHub session you used to generate the above trace, just in case someone tries to use your session cookies for something nefarious.

@mithereal
Copy link

the only warning i see is Cookie “__session_key” does not have a proper “SameSite” attribute value. Soon, cookies without the “SameSite” attribute or with an invalid value will be treated as “Lax”. This means that the cookie will no longer be sent in third-party contexts. If your application depends on this cookie being available in such contexts, please add the “SameSite=None“ attribute to it. To know more about the “SameSite“ attribute, read https://developer.mozilla.org/docs/Web/HTTP/Headers/Set-Cookie/SameSite so im assuming this is the error but where do i add the samesite attribute, ive tried in the config to no avail, thanx for looking at this even tho its across application bounds, it seems as multiple ueberauth plugins are having the same issue and this had the most traction

@aj-foster
Copy link
Contributor

Just sharing based on my past experience, first some general things to check (for anyone reading) and then some specific thoughts for the above conversation.

General Notes:

  • Check that you are using ueberauth version 0.7.0 or above. This is when CSRF checks were added, so if you're seeing a CSRF related error, you're here.

  • If you're using an OAuth strategy that requires POST callbacks (for example, ueberauth_apple), then ensure the strategy is using the state_param_cookie_same_site option in its code. POST requests require SameSite=None to work properly. (Sidenote: the "official" ueberauth_apple strategy doesn't do this yet, but I maintain a fork that does.)

  • If you require SameSite=None because of the above, you must also trick Plug into setting the secure attribute on the cookie as well.

    Plug manages this behaviour based on the incoming request conn. If the original request was for an http address, Plug will not set the secure attribute, and SameSite=None will not be accepted by the browser. If the original request used https but you're terminating TLS at a load balancer (for example), you must inform plug about the correct protocol by using an X-Forwarded-Proto header or something similar.

  • Related to proxies and headers, make sure you don't have a layer of infrastructure that is stripping out the set-cookie header in responses or cookies in requests.

  • Make sure the scheme matches between your original request to /auth/:provider and the callback request. If one is made with http and the other https, or vice-versa, the browser may decline to send the state cookie during the callback.

Specifics:

  • It's odd that there is no set-cookie header listed in the first response at all. Maybe that's just an artifact of the way the browser exported the request log (it automatically removes cookies that were rejected?). But it makes me wonder if Ueberauth isn't even trying. A quick version check of all the libraries involved wouldn't hurt. You almost certainly have ueberauth version 0.7.0 or higher because of the set-cookie in the last response, but maybe you have an old version of the GitHub strategy that doesn't yet call the internal function for setting the state cookie during the request phase.

  • GitHub and Google use GET requests during the callback phase, which means SameSite shouldn't matter (as far as I understand). So as long as the browser isn't completely blocking the cookie, it should be fine. Furthermore, localhost is a secure context, so the whole secure attribute discussion above shouldn't matter.

  • As a final check, make sure the scheme matches between your original request to /auth/:provider and the callback request. If one is made with http and the other https, or vice-versa, the browser may decline to send the state cookie during the callback.

@mithereal
Copy link

i fixed this by noticing my callback was running 2x, this was due to a failure in the callback of the controller i was running returning an unexpected response so wasnt technically failing but ueberauth wasnt setting the cookie

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

6 participants