Kuba Niechcial
I am senior software developer and team leader at netguru, Poland. I work mostly with Ember.js, React and Ruby on Rails. I am passionate blogger and you can find out most of my work on my website.
Cross-origin resource sharing (CORS) is a standard for accessing web resources on different domains.
What does it mean?
CORS is browser-level mechanism that prevents client-side JS from accessing other domains than current one.
To remember: it is browser-level.
Core mechanism depends on browser adding Origin header to each cross-domain request. Browser expects server to respond with Access-Control-Accept-Origin header.
What does it mean?
Each cross-domain request is automatically extended with Origin header. If the server responds with empty Access-Control-Accept-Origin header or the one that does not contain current domain, browser will raise an exception.
CORS was introduced to handle XMLHttpRequests. JSONP allows only to perform GET request, the motivation was to introduce secure way to handle all HTTP verbs.
Simple CORS mechanism is used when the request sent is not expected to do any side-effects. It means that it is GET, HEAD or POST request and does not include any additional headers.
What does it mean?
CORS is browser-level. Browser assumes that GET, HEAD or POST without any additional headers should not make any side effects, therefore it's safe to send the request and check the headers on response.
Step by step
1. Client-side JS requests resource on the other domain (GET).
2. Browser is automatically adding Origin header.
3. Server is responding. It adds Access-Control-Allow-Origin containing Origin domain.
4. Browser accepts the header, the request is fulfilled.
Extender CORS mechanism is used when the request sent is expected to do side-effects. It means that it is PUT, DELETE or any other with custom headers.
What does it mean?
CORS is browser-level. To prevent server from accepting request that potentially can do harm (side-effects), the browser is sending preflight request to check the headers before doing any side effects. This preflight request is using OPTIONS HTTP verb.
Step by step
1. Client-side JS requests resource on the other domain (PUT).
2. Browser is automatically sending preflight request with Origin header.
3. Server is responding. It adds Access-Control-Allow-Origin containing Origin domain.
4. Browser accepts the header. It sends initial PUT request eventually using simple CORS mechanism.
Amazon S3
You deploy your app using ember-cli-deploy. Assets are uploaded to S3 (nice one!) and while testing you get...
Access to Font at 'https://my-app.s3.amazonaws.com/webfonts/yolo.woff' from origin 'https://my-app.s3.amazonaws.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access.
Ember SPA
You run your Ember app on yolo-front.staging.my-app.com. Your backend runs on yolo.staging.my-app.com. And then...
Access to Resource at 'https://yolo.staging.my-app.com/users/me' from origin 'https://yolo.staging.my-app.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://yolo-front.staging.my-app.com' is therefore not allowed access.
Enable CORS in your backend
Ruby on Rails
rack-cors - default in netguru stack
Node.js (express.js)
cors - tried in battlefield, it works :)
Most important to remember
CORS is browser-level security mechanism that you must eventually bump into while working with frontend.
It's not hard, it's quite easy and straightforward.
It is doing two requests that can't be cached, so you are probably wasting time.
By Kuba Niechcial
What is CORS and how does it impact my work?
I am senior software developer and team leader at netguru, Poland. I work mostly with Ember.js, React and Ruby on Rails. I am passionate blogger and you can find out most of my work on my website.