Chaque développeur web a probablement un jour été confronté au message énigmatique Access to fetch at '...' has been blocked by CORS policy dans la console de son navigateur. Cette erreur, bien que fréquente, révèle souvent une incompréhension des mécanismes de sécurité fondamentaux du web. Ce guide complet a pour ambition de démystifier le CORS (Cross-Origin Resource Sharing) en partant de ses principes fondamentaux, afin que vous puissiez non seulement résoudre ces problèmes, mais aussi comprendre en profondeur leur raison d'être et bâtir des applications plus robustes.
Qu'est-ce que la Politique de Même Origine (SOP) ?
Les navigateurs web mettent en œuvre une règle de sécurité cruciale : la Politique de Même Origine (SOP - Same-Origin Policy). Cette politique dicte qu'un script ou une application web chargé depuis une origine ne peut interagir qu'avec des ressources provenant de la même origine. Une origine est définie par la combinaison de son protocole (HTTP, HTTPS), de son nom d'hôte (domaine) et de son port.
https://example.com/page1 → https://example.com/page2 ✅ Même origine https://example.com → http://example.com ❌ Protocole différent https://example.com → https://api.example.com ❌ Nom d'hôte différent https://example.com → https://example.com:8080 ❌ Port différent
La SOP est une barrière essentielle qui empêche les sites malveillants d'accéder sans permission à des données sensibles sur d'autres domaines, comme vos informations bancaires via des requêtes API non autorisées, protégées par vos cookies.
Qu'est-ce que le CORS ?
Le CORS (Cross-Origin Resource Sharing, ou Partage de Ressources Trans-origines) est une spécification qui, tout en respectant l'esprit de la SOP, permet aux serveurs de déléguer de manière contrôlée l'accès à leurs ressources depuis des origines différentes. C'est un contrat de confiance où un serveur indique explicitement, via des en-têtes HTTP spécifiques dans ses réponses, quels sont les domaines autorisés à interagir avec lui. Sans CORS, toute requête provenant d'une origine différente serait systématiquement bloquée par le navigateur.
Comment Fonctionne le CORS ?
Les Requêtes Simples
Certaines requêtes HTTP sont considérées comme "simples" par la spécification CORS. Il s'agit généralement des requêtes utilisant les méthodes GET ou POST (avec un type de contenu spécifique comme application/x-www-form-urlencoded, multipart/form-data, ou text/plain), et n'incluant pas d'en-têtes personnalisés. Pour ces requêtes, le navigateur envoie directement la demande et examine les en-têtes de la réponse pour déterminer si l'accès est autorisé.
// Le navigateur envoie :
GET /api/data HTTP/1.1
Host: api.example.com
Origin: https://myapp.com
// Le serveur répond :
HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://myapp.com
Content-Type: application/json
{"data": "..."}
Les Requêtes Pré-vol (OPTIONS)
Pour les requêtes dites "non-simples", c'est-à-dire celles qui utilisent des méthodes HTTP autres que GET/POST (comme PUT, DELETE, PATCH), qui incluent des en-têtes HTTP personnalisés, ou qui ont un type de contenu complexe (par exemple application/json), le navigateur adopte une approche plus prudente. Avant d'envoyer la véritable requête, il effectue une "requête pré-vol" (preflight request) en utilisant la méthode OPTIONS. Cette requête préliminaire a pour but de s'assurer auprès du serveur que la requête principale est permise.
// 1. Le navigateur envoie la requête pré-vol : OPTIONS /api/users HTTP/1.1 Host: api.example.com Origin: https://myapp.com Access-Control-Request-Method: DELETE Access-Control-Request-Headers: Content-Type, Authorization // 2. Le serveur répond avec les méthodes/en-têtes autorisés : HTTP/1.1 204 No Content Access-Control-Allow-Origin: https://myapp.com Access-Control-Allow-Methods: GET, POST, PUT, DELETE Access-Control-Allow-Headers: Content-Type, Authorization Access-Control-Max-Age: 86400 // 3. Le navigateur envoie la requête réelle (uniquement si la pré-vol réussit)
Les En-têtes de Réponse CORS
Access-Control-Allow-Origin: https://myapp.com // Quelles origines peuvent accéder Access-Control-Allow-Methods: GET, POST, PUT // Méthodes HTTP autorisées Access-Control-Allow-Headers: Content-Type, Auth // En-têtes de requête autorisés Access-Control-Allow-Credentials: true // Autorise les cookies/authentification Access-Control-Max-Age: 86400 // Met en cache la pré-vol (secondes) Access-Control-Expose-Headers: X-Request-Id // En-têtes lisibles par JS
Configuration Serveur pour CORS
import cors from 'cors';
app.use(cors({
origin: ['https://myapp.com', 'https://staging.myapp.com'],
methods: ['GET', 'POST', 'PUT', 'DELETE'],
allowedHeaders: ['Content-Type', 'Authorization'],
credentials: true,
maxAge: 86400
}));
location /api/ {
add_header Access-Control-Allow-Origin "https://myapp.com" always;
add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE" always;
add_header Access-Control-Allow-Headers "Content-Type, Authorization" always;
if ($request_method = OPTIONS) {
return 204;
}
}
header("Access-Control-Allow-Origin: https://myapp.com");
header("Access-Control-Allow-Methods: GET, POST, PUT, DELETE");
header("Access-Control-Allow-Headers: Content-Type, Authorization");
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
http_response_code(204);
exit;
}
Erreurs CORS Fréquentes à Éviter
- Utilisation de
Access-Control-Allow-Origin: *avec des identifiants (credentials) : Le navigateur bloquera systématiquement une telle configuration. Si votre API nécessite l'envoi de cookies ou d'en-têtes d'autorisation (c'est-à-dire queAccess-Control-Allow-Credentialsest àtrue), vous devez spécifier une ou plusieurs origines exactes, et non un wildcard (*). - Considérer CORS comme une protection API serveur-à-serveur : CORS est une fonctionnalité de sécurité implémentée par les navigateurs web. Elle ne protège absolument pas votre API contre les requêtes effectuées directement depuis un autre serveur. Assurez-vous toujours de mettre en place une authentification et une autorisation robustes côté serveur pour toutes vos requêtes, indépendamment du CORS.
- Oublier le drapeau
alwaysdans Nginx : Lorsque vous configurez Nginx pour les en-têtes CORS, l'omission du mot-cléalwayssignifie que les en-têtes ne seront pas inclus dans les réponses d'erreur (codes 4xx, 5xx), ce qui peut compliquer le débogage. - Ne pas gérer les requêtes OPTIONS : Si votre serveur renvoie une erreur 404 (Non Trouvé) ou 405 (Méthode Non Autorisée) pour une requête OPTIONS, toutes les requêtes pré-vol échoueront, empêchant ainsi les requêtes réelles de type PUT, DELETE ou avec des en-têtes personnalisés d'aboutir.
Découvrez Nos Outils Gratuits pour Développeurs
Encodez des URLs, décodez du Base64, et formatez du JSON en un instant. Simples, rapides et efficaces.