Qu'est-ce que CORS (Cross-Origin Resource Sharing) ?

Mis à jour : septembre 2026

CORS est un mécanisme du navigateur où un serveur déclare les autres origines autorisées à l’appeler, assouplissant sciemment la politique de même origine. Deux recadrages dissipent l’essentiel de la confusion : c’est le navigateur qui l’applique (pas le serveur — c’est pourquoi curl fonctionne), et c’est le serveur qui le corrige (pas votre frontend — c’est pourquoi aucune quantité de JavaScript n’y change rien). Tout le reste, ce sont des headers.

Points clés

QuestionRéponse
Le fondementLa politique de même origine (same-origin policy) : par défaut, les scripts ne peuvent pas lire les réponses d’autres origines
Une origineschéma + hôte + port — les trois doivent correspondre
CORSDes headers serveur qui autorisent des origines précises ; le navigateur applique
Requête préliminaire (preflight)Un OPTIONS “puis-je ?” avant les requêtes non simples
La vérité éternelleLes erreurs CORS se corrigent sur le serveur, point final

Tout le protocole, sur le fil

# Preflight : le navigateur demande avant un PUT avec un header d'authentification
OPTIONS /classes/Product HTTP/1.1
Origin: https://app.example.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: x-parse-session-token

# Le bon pour accord du serveur
HTTP/1.1 204 No Content
Access-Control-Allow-Origin: https://app.example.com   ← cette origine peut lire
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: x-parse-session-token
Access-Control-Max-Age: 7200         ← mettez cette réponse en cache ; pas de preflight répété

# Alors, et seulement alors, la vraie requête part.

Ce que cela donne depuis le code applicatif — et la vérité de plateforme que montrent les onglets : CORS est une affaire de navigateur, que les apps natives ne rencontrent jamais :

// Browser JavaScript — Back4app JS SDK
// A cross-origin call that just works: the platform answers the
// preflight and sends the CORS headers, so the browser lets it through
Parse.initialize('APP_ID', 'JS_KEY');
Parse.serverURL = 'https://parseapi.back4app.com'; // different origin than your site

const products = await new Parse.Query('Product').find();
// No proxy hacks, no "disable CORS" — the server side is configured correctly.

Le flux, tranché

Comment un navigateur tranche une requête cross-originLes requêtes de même origine passent directement ; les requêtes cross-origin simples sont envoyées et leur réponse est contrôlée à la recherche d'un header allow-origin ; les requêtes non simples déclenchent d'abord un preflight OPTIONS, et tout header manquant ou non concordant amène le navigateur à bloquer la réponse pour la page.

oui

non

oui

non

le header correspond à l'origine

absent / non concordant

Un script émet une requête

Même origine ?

Passe, sans CORS

Requête simple ?
(GET/HEAD/POST, headers de la safelist)

Envoi ; contrôle de la réponse :
Access-Control-Allow-Origin

Preflight OPTIONS d'abord

Réponse lisible

Bloquée par le navigateur
(l'erreur de la console)

Les requêtes de même origine passent directement ; les requêtes cross-origin simples sont envoyées et leur réponse est contrôlée à la recherche d'un header allow-origin ; les requêtes non simples déclenchent d'abord un preflight OPTIONS, et tout header manquant ou non concordant amène le navigateur à bloquer la réponse pour la page.

Deux détails portent l’essentiel des sessions de débogage : une requête simple (GET/HEAD/POST avec des headers de la safelist et des content types basiques) échappe au preflight — c’est pourquoi ajouter un header Authorization “casse” soudain un endpoint qui fonctionnait ; et les requêtes avec identifiants resserrent tout — les cookies ne circulent qu’avec Access-Control-Allow-Credentials: true plus une origine exacte, jamais le wildcard, selon la spécification.

Comment corriger les erreurs CORS courantes (erreur → cause → correctif)

La console afficheCe qui s’est réellement passéCorrectif (toujours côté serveur)
No ‘Access-Control-Allow-Origin’ headerLe serveur n’a jamais autorisé votre origineAjoutez votre origine à la liste autorisée
Origin not allowed by Access-Control-Allow-OriginLa liste existe ; vous n’y figurez pasAjoutez le schéma+hôte+port exact
Response to preflight… doesn’t passOPTIONS non géré ou headers incompletsRépondez à OPTIONS avec méthodes/headers
Wildcard ’*’ cannot be used with credentialsCookies + * — combinaison interditeListez les origines explicitement
Request header not allowedHeader personnalisé absent de la liste autoriséeAjoutez-le à Access-Control-Allow-Headers

Et l’anti-correctif qui mérite d’être nommé : désactiver via un flag du navigateur ou passer par des proxies de dev permissifs rend l’erreur invisible sur votre machine uniquement — le déploiement reste cassé pour les utilisateurs. Le vrai correctif est une configuration serveur qui se compte en minutes.

Cas d’usage courants

  • SPA + API sur des origines différentes — app.example.com qui appelle api.example.com : le cas quotidien pour lequel CORS existe.
  • Développement local — localhost:3000 face à un vrai backend ; autorisez l’origine de dev, ne désactivez pas le bouclier.
  • API publiques — origine wildcard, sans identifiants : correct et sûr pour des données réellement publiques.
  • Plateformes multi-frontend — plusieurs apps, un backend, une liste explicite d’origines par environnement.
  • Backends BaaS — la plateforme répond aux preflights et envoie les headers ; votre travail se réduit à déclarer les origines autorisées.

Wildcard vs. origines explicites : matrice de décision

ConfigurationPertinent quand…Jamais quand…
Wildcard *API publique, sans identifiantsDes cookies ou des sessions utilisateur existent
Liste explicite d’originesAPI privées, apps avec identifiants— (c’est la réponse par défaut)
Refléter l’origine de la requêtePresque jamaisCombiné avec des identifiants — la brèche classique
Listes par environnementHygiène dev/staging/prodLa prod hérite des entrées localhost du dev

Un recadrage sécurité referme la matrice : CORS n’est pas du contrôle d’accès — les apps natives et les serveurs l’ignorent complètement, il protège donc les utilisateurs du navigateur contre les sites malveillants, pas votre API contre ses appelants. L’authentification et les permissions au niveau de la couche de données font ce travail ; CORS décide seulement quels scripts de quels sites peuvent lire les réponses.

Limites et trade-offs

  • Il ne régit que les navigateurs. Tout ce qui n’est pas un navigateur passe outre — ne confondez jamais une liste d’origines avec une autorisation.
  • Les preflights coûtent un aller-retour sur les requêtes non simples ; la mise en cache via Access-Control-Max-Age est le correctif bon marché et oublié.
  • Une mauvaise configuration échoue en mode fermé, et bruyamment — bien pour la sécurité, brutal pour le débogage sans le tableau erreur→correctif ci-dessus.
  • Les listes d’origines sont un état d’environnement. Des origines de staging se glissent dans les configurations de production ; auditez la liste comme n’importe quel identifiant.
  • CORS ≠ CSRF ≠ CSP. Des sigles voisins, des défenses distinctes — les cookies ont toujours besoin d’une protection SameSite/token, et les pages d’une politique de contenu, CORS ne gérant que la lecture cross-origin.

CORS sur Back4app

Back4app est une plateforme open-source de Backend as a Service (BaaS) qui combine une base de données gérée, des API REST et GraphQL générées automatiquement, l’authentification, le stockage de fichiers et des fonctions serverless avec Cloud Code. La corvée CORS est réglée d’office : les API de la plateforme répondent aux preflights et envoient les bons headers, si bien que les apps navigateur appellent le backend depuis les origines autorisées sans bricolage de proxy — l’onglet JavaScript ci-dessus est toute l’expérience — tandis que les onglets Flutter, Swift et Kotlin démontrent une vérité plus discrète : les clients natifs ne rencontrent jamais la cérémonie. La vraie sécurité reste là où elle doit être : sessions, ACL et permissions au niveau de la classe appliquées côté serveur à chaque requête, quelle que soit l’origine.

Questions fréquentes

Qu'est-ce que CORS, en termes simples ?

Le système de permissions du navigateur pour les appels d'API entre sites. Par défaut, les scripts d'une origine ne peuvent pas lire les réponses d'une autre — c'est la politique de même origine (same-origin policy). CORS est la façon dont un serveur donne son accord : des headers de réponse qui déclarent les origines, méthodes et headers qu'il accepte. Le navigateur applique ; le serveur déclare ; votre code frontend n'est que le messager.

Qu'est-ce qu'une origine, exactement ?

Le triplet schéma, hôte et port. https://app.example.com et https://api.example.com sont des origines différentes (l'hôte diffère) ; tout comme les versions http et https d'un même site (le schéma diffère), et :3000 vs :8080 en développement (le port diffère). Chaque décision CORS compare ces trois parties — rien d'autre dans l'URL ne compte.

Qu'est-ce qui provoque l'erreur CORS classique ?

Le navigateur a appelé une autre origine, et la réponse ne contenait pas de header Access-Control-Allow-Origin correspondant à la vôtre — le navigateur a donc empêché votre script de la lire. La requête a souvent bien atteint le serveur ; le blocage a lieu côté client, à la lecture. C'est pourquoi le correctif relève toujours de la configuration serveur, jamais du code frontend.

Qu'est-ce qu'une requête préliminaire (preflight) ?

La vérification de permission que le navigateur effectue à l'avance pour les requêtes non simples : avant d'envoyer un PUT, un DELETE ou quoi que ce soit avec des headers personnalisés comme un token d'autorisation, il envoie une requête OPTIONS qui demande "puis-je ?". Les headers du serveur répondent quelles méthodes, quels headers et quelles origines sont autorisés ; alors seulement la vraie requête part. Les preflights peuvent être mis en cache via Access-Control-Max-Age.

Pourquoi ma requête fonctionne-t-elle avec curl mais échoue-t-elle dans le navigateur ?

Parce que CORS est une contrainte appliquée par le navigateur, pas un rejet du serveur. Des outils comme curl et les apps mobiles natives n'ont pas de politique de même origine, et lisent donc la réponse sans broncher. Le navigateur applique la politique pour le compte de son utilisateur — la différence que vous constatez est le point d'application, et c'est aussi la preuve que CORS n'est pas du contrôle d'accès.

Access-Control-Allow-Origin: * est-il sûr ?

Pour des API réellement publiques et sans identifiants, oui. Le wildcard est interdit en mode avec identifiants — les navigateurs refusent par conception d'y associer des cookies — et refléter des origines arbitraires tout en autorisant les identifiants est la mauvaise configuration classique qui transforme CORS de bouclier en brèche. Les API privées listent les origines explicitement.

Puis-je simplement désactiver CORS pour corriger l'erreur ?

Seulement au sens où retirer un détecteur de fumée éteint un incendie. Les flags du navigateur et les proxies permissifs masquent le symptôme sur votre machine tout en livrant la panne à chaque utilisateur. Le bon correctif prend quelques minutes : configurez le serveur (ou le dashboard de la plateforme) pour autoriser les origines censées l'appeler.

Quelle est la différence entre CORS, CSRF et CSP ?

Trois rôles différents. CORS régit les origines autorisées à lire les réponses d'un serveur. CSRF est une attaque — profiter des cookies d'un utilisateur pour forger des requêtes — contrée par des tokens et des cookies SameSite, pas par CORS. CSP est la politique propre à une page qui restreint ce qu'elle peut charger et exécuter, l'outil anti-XSS. Des sigles voisins, des mécanismes orthogonaux.

Termes associés

À comparer avec

Lectures recommandées

Prêt à construire votre backend ?

Lancez votre projet sur Back4app en quelques minutes — base de données, authentification, API et Cloud Code inclus. Sans carte bancaire.

Écrit et révisé par Back4app Engineering, Back4app Engineering · Publié le 2026-09-11