dbrgn / iron-cors-rs

A CORS Middleware implementation for Iron.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

with_whitelist should have an option for accepting request without origin header

DavidBM opened this issue · comments

When the domain is the same as the webpage was loaded, the browser doesn't send the origin header.

For example, when I launch a server in localhost and with cors like ["localhost:3000"] the middleware doesn't allow the request because the browser is not sending the cors.

That will apply to if I have a webpage that is using some subroute as api endpoint (can be done with nginx).

Anyway, that should be configurable for be able to express "My domain and this other domains".

Hm, good point.

Here's also a good SO post: http://stackoverflow.com/a/15514049/284318

I would recommend checking the Host header, and if it matches the domain in the Origin header, don't treat the request as CORS.

Maybe that's what we should do, although this gets a bit tricky with proxies. The correct way to handle this would probably be the "Forwarded" header. It's not supported by Hyper yet, but I filed an issue today. An alternative commonly used but non-standard header set by proxies that might be relevant to us is X-Forwarded-Proto.

As I understand from that Stack Overflow post if that Same-domain Origin is totally optional by standard. That means that:

  • We should allow any request that go without Origin. That means that the browser is in the same origin. Doing a check again the Forwarded or X-Forwarded-Proto is, in my opinions, useless, because
    • A) CORS assumes that browsers have the standard implemented correctly.
    • B) CORS doesn't protect the access to the API from any request, only from third party (browsers that implement CORS). That means, CORS avoid that someone put a script in a big webpage making a DDOS attack using the browsers of other people and things like that. But doesn't avoid a nodejs apps or similar to access to the API.

This can be fixed having the variable allow_invalid always in true.

Yeah, I think you're right. Since anyone can fake the Origin header it's useless to try to enforce it.

Another question would be whether the original handler should be executed even if the Origin header does not match, or not. Right now, a BadRequest status is returned.

I think is better to just interrupt the chain and return BadRequest. If not the developer have a lot of work to do. Maybe it can be done with an optional flat. But I think the actual behavior is KISS and correct one.

I removed the BadRequest behavior in my pull request. Reasoning: CORS only affects headers and is only useful in browsers. Browsers will always set an Origin header if applicable. And if they set the request headers, they will also check the response headers. So there's no advantage in not processing the response, that's the job of the browser.

Wait wait. Then the developer how know is the CORS pass from the server?

I mean, the browser send the request (without preflight), the server answer without a CORS header. Then the browser shows an error about CORS and doesn't give to the js the data from the server, but still the server process the request.

For example, consider this scenario.

  • Webpage in domain.com
  • Creating account in api.domain.com
  • Other web in otherdomain.com
  • Someone finds an XSS in otherdomain.com and adds an script that send a request to create acount in api.domain.com.
  • All the browsers show an error. That is ok. But still the server in api.domain.com is creating users.

There should be a way to know if the CORS was valid or not from the server. Maybe automatic, maybe with a flag or maybe injecting it in the Request object.

@dbrgn

@DavidBM isn't that exactly the problem solved by preflight requests? see also: https://www.html5rocks.com/en/tutorials/cors/

@dbrgn Yes, but as far I understand, there is cases of CORS calls that don't use preflight. GET & POST don't use preflight in some header configurations. That means, a POST still can be done using CORS without preflight. In my opinion, that calls should not be executed on the server and should return with error.

My logic is: When that occurs, we have enough data for knowing for sure that this is a request that is going to be blocked by the browser. Why execute this in the server then?