Guide complet pour résoudre le problème d'envoi de cookies dans les requêtes Cross-Origin (CORS)
Si vous avez rencontré un scénario où le serveur définit correctement le cookie (visible dans la réponse du navigateur), mais que dans les requêtes suivantes, le navigateur ne renvoie pas ce cookie au serveur, ce guide est pour vous. Ce problème survient presque toujours lorsque le frontend et le backend de votre projet se trouvent sur deux domaines ou ports différents — par exemple, le frontend sur app.example.com et l'API sur api.example.com.
Pourquoi cela se produit-il ?
Les navigateurs modernes imposent deux politiques de sécurité strictes pour prévenir les attaques CSRF et le détournement de session :
- Politique CORS : Par défaut, le navigateur n'autorise pas les requêtes entre domaines à inclure des informations d'identification (comme les cookies) à moins que le serveur ne l'autorise explicitement.
- Politique SameSite : À partir de Chrome 80, les cookies sont traités par défaut avec un comportement
SameSite=Lax, ce qui signifie qu'ils ne seront pas envoyés dans les requêtes entre domaines à moins d'être explicitement définis avecSameSite=None.
Le point important est que pour résoudre ce problème, les côtés client et serveur doivent être correctement configurés. Modifier un seul côté ne suffit pas.
Étape 1 : Configuration correcte du serveur
Trois règles d'or côté serveur
Règle 1 — Activer les informations d'identification : L'en-tête de réponse du serveur doit inclure la valeur suivante :
Access-Control-Allow-Credentials: true
Règle 2 — Ne pas utiliser de caractère générique : Lorsque les informations d'identification sont activées, vous ne pouvez pas utiliser le caractère générique * dans l'en-tête Access-Control-Allow-Origin. Vous devez spécifier exactement l'adresse de domaine complète du frontend :
Access-Control-Allow-Origin: https://app.example.com
Règle 3 — Attributs du cookie : Le cookie doit être défini avec deux attributs : SameSite=None et Secure. Sans ces deux attributs, le navigateur stockera le cookie mais ne l'enverra jamais dans les requêtes entre domaines.
Exemple de code en Node.js (Express)
const express = require('express');
const cors = require('cors');
const app = express();
app.use(cors({
origin: 'https://app.example.com', // Domaine exact du frontend, sans /
credentials: true
}));
app.post('/login', (req, res) => {
res.cookie('session_token', 'abc123', {
httpOnly: true, // Empêche l'accès JavaScript au cookie
secure: true, // Envoyé uniquement via HTTPS
sameSite: 'none', // Permet l'envoi dans les requêtes Cross-Origin
maxAge: 24 * 60 * 60 * 1000
});
res.json({ message: 'Connexion réussie' });
});
Exemple de code en PHP
<?php
// Spécifiez le domaine exact du frontend, pas *
header("Access-Control-Allow-Origin: https://app.example.com");
header("Access-Control-Allow-Credentials: true");
header("Access-Control-Allow-Headers: Content-Type, Authorization");
header("Access-Control-Allow-Methods: GET, POST, OPTIONS");
// Répondre à la requête Preflight
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
http_response_code(204);
exit;
}
// Définir le cookie avec les attributs requis
setcookie('session_token', 'abc123', [
'expires' => time() + 86400,
'path' => '/',
'secure' => true, // Requis
'httponly' => true,
'samesite' => 'None' // Requis pour Cross-Origin
]);
Remarque : Si vous utilisez Laravel, définissez supports_credentials sur true dans le fichier config/cors.php et ajoutez le domaine du frontend au tableau allowed_origins.
Étape 2 : Configuration correcte du client (frontend)
Même avec une configuration complète du serveur, le navigateur n'enverra toujours pas les cookies à moins que vous ne déclariez explicitement côté client que cette requête est "avec informations d'identification".
Utilisation de Fetch API
fetch('https://api.example.com/user/profile', {
method: 'GET',
credentials: 'include' // Cette ligne est la clé pour résoudre le problème
})
.then(res => res.json())
.then(data => console.log(data));
Utilisation de Axios
// Pour une requête spécifique
axios.get('https://api.example.com/user/profile', {
withCredentials: true
});
// Ou globalement pour l'ensemble du projet
axios.defaults.withCredentials = true;
Liste de vérification pour le dépannage
Si le problème persiste après l'application des étapes ci-dessus, vérifiez ces éléments dans l'ordre :
- ✅ Les deux côtés sont-ils en HTTPS ? L'attribut
Securesignifie que le cookie ne fonctionne que sur des connexions cryptées. Si votre site est en HTTP, le navigateur n'acceptera pas le cookie. (Exception : environnement de développement surlocalhost) - ✅ L'adresse Origin est-elle exacte ? L'adresse
Access-Control-Allow-Origindoit correspondre exactement à l'URL que vous voyez dans le navigateur. Même une différence danswwwou une barre oblique finale/entraînera un échec. - ✅ La requête OPTIONS est-elle réussie ? Dans l'onglet Network des outils de développement du navigateur, vérifiez la requête Preflight (avec la méthode OPTIONS). Cette requête doit être répondue avec le code 200 ou 204 et les en-têtes CORS corrects.
- ✅ Le cookie est-il stocké ? Dans le navigateur, allez dans DevTools ← Application ← Cookies et assurez-vous que le cookie est stocké avec les attributs
SecureetSameSite=None. - ✅ Avez-vous un proxy ou un pare-feu intermédiaire ? Parfois, Cloudflare ou des serveurs web comme Nginx réécrivent les en-têtes. Vérifiez également leur configuration.
Résumé
L'envoi de cookies dans les requêtes entre domaines nécessite la coordination de trois facteurs : le serveur avec Access-Control-Allow-Credentials: true et Origin exact, le cookie avec les attributs SameSite=None; Secure, et le client avec l'activation de credentials: 'include' ou withCredentials: true. En suivant ces trois points, le problème sera complètement résolu.
Infrastructure fiable, tranquillité d'esprit pour les développeurs
La mise en œuvre correcte de CORS et la gestion des cookies ne sont qu'une partie de l'histoire ; l'infrastructure sur laquelle votre projet s'exécute joue également un rôle déterminant dans la stabilité et la sécurité du service :
Hébergement Radib — Hébergement web haute vitesse avec prise en charge complète de SSL gratuit et configuration standard des en-têtes ; un choix idéal pour l'hébergement du frontend et du backend de vos projets.
Serveur Virtuel Radib — Si votre projet nécessite un accès complet, des ressources dédiées et une liberté de configuration du serveur web (Nginx/Apache), les serveurs virtuels Radib avec du matériel puissant et un réseau stable sont le meilleur choix pour les API professionnelles.
Services de débogage et de sécurité Radib — Si vous êtes confronté à des erreurs CORS complexes, des problèmes d'authentification ou des défis de sécurité, l'équipe technique de Radib, avec une expérience approfondie en dépannage et en sécurisation des applications web, est à vos côtés pour résoudre le problème à la racine.


