What is the issue CORS is trying to solve?
Asked Answered
M

4

83

I've been reading up on CORS and how it works, but I'm finding a lot of things confusing. For example, there are lots of details about things like

User Joe is using browser BrowserX to get data from site.com, which in turn sends a request to spot.com. To allow this, spot has special headers... yada yada yada

Without much background, I don't understand why websites wouldn't let requests from some places. I mean, they exist to serve responses to requests, don't they? Why would certain people's of requests not be allowed?

It would really appreciate a nice explanation (or a link to one) of the problem that CORS is made to solve.

So the question is,

What is the problem CORS is solving?

Mart answered 8/12, 2014 at 19:22 Comment(0)
M
53

The default behavior of web browsers that initiate requests from a page via JavaScript (AKA AJAX) is that they follow the same-origin policy. This means that requests can only be made via AJAX to the same domain (or sub domain). Requests to an entirely different domain will fail.

This restriction exists because requests made at other domains by your browser would carry along your cookies which often means you'd be logged in to the other site. So, without same-origin, any site could host JavaScript that called logout on stackoverflow.com for example, and it would log you out. Now imagine the complications when we talk about social networks, banking sites, etc.

So, all browsers simply restrict script-based network calls to their own domain to make it simple and safe.

Site X at www.x.com cannot make AJAX requests to site Y at www.y.com, only to *.x.com

There are some known work-arounds in place (such as JSONP which doesn't include cookies in the request), but these are not a permanent solution.

CORS allows these cross-domain requests to happen, but only when each side opts into CORS support.

Monk answered 8/12, 2014 at 19:25 Comment(11)
Ah ok, so it's the browser that sets these rules. If so, then what's with the Access-Control-Allow-Origin on the server end? How would cross origin requests even get there if the browser won't allow it?Mart
@Imray - see the CORS link in my answer. Newer browsers support CORS if the sites opt in to using it (via the header).Monk
In MDN Access Cotrol doc, GET request with credentials are not preflighted. But if response headers doesn't include Access-Control-Allow-Credentials: true then response will not be available to the invoking client. If this behaviour same for POST (Simple POST request with credentials - Content Type may be form-data) request as well, there is risk that POST might change the server state though response may not be made available to client. Is this assumption correct? OR POST request with credentials pre-flighted?Miserere
#36613551Miserere
The thing I really don't get though, is that if you make a GET or POST request, it won't get pre-flighted. So the server could still process the request. So in theory, couldn't you make a malicious request and it just doesn't show up to the client?Berger
Doesn't the Same-Site=Strict parameter for the Set-Cookie header obsolete all the CORS shenanigans? As far as I understand from the docs it prevents exactly what you are describing.Charest
requests can only be made via AJAX to the same domain (or sub domain). Requests to an entirely different domain will fail. A dangerous oversimplification. Open your browser's Console on this very page and run fetch('//example.com'), then inspect the Network tab; you'll see that a GET request was indeed sent to https://example.com.Trapezohedron
@BalázsÉdes The SameSite cookie attribute and CORS can be used in conjunction precisely because site is broader than origin. More about this topic elsewhere.Trapezohedron
@Trapezohedron did exactly that, and here's what my console gave me (chrome latest, win 10): Access to fetch at 'example.com' from origin 'stackoverflow.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.Monk
@Monk Regardless of what you make of this error message, your request reached the server, as evidenced by what your browser's Network tab shows. The browser is only preventing your client (running in the context of Web origin https://stackoverflow.com) from reading the response to that request.Trapezohedron
If you don't believe me, try fetch('//some-server-you-control.com') instead and then inspect that server's logs.Trapezohedron
F
40

First, let's talk about the same origin policy. I'll quote from a previous answer of mine:

The same-origin policy was invented because it prevents code from one website from accessing credential-restricted content on another site. Ajax requests are by default sent with any auth cookies granted by the target site.

For example, suppose I accidentally load http://evil.com/, which sends a request for http://mail.google.com/. If the SOP were not in place, and I was signed into Gmail, the script at evil.com could see my inbox. If the site at evil.com wants to load mail.google.com without my cookies, it can just use a proxy server; the public contents of mail.google.com are not a secret (but the contents of mail.google.com when accessed with my cookies are a secret).

(Note that I've said "credential-restricted content", but it can also be topology-restricted content when a website is only visible to certain IP addresses.)

Sometimes, however, it's not evil.com trying to peek into your inbox. Sometimes, it's just a helpful website (say, http://goodsite.foo) trying to use a public API from another origin (say, http://api.example.com). The programmers who worked hard on api.example.com want all origins to access their site's contents freely. In that case, the API server at api.example.com can use CORS headers to allow goodsite.foo (or any other requesting origin) to access its API responses.

So, in sum, we assume by default that cross-origin access is a bad thing (think of someone trying to read your inbox), but there are cases where it's a good thing (think of a website trying to access a public API). CORS allows the good case to happen when the requested site wants it to happen.

Flightless answered 8/12, 2014 at 19:36 Comment(2)
So the browser still has to send some sort of request to all sites to see if they have CORS headers, right? If evil.com has a script to access my bank site, will my browser send a test request or something to check for those headers, while not attaching my cookies?Mart
@Imray Yes, requests are performed on the network level; the results simply aren't shown to JavaScript if the CORS check fails. See my answer on How does Access-Control-Allow-Origin header work? (sorry to keep linking to my own stuff, but it's a question I've answered a few times before and the linked answers are (I hope) relevant to your questions)Flightless
M
0

There are security and privacy reasons for not allowing requests from anywhere. If you visited my website, you wouldn't want my code to make requests to Facebook, reddit, your bank, eBay, etc. from your browser using your cookies, right? My site would then be able to make posts, read information, place orders, etc. on your behalf. Or on my behalf with your accounts.

Mutualize answered 8/12, 2014 at 19:29 Comment(1)
If i'm visiting your site, you won't have access to my facebook cookies! you only have access to cookies for your own website, right!?Borreri
C
0

Cross Origin Request Sharing(CORS) is, it is just a mechanism to by pass web browser's Single Origin Policy(SOP).

In simple terms, the web browser dosen't allow the frontend code for a website running on domainA to make calls to servers on domainB. Eg. When you are on [facebook.com] on the browser, the frontend code for facebook cannot make calls to [icicibank.com]. This is what web browser's Single Origin Policy dictates. You can bypass this mechanism using CORS.

But why the hell was SOP needed in the first place?

Well, the answer is cookies!

Let's understand this with the same [facebook.com] and [icicibank.com] example. You see, whenever you interact with any website, the website takes your login information, and generally returns back a token of sorts and this token is stored in the web browser and is called a cookie. Now when you try to login to the see the website again, the token is detected and you are directly allowed to login without asking for your credentials again.

Before SOP existed these cookies were misused. Eg.

  1. Lets say you logged into [icicibank.com], checked your account balance and closed the web browser. Sometime later you tried to access [facebook.com].

  2. Lets imagine facebook is an evil website for a second, now while you are on [facebook.com], the frontend code for facebook could be making AJAX(dynamic https request) to [icicibank.com].

  3. Before SOP, web browsers allowed these requests to take place. Since these requests were executed in the background, you would never know whether these requests were made or not. And when these requests to icicibank's server were made through facebook's frontend code, the web browser would innocently pass the icicibank's cookie in the request. Allowing facebook to access your bank account and then misuse it for evil purposes.

And this is why SOP was created!

Now, there are some APIs that the developers have worked hard on and want to be public in nature. CORS allows for that to happen.

Corkhill answered 7/4 at 6:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.