Dans ce tutoriel je vous propose de démystifier le principe du CORS.

Le problème

Par défaut, les navigateurs imposent une politique de sécurité same-origin qui limite comment une resource chargée depuis une origine peut intéragir avec une resource chargée depuis une autre origine. Si vous avez déjà essayé de faire des requêtes cross-origin en Ajax vous avez du faire les frais de cette polique et rencontrer l'erreur :

Access to fetch at 'XXXXX' from origin 'YYYYY' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: 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.

CORS à la rescousse

CORS, pour Cross-origin resource sharing, permet, à travers des en-têtes HTTP, d'autoriser un utilisateur l'accès à des resources situées sur une autre origine que le site courant.

Pour indiquer que votre serveur accepte les requêtes cross-origin provenant de l'origin http://domaine-a.localhost vous devez ajouter l'en tête Access-Control-Allow-Origin à votre réponse (cette en-tête peut contenir l'origine ou un joker *).

Access-Control-Allow-Origin: http://domaine-a.localhost

Les requêtes préliminaires preflight

L'en-tête précédente suffit dans le cas de requêtes simples mais pour des cas plus complexes le navigateur va effectuer une requête préliminaire afin de vérifier ce qui est autorisé par le serveur. Cette requête va utiliser la méthode OPTIONS et utilisera le même chemin que la requête originale. Il faudra répondre à cette requête avec des en tête CORS afin de spécifier que vous acceptez les en-têtes et les méthodes qui vous seront envoyées.

Access-Control-Allow-Origin: http://domaine-a.localhost
Access-Control-Allow-Headers: X-Requested-With, Content-Type
Access-Control-Allow-Methods: POST, GET
  • Access-Control-Allow-Headers permet de spécifier les en-têtes supplémentaires qui sont acceptées en cross-origin
  • Access-Control-Allow-Methods permet de limiter les méthodes qui seront utilisables dans le cas d'une requête cross origin.

Et les cookies ?

Les cookies ne peuvent pas être envoyés entre 2 domaines qui ont une racine différente. En revanche il est tout à fait possible d'envoyer les cookies d'un domaine a.domain.ltd vers un domaine b.domain.ltd. Pour cela il y a plusieurs prérequis :

  • Le cookie doit être enregistré pour le domaine racine : Set-Cookie: clef=valeur; Domain=domain.ltd; Path=/; Expires=Wed, 21 Oct 2020 07:28:00 GMT; HttpOnly
  • On doit ensuite spécifier que l'on souhaite inclure les en-têtes cookies
fetch('https://domain.ltd', {
  credentials: 'include'  
})
  • Enfin le serveur doit répondre à la requête avec un Access-Control-Allow-Origin qui ne soit pas un joker * et doit inclure une nouvelle en tête : Access-Control-Allow-Credentials: true

Et si je n'ai pas la main sur le serveur ?

Si vous n'avez pas la main sur le serveur la seule solution pour contourner la politique same-origin est de créer un proxy vers l'origine que vous souhaitez appeler qui lui renverra les en-têtes CORS.

Quelques librairies

Voici quelques librairies pour vous aider à mettre en place facilement les en-têtes CORS sur votre application.