Blane Townsend
Blane Townsend

Reputation: 3048

AJAX withCredentials not passing along cookies in Safari

I have a single-page static app hosted at example.com. My server for the app is hosted at server.com. I keep these two services completely separate and they can scale differently this way. When the user wants to login their username and password is passed to yoyoma.com and a cookie is set on server.com with the access_token. The user is then redirected to example.com and is now logged in.

From the static app at example.com, we can now make AJAX requests to server.com setting withCredentials=true so that the access_token we set is passed along to server.com. This works perfectly in every browser but Safari. The only way I've gotten Safari to work is by going to preferences -> privacy -> disabling "Prevent cross-site tracking". I know that the cookies are getting set on server.com, but they don't get passed with the AJAX request. It seems to be some Privacy feature that Apple thinks is just wonderful, but how are you supposed to get around this issue. I'm not an ad service, I'm not doing anything evil, just trying to get my app to work. I specifically want to build a single page app where the server is on a different domain. Is this possible in Safari or has their privacy setting made this impossible?

Note: I should also mention to security fanatics that when the access_token cookie is set, the user is then redirected to example.com with a CSRF token. This csrf token is passed in every AJAX request by a header to prevent Cross Site Request Forgery.

Upvotes: 1

Views: 1639

Answers (1)

Seivan
Seivan

Reputation: 689

Assuming you're set on keeping different domains - which is not at all unreasonable there are some ways to tackle it, but they come with compromises

1 Have example.com redirect to a server rendered server.com/login for creating the httpOnly cookie and then redirect them back to their logged in state in your SPA.

As I understand it, when Prevent cross-site tracking is enabled in Safari, the intention is to have the user interact with the other domain before cookies are allowed to be sent. By redirecting them, that intent has been created and you should have no issue setting a cookie and have it be sent by example.com.

However it does come it its own set of limitations https://webkit.org/wp-content/uploads/tracking-prevention-timeline.png

Read more

2 Look into the discussion related to StorageAccess as the idea here is to work with third party auth solutions that rely on cookies from different domains. Safari ITP has sorta made those harder to use, so the idea is to work with vendors for a better solution than LocalStorage.

3 Store your key in LocalStorage, and vet all running javascript code coming from you and make sure to follow best practices when it comes to dealing with user created values.

LocalStorage exposes your to potential XSS, but Cookies expose you to CSRF attacks. You have to mitigate those and it's not too hard, but keep in mind you introduced those vectors when cookies were used.

Any XSS that happens is game over, even with httpOnly cookies. Forget your auth key, running the attackers code can do so much more damage.

  • Keylogger to take username/password
  • If the attack happens after an authed state, they could pop up a modal asking re-auth.
  • Submit a request to change email and then ask for password reset

Don't get me wrong, it's easier to dump LocalStorage as a generic attack versus the attacks listed above

That being said, in the end the resources you spend on dealing with cookie issues, could be better spent hardening down your javascript running on the users browsers to ensure they aren't running malicious code

You can't protect them from extensions though, and a httpOnly cookie would at the very least ensure that their keys aren't leaked. Know your compromises.

Edit: Keep in mind that whatever approach you're taking, any further reliance on browser needs to think through the different versions of browsers out in the wild. As an example, don't assume using httpOnly cookies and setting a sameSite policy negates the need for a CSRF token. Any addition of cookies might s till need a CSRF token as a header as of today unless it's a controlled environment.

Personal Opinion held loosely. Do no harm. Cookies add "harm"/work that you have to mitigate. Cookies might protect attacks leaking access tokens but why would an attacker care about the access token when they can run any code they wish? LocalStorage weakness is XSS, but Cookies does not protect against that.

What prevents them from just taking the password? Popping up a login modal to an unexpected user that won't think twice, hell Github does that from time to time for good reasons, it's not unheard of.

Upvotes: 1

Related Questions