Live data from Hacker News

Killing CORS Preflight Requests on a React SPA

m.alphasights.com

41–50 of 54 posts

Re: Killing CORS Preflight Requests on a React SPA

#41
post #8

> In terms of security, all API calls should be using https and there is little difference in putting the token in headers or as part of the query string. Mostly true. But as a heads up, you might want to shy away from this as plenty of browser extensions are actually spyware and report full URLs back to the mothership. We ran into this recently where calls to our service including API keys in the query parameters en…

If your token is invalidated and regenerated after every request, this mitigates a token leaking (unless the browser extension intercepts your call and uses the token immediately... at which point your user has other problems to worry about!)

https://github.com/lynndylanhurley/devise_token_auth#about-t... has a good example of this. It's nontrivial for either clients or server to implement (the edge cases around overlapping requests require careful thought), but it would likely solve this scenario.

Re: Killing CORS Preflight Requests on a React SPA

#42

Maybe this is obvious, but why not just configure a reverse proxy to point different paths to different backends? I always assumed CORS was more for connecting directly to 3rd party APIs.

Sounds like they're hosted entirely on Heroku and didn't want to go through the effort of adding external infrastructure. But I just found out apparently you can host Nginx on Heroku [1] which is neat, but looks a bit sketchy

[1] https://github.com/ryandotsmith/nginx-buildpack

Re: Killing CORS Preflight Requests on a React SPA

#43
post #31

I was running into a CORS-related issue, and was thinking of a possible solution: If it were possible to make "cookie-less" AJAX requests to things like APIs, would it be safe for those requests to bypass CORS? My impression is that the cookie sending is the main danger, and if we could opt-out, then the "use API with provided key" use-case could work independent of what the destination site wants. I don't know if th…

FYI, Safari on iOS will never send cookies cross-domain, regardless of how you configure the server or call your XmlHttpRequest (the user can enable 3rd-party cookies in Settings, but literally nobody will ever do this):

https://stackoverflow.com/questions/14206531/mobilesafari-wo...

Re: Killing CORS Preflight Requests on a React SPA

#44
> we had to deal with making CORS requests from app.example.com to api.example.com

What? If you share the same domain but a different sub domain then just set the document.domain property[1] so they trust each other and be done with it. You don't even need CORS...

Alternatively setup a proxy to keep everything behind the same domain. This is typically a best practice.

> In our case, since each CORs request makes a preflight check, it doubles this significant latency without adding any value.

Considering CORS contains no body and does no processing beyond asking what the client can and cannot do, it seems odd this would always "double" the latency here.

> After reading a great blog post and MDN’s CORS docs I realized there are circumstances where the browser does not make a preflight request, if conditions are met

Okay this is scaring me. Where are we going with this?

> In terms of security, all API calls should be using https and there is little difference in putting the token in headers or as part of the query string.

Yeah was afraid of that. Please don't do this especially if you use that URL in any way to give the user access to a link (e.g. downloading a file) because now it's part of their browser history and they can't completely log out.

> Thanks for reading this! I hope it helped, even if the conclusion is “preflight requests are too troublesome, I’m going proxy” :)

A proxy is the correct solution. Not this horrible hack fest of completely disregarding important HTTP headers. Sigh

[1] https://developer.mozilla.org/en-US/docs/Web/API/Document/do...

Re: Killing CORS Preflight Requests on a React SPA

#45
> 1. Find a way to proxy requests so that there’s no CORS

Turns out this is really, really easy.

I tried this recently on a cookie-authenticated web api (after discovering that CORS cookies are useless because mobile Safari will always block them). I'm never touching CORS again unless it's a blasting out a bunch of '*' Access-Control-Whatevers on a public API.

Re: Killing CORS Preflight Requests on a React SPA

#46
post #4
post #3

"If this feels “so 2015” to you, we did start building the app in early 2015 and went down the centralized RESTful API route." If the author considers that route to be "so 2016", what would the 2016 Newest Thing be?

Another symptom of how rotten the javascript ecosystem is. If I'm picking a technology stack for a business, I want to pick one that will last me 10 years.

> If I'm picking a technology stack for a business, I want to pick one that will last me 10 years.

What? Why wouldn't JavaScript last you 10 years? It's been around for over 20 already and is certainly not going anywhere...

You don't have to upgrade to the newest fad every 6 months like you seem to imply. Most modern languages have crazy fads (just maybe not as fast as JavaScript does) and no one jumps on them every single time they're released, why would JavaScript be different?

Re: Killing CORS Preflight Requests on a React SPA

#47
post #36
post #23

Earlier quoted context omitted.

If we're talking about browser extensions (as the comment I replied to was) then we're talking about calls being made from the browser.

FWIW, if it clarifies things, we disable shared secret auth when enabling mutual auth. At that point, you can really only call it with curl or your application.

I'm not sure I follow. If you can use it from curl (presumably by passing the client certificate) couldn't you also use it from a browser? The browser has client certificate infrastructure, surely it can use it when making ajax requests?

Re: Killing CORS Preflight Requests on a React SPA

#48
post #6

Earlier quoted context omitted.

2016 would be the rise of GraphQL or Falcor backends, where you write exactly what you are looking for on the frontend and send that request to the backend instead of REST endpoints. http://graphql.org/ http://netflix.github.io/falcor/

This is a pretty neat idea. It seems like it would be a lot harder to reason about than REST endpoints. I'm particularly thinking about validation (beyond the type-level, like when other data could conflict with a change) and security issues. What kinds of techniques are used to approach these concerns? Both examples seem to be completely JavaScript-centric on the server side, but it seems like there's no reason it s…

GraphQL servers exist in multiple languages, many of them have more mature implementations than the reference (JavaScript)server. Sangria (the Scala implementation) is particularly impressive. And one of the Elixir implementations, Absinthe, is coming along very nicely.

The main security concerns are:

* Data leakage, the GraphQL schema reveals the overall capabilities of your system, which may not be desirable. It may still be necessary to split into private/public implementations.

* Denial-of-service. Unless you take steps to mitigate it (there are a few approaches out there), it's often trivial to construct a query that could bring down a server. The two main approaches i've seen are white-listing queries at build time (so clients can't construct arbitrary queries), and adding cost/complexity heuristics to the server and rejecting any query over a certain threshold.

* Authentication. Not actually a new concern, because the issue is basically the same as with REST. But you do need to get authentication and permissioning properly designed on the backend, it's not something you can really defer until a later date.

Re: Killing CORS Preflight Requests on a React SPA

#49

> we had to deal with making CORS requests from app.example.com to api.example.com What? If you share the same domain but a different sub domain then just set the document.domain property[1] so they trust each other and be done with it. You don't even need CORS... Alternatively setup a proxy to keep everything behind the same domain. This is typically a best practice. > In our case, since each CORs request makes a pr…

Even more so, please prevent expensive TLS setup roundtrips to two different hosts. That's probably 2x as expensive as a single preflight request for non-resuming sessions.

As parent states: a simple reverse proxy is probably the way to go here. Takes about 3 lines in nginx.

> After reading a great blog post and MDN’s CORS docs I realized there are circumstances where the browser does not make a preflight request, if conditions are met

I must say I was a bit surprised that some POST requests can be executed without verifying CORS. There must be a bunch of POST endpoints out there that do have side-effects based on the cookie value, even without body. The distinction in behaviour between json or form encoding is pretty bizarre imo.

Re: Killing CORS Preflight Requests on a React SPA

#50
post #47
post #36

Earlier quoted context omitted.

FWIW, if it clarifies things, we disable shared secret auth when enabling mutual auth. At that point, you can really only call it with curl or your application.

I'm not sure I follow. If you can use it from curl (presumably by passing the client certificate) couldn't you also use it from a browser? The browser has client certificate infrastructure, surely it can use it when making ajax requests?

You can, it just requires you to import the cert and use some pretty gnarly UI. I didn't mean to imply you couldn't use it from the browser, just that it was much less likely than curl + we rely on the cert for figuring out your account and not an API key.
Post reply on HN