> ## Content Index
> Fetch the complete content index at: https://blog.bajonczak.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# What is Cors?
- URL: https://blog.bajonczak.com/cors/
- Published: 2020-02-09T23:00:00.000Z
- Updated: 2022-10-23T16:02:32.000Z
- Author: Sascha Bajonczak
- Tags: Security, Development, Web Development

If you're a web developer, CORS is probably a recurring phantom that comes back every other project to steal a whole week. After my most recent wrestle with it, I decided to share my knowledge about it with you.

# What's that?

Cross Origin Resource Sharing (CORS) is a security measure enforced by web browsers which affects calls made from a web browser to a remote resource like an API on another web domain. The key to understanding CORS is to understand that it is the browser which is blocking, but to allow CORS, the server has to add special headers which satisfy the browser into allowing the connection. As such, CORS blocking doesn't affect back-end solutions that call APIs.

# Simple Requests

If you are just doing an `HTTP` `GET`, `HEAD`, or `POST` (with no custom/exotic HTTP headers and a **normal** content-type), then you're making a simple request. This means there won't be a **preflight** OPTIONS check. So... no fancy stuff.

A **normal** content-type is one of the following:

- application/x-www-form-urlencoded
- multipart/form-data
- text/plain

But wait! What about `application/json`? I (maybe all others) need them for specific calls to API's. But this content-type counts as an exotic content-type, and you **will** be subject to a preflight OPTIONS request! You can imagine a Preflight like this:

![Preflight](https://notes.bajonczak.com/assets/img/preflight.2ccbd883.gif)

# My call really is simple

Well, after calling for the endpoint you wanted, (e.g. `https://superduperapi.example.com/leaderships/`), the browser checks whether the response contains an `Access-Control-Allow-Origin` header which lists your site by name or implies it by wildcard (that is, `*`).

If there's no such header, or your site isn't mentioned in said header, the browsers thinks "Ok, that API isn't supposed to be called from here (perhaps an attacker is trying to get some financial information)" and it stops the running JavaScript from seeing any detail about the response except that it failed. The F12 developer tools in the browser can tell the developer/user what happened, but the (potentially evil) script is kept in the dark.

You will get also promted with an **nightmare** errormessage in the developer console too:

![Cors Error](https://notes.bajonczak.com/assets/img/cors-error.edd69d05.png)

So, to allow calls to your API from any and all websites, as long as you don't require special headers or anything else mentioned on the MDN description of a simple request, you only have to make sure that your server returns the aforementioned `Access-Control-Allow-Origin: * header`.

> Please keep attention that using the `*` you will allow any caller to access. So change it on the production to the list of domains that has access to it (except localhost).

# Complex requests

Complex, or **preflighted** requests are those with extra headers or an unusual content type, and have to be checked first (by the browser) to find out whether the request is safe to send at all.

When the browser thinks a request is complex, it will call ahead to the server with the HTTP `OPTIONS` verb.

Your server must respond to the OPTIONS verb not only with a matching `Access-Control-Allow-Origin` but with other headers that explicitly allow whatever incoming stuff you expect in the request. For example, if you expect a header called `X-Secret-Allergies` then your server must respond to the OPTIONS call with a header like:

```text
Access-Control-Allow-Headers: X-Secret-Allergies

```

To allow content types that aren't in the **simple** list above, you have to explicitly add the `Content-Type` header to the list in `Access-Control-Allow-Headers`!

# But What about Authorization?

If your request requires an `Authorization` header, or an auth cookie of some kind, you **can't use a wildcard** for your Allow-Origins list! You have to specify the exact domains. I don't know how people are working around this in the wild, except perhaps by rolling their own auth headers or doing some RESTful credentials-in-every-request. Because the local URL's may be different on each machine.

If you're using a framework to abstract HTTP requests, like Axios, Angular `$http`, or (cough) JQuery AJAX, then you should look for the `withCredentials` option. Setting it to **true** means that you **are** sending either an `Authorization` header or an auth cookie. So you can't have a wildcard allow list, and you must add Authorization to your `Access-Control-Allow-Headers` list.

# Why. What. Why do I have to do this

[Here (opens new window)](https://security.stackexchange.com/questions/149150/what-attacks-are-mitigated-by-requiring-cors-for-subresource-integrity-verificat/149169?ref=blog.bajonczak.com#149169)is the best explanation of an attack which is stopped by CORS that I have found.

It seems to me that in essence, CORS helps to protect users from evil sites which try to load resources from good sites, hoping that the user is logged into the good site, so that their account information can be pulled across to this evil page and sent off to an evil server.

# End

I hope that his article will help you to understand the basic of CORS and how to handle it. It is a very usefull technical feature to increase the security for your api and it is well supported by the browsers(*except IE<10*):

![](https://notes.bajonczak.com/assets/img/browser-support.86b6832a.png)

Tell me about your CORS experience or suggestions in the comments!