Live data from Hacker News

Demystifying CORS

frontendian.co

11–20 of 50 posts

Re: Demystifying CORS

#11
I've never understood why so many people seem to find this confusing. CORS is really simple: if you want third-party sites to be able to access the contents of a given page, you need to send `Access-Control-Allow-Origin: sitename.com` in your response. If you don't send that header, the browser will default to the more secure behavior and just deny access. (Yes, it can get more complicated when you need to allow credentials or access to other HTTP methods but the concept itself is dead-simple.)

Maybe people are just confused about the same-origin policy in general? (Which is not the same thing as CORS, but related.) That's more understandable, but still really easy to explain; if you're signed into a site or have access to a non-public (corporate LAN) site, you _don't_ want every third-party site you visit to have unrestricted access to all your personal data on that site. Therefore browsers, by default, don't allow third-party access to a given origin; simple as that.

Re: Demystifying CORS

#12

What I find perplexing is that for this and every other web technology, there doesn't seem to be a central comprehensive resource that explains it all in great detail. It's like we have to pick things up as we go along, from tidbits and articles here and there, not of it complete or comprehensive, and often there'll be little mistakes or misleading bits.

I think MDN is doing a great job of becoming the go-to resource for everything: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS

Re: Demystifying CORS

#13
I feel like that part at the end is very misleading. GET and POST with simple headers are still subject to CORS. The distinction between a form submit and an ajax request is that you are reading the response from javascript. Same origin policy only kicks in when you attempt to read a response from JavaScript. It's why Fetch API has a 'no-cors' mode where you can make cross-origin requests willy nilly so long as you don't attempt to read the response values. The idea is prevent "secret" background requests being sent by malicious sites. Form submits are handled by the browser and will incur a page refresh.

Re: Demystifying CORS

#14
post #11

I've never understood why so many people seem to find this confusing. CORS is really simple: if you want third-party sites to be able to access the contents of a given page, you need to send `Access-Control-Allow-Origin: sitename.com` in your response. If you don't send that header, the browser will default to the more secure behavior and just deny access. (Yes, it can get more complicated when you need to allow cred…

People get confused because it's two requests, first the options one, then the normal one. Their web frameworks are largely built on single connection handling, but because CORS isn't used by many people it's often a tacked on afterthought. For example, in Rails they briefly made it impossible to manually handle Options requests (something that I fixed).

Then there is the core weirdness of subdomains and security headers in general. Most developers don't really care about security. They'll do what they're told and like to do a good job overall, but deep down they don't enjoy spending time thinking about how to pwn the app they're building. They just want someone to use what they've built and love it.

Re: Demystifying CORS

#15
post #4

This post never actually explains why any of this was needed. The closest it comes is this bit: "If [...] the same-origin policy for XMLHttpRequests relaxed, said services could now receive a deluge of DELETE, PUT, etc… requests from any origin" But why on earth is this a problem? And in any case those services always could receive requests from any origin, browsers aren't the only HTTP clients in the world. In the o…

CORS was designed to mitigate e.g. the following attack: * You are logged at with service X, which uses a Cookie to store your authentication code. * Service X offers an endpoint to change your password, as well as an endpoint to retrieve your user account. * You visit malicious website Y, which uses JS to send requests to the "change password" and "view profile" endpoints of service X (which without CORS would be ac…

I've always found it interesting how there's a difference between actions the user initiated and those the user did not. You'd think that would be very challenging to enforce, given how flexible browser scripting is nowadays, but it seems to Just Work.

Re: Demystifying CORS

#16
Where CORS got complicated for me was adding custom request and/or response headers to a cross-origin GET request. Different browsers handles this differently. For example, Safari would make a pre-flight request if certain request headers are sent, while Chrome would just send it. And Chrome would not make a pre-flight request, and won't populate the "Origin" request header, but will then drop "unknown" response headers (and doesn't give you any way to force a pre-flight request or Origin header). I eventually figured out you can just always respond with `Access-Control-Expose-Headers`, even though it doesn't look like a CORS request, and then Chrome will expose the headers to the JS.

Re: Demystifying CORS

#17
post #11

I've never understood why so many people seem to find this confusing. CORS is really simple: if you want third-party sites to be able to access the contents of a given page, you need to send `Access-Control-Allow-Origin: sitename.com` in your response. If you don't send that header, the browser will default to the more secure behavior and just deny access. (Yes, it can get more complicated when you need to allow cred…

People get confused because it's two requests, first the options one, then the normal one. Their web frameworks are largely built on single connection handling, but because CORS isn't used by many people it's often a tacked on afterthought. For example, in Rails they briefly made it impossible to manually handle Options requests (something that I fixed). Then there is the core weirdness of subdomains and security hea…

There aren't two requests; at least not normally.

Preflight requests are only needed if you want to send unusual headers in your request or use HTTP methods other than GET or POST. See https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#Simpl...

But you make a good point about developers not caring about security. If I look at it from that perspective it totally makes sense. If you don't have any reason to care, CORS headers may just seem like an unnecessary annoyance that you don't want to bother learning. "Not allowed access? Why? I don't care about your darned security headers, I just want to make an API request."

Re: Demystifying CORS

#18
post #11

I've never understood why so many people seem to find this confusing. CORS is really simple: if you want third-party sites to be able to access the contents of a given page, you need to send `Access-Control-Allow-Origin: sitename.com` in your response. If you don't send that header, the browser will default to the more secure behavior and just deny access. (Yes, it can get more complicated when you need to allow cred…

CORS as a concept is dead simple. CORS as an implementation in decades old Java services is anything but. I can spend hours trying to get Charles to allow a proxy from localhost development to a backend service.

Re: Demystifying CORS

#19
We really need Authorization added to simple headers. Needing to preflight every single SPA request either causes a huge performance hit or else forces super hacky workarounds that introduce their own security issues. Not good for the web.

Re: Demystifying CORS

#20

Where CORS got complicated for me was adding custom request and/or response headers to a cross-origin GET request. Different browsers handles this differently. For example, Safari would make a pre-flight request if certain request headers are sent, while Chrome would just send it. And Chrome would not make a pre-flight request, and won't populate the "Origin" request header, but will then drop "unknown" response head…

That's really odd. There are shared tests for all this stuff, and browsers should really be doing it identically.

Did you happen to report bugs on this to browsers? If not, do you happen to have a link to a page that shows the behavior difference?

Post reply on HN