Access-Control-Allow-Origin
Utilisation
Remarque
CORS (Cross-Origin Resource Sharing) est un mécanisme du navigateur qui empêche les pages web de lire les réponses servies par une origine différente, sauf si le serveur autorise explicitement l’accès. Les navigateurs ajoutent automatiquement l’en-tête Origin aux requêtes cross-origin. JavaScript ne peut pas modifier l’en-tête Origin.
Chaque réponse CORS inclut Access-Control-Allow-Origin pour indiquer au navigateur si le code front-end d’une origine donnée est autorisé à lire la réponse. Sans valeur correspondante, le navigateur empêche la réponse de parvenir à JavaScript.
Les serveurs qui choisissent d’autoriser l’accès disposent de trois options : un caractère générique, une origine explicite, ou null. La plupart des API en production sélectionnent l’origine dynamiquement en comparant l’en-tête de requête Origin entrant à une liste d’autorisation. Lorsque l’origine correspond, le serveur renvoie la valeur à l’identique. Comme la réponse varie selon la requête, un en-tête Vary: Origin est nécessaire pour que les caches stockent une copie distincte par origine.
Ce qui déclenche CORS
Tout appel fetch() ou XMLHttpRequest vers une origine différente déclenche l’application de CORS. Le chargement de polices via @font-face, les textures WebGL et canvas.drawImage() sur des images cross-origin déclenchent également des contrôles CORS. Les requêtes portant des en-têtes personnalisés, des méthodes non simples comme PUT, DELETE ou PATCH, ou un Content-Type application/json déclenchent une requête préliminaire OPTIONS avant l’envoi de la requête réelle. La navigation standard, comme cliquer sur des liens ou charger des pages dans le navigateur, ne déclenche pas CORS.
* (caractère générique)
Autorise n’importe quelle origine à lire la réponse. Le caractère générique n’est valide que pour les requêtes sans identifiants.
Access-Control-Allow-Origin: *
Remarque
Le caractère générique est incompatible avec les requêtes authentifiées. Lorsque Access-Control-Allow-Credentials vaut true, le serveur doit renvoyer une origine explicite.
Origine explicite
Une valeur d’origine unique composée d’un schéma, d’un nom d’hôte et d’un port facultatif. C’est l’approche standard pour les API réservées à des appelants connus.
Access-Control-Allow-Origin: https://example.com
Une seule origine est autorisée par réponse. Les serveurs qui prennent en charge plusieurs origines inspectent l’en-tête de requête Origin et répondent avec la valeur correspondante, en ajoutant Vary: Origin à la réponse.
null
Représente une origine opaque ou sensible du point de vue de la confidentialité. Certains documents en bac à sable et certaines URL de fichiers locaux envoient null comme origine.
Access-Control-Allow-Origin: null
Remarque
Répondre avec null est déconseillé. Les documents malveillants issus d’iframes en bac à sable portent eux aussi une origine null, ce qui rend cette valeur facile à falsifier.
Exemple
Un serveur reflète dynamiquement l’origine de la requête et inclut un en-tête Vary pour un comportement de cache correct.
Access-Control-Allow-Origin: https://example.com
Vary: Origin
Un CDN public qui sert des ressources statiques à tout appelant utilise le caractère générique.
Access-Control-Allow-Origin: *
Une réponse cross-origin authentifiée associe l’origine explicite à l’en-tête d’identifiants.
Access-Control-Allow-Origin: https://dashboard.example.re
Access-Control-Allow-Credentials: true
Vary: Origin
Dépannage
Les requêtes cross-origin échouent lorsque le navigateur ne parvient pas à faire correspondre l’origine de la réponse avec celle de la page appelante.
La console affiche « No ‘Access-Control-Allow-Origin’ header is present on the requested resource. » Le serveur n’a pas inclus l’en-tête du tout. Vérifiez que la configuration CORS côté serveur s’applique bien à la route et à la méthode HTTP concernées. Dans nginx, confirmez que la directive add_header se trouve dans le bon bloc location. Dans Apache, confirmez que Header set est à l’intérieur du
Le caractère générique * ne fonctionne pas avec les requêtes authentifiées. Les navigateurs rejettent les réponses qui associent Access-Control-Allow-Origin: * à Access-Control-Allow-Credentials: true. La solution consiste à lire l’en-tête Origin entrant, à valider la valeur par rapport à une liste d’autorisation, puis à renvoyer l’origine correspondante. Ajoutez Vary: Origin à la réponse afin que les caches stockent une copie distincte par origine.
Réflexion de l’origine sans validation. Renvoyer l’en-tête de requête Origin tel quel sans le confronter à une liste d’autorisation ouvre l’API à n’importe quel domaine. Les attaquants exploitent cela pour dérober des données via une page qu’ils contrôlent. Comparez toujours l’origine entrante à une liste de valeurs de confiance avant de la refléter.
Un CDN met en cache une réponse avec la mauvaise origine. Lorsque le serveur renvoie une valeur d’origine dynamique mais omet Vary: Origin, un CDN stocke la première valeur d’origine et sert la même réponse en cache à toutes les origines suivantes. Ajoutez Vary: Origin à chaque réponse qui reflète une origine dynamique. Dans Cloudflare, cela est géré automatiquement lors de l’utilisation de la transformation managée CORS. Dans les autres CDN, vérifiez que l’origine fait partie de la clé de cache.
La requête préliminaire réussit mais la requête réelle échoue. La réponse OPTIONS contient les en-têtes CORS, mais pas la réponse au GET, POST ou PUT qui suit. De nombreux frameworks serveur traitent OPTIONS séparément des autres méthodes. Assurez-vous que les en-têtes CORS sont ajoutés à tous les types de réponses, et pas uniquement aux réponses préliminaires. Dans Express, placez le middleware CORS avant les gestionnaires de routes afin que chaque réponse traverse le middleware.
Le débogage avec curl montre les bons en-têtes mais le navigateur bloque quand même. Ouvrez les DevTools, allez dans l’onglet Network et inspectez les en-têtes de réponse réellement reçus par le navigateur. Les proxys, répartiteurs de charge ou règles edge de CDN suppriment ou écrasent parfois les en-têtes CORS entre le serveur d’origine et le navigateur. Comparez la sortie de curl à celle des DevTools pour identifier la couche qui supprime l’en-tête.