# C.O.R.S.

## Définitions

Cross-Origin Resource Sharing. <https://www.w3.org/TR/cors/>

L’ "origin" *(*[*https://tools.ietf.org/html/rfc6454*](https://tools.ietf.org/html/rfc6454)*)* est composé des éléments suivants :

* Scheme : http / https / …
* FQDN : [www.attacker.com](http://www.attacker.com) / api.target.com / …
* Port : 80 / 443 / 8000

## Fonctionnement

![C.O.R.S. Flowchart](/files/-LFL_5h9d2ge4x_TiWLW)

Supposons que nous avons deux “origins” : <https://attacker.com> et <https://target.com>.

### GET ou FETCH

Par défaut, si l’application [`https://attacker.com`](https://attacker.com/) émet une requête `GET` depuis le browser *(en JavaScript)* vers l’*origin* [`https://target.com`](https://target.com/), celle-ci ne **transmettra aucun des cookies des deux&#x20;*****origins***.

Le browser analysera ensuite certains *headers* C.O.R.S. *(que nous verrons plus tard)* mais en leur absence, il ne transmettra pas la réponse à l’application.\
`Error: No 'Access-Control-Allow-Origin' header is present on the requested resource`

### Autre

S’il s’agit d’une requête **autre que `GET`** *(ou similaire `HEAD`…)* le *browser* envoie une *preflight request* de type `OPTIONS` pour vérifier si la requête est autorisée en fonction de l’ *origin* et de la méthode utilisée.

## Méfiez-vous des Fausses Solutions&#x20;

Ces mécanismes ont été mis en place pour éviter les attaques de type C.S.R.F *(Cross Site Request Forgery)*.

Malheureusement, le premier résultat sur lequel on tombe en recherchant le message d’erreur est le suivant :\
<https://stackoverflow.com/questions/20035101/why-does-my-javascript-get-a-no-access-control-allow-origin-header-is-present>

On y trouve les propositions suivantes :

* “The easy way is to just add the extension in google chrome to allow access using CORS.”\
  <https://chrome.google.com/webstore/detail/allow-control-allow-origi/nlfbmbojpeacfghkpbjhddihlkkiljbi?hl=en-US><br>
* `chrome.exe --user-data-dir="C:/Chrome dev session" --disable-web-security`<br>
* “It’s very simple to solve if you are using PHP. Just add the following script in the beginning of your PHP page which handles the request:”\
  `<?php header('Access-Control-Allow-Origin: *'); ?>`

## Sauvés par le C.O.R.S.

Après la mise en place du *header* `Access-Control-Allow-Origin: *`, la requête émise depuis l’*origin* [`https://attacker.com`](https://attacker.com/) vers  [`https://target.com`](https://target.com/) ne contient pas de cookies.

Il faut activer l’option `withCredentials` de l’objet XHR ou de la fonction `fetch` avec le paramètre `credentials: 'include'`.

La **requête est alors envoyée avec les cookies** mais encore une fois les spécifications C.O.R.S. sont rigoureuses et **il n’est pas possible de récupérer le contenu de la réponse** si le *header* `Access-Control-Allow-Origin` vaut `*`.

Pour pouvoir transmettre des cookies et récupérer la réponse, il faut configurer le *header* **`Access-Control-Allow-Credentials`** mais encore une fois, heureusement que ce n’est pas suffisant. **Cette fonctionnalité ne peut pas être activée si `Access-Control-Allow-Origin` vaut `*`**.

Il faut donc définir une *whitelist* d’*origins* mais malgré tous ces obstacles volontaires, certains vont jusqu’au bout…\
<http://stackoverflow.com/questions/26411480/angularjs-a-wildcard-cannot-be-used-in-the-access-control-allow-origin-he>

{% hint style="danger" %}
Please don’t!!!
{% endhint %}

Après cette ultime étape, n’importe quelle application depuis n’importe quel *origin* peut communiquer librement avec votre API en utilisant les *credentials* présents dans les *cookies* de l’utilisateur actuellement authentifié.

![I Will Never Use Cookies Again](https://wishtackblog.files.wordpress.com/2017/03/i-will-never-use-cookies-again.gif?w=657)

Par précaution, même en l’absence de *cookies*, il vaut mieux éviter d’utiliser la valeur `*` pour le *header* `Access-Control-Allow-Origin` sauf dans le cas d'une API publique.

Il est préférable d’implémenter une logique de *whitelist* sur l’API qui vérifie le contenu du *header* `Origin` de la requête et le renvoie dans le *header* `Access-Control-Allow-Origin` de la réponse en cas d’autorisation réussie.

**La vérification de la&#x20;*****whitelist*****&#x20;doit être stricte !** Il ne suffit pas de vérifier le FQDN.

{% hint style="success" %}
Pensez à implémenter une règle sur votre W\.A.F. (Web Application Firewall), middlewares ou monitoring sécurité pour détecter et bloquer les réponses HTTP contenant le *header* `Access-Control-Allow-Credentials`.
{% endhint %}

{% hint style="danger" %}
**Attention ! Les certificats clients et l’authentification de type "basic auth" sont également considérés comme des&#x20;*****credentials*** et on rencontre les mêmes problèmes qu’avec les *cookies*.
{% endhint %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://guide-api-rest.marmicode.fr/securite-des-apis-rest/c.o.r.s..md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
