Uitgebreide handleiding voor het oplossen van het probleem dat cookies niet worden verzonden in Cross-Origin-verzoeken (CORS)

Als u te maken heeft gehad met een scenario waarin de server de cookie correct instelt (zichtbaar in het antwoord van de browser), maar bij volgende verzoeken de browser die cookie niet aan de server retourneert, is deze handleiding voor u bedoeld. Dit probleem doet zich bijna altijd voor wanneer de frontend en backend van uw project zich op twee verschillende domeinen of poorten bevinden — bijvoorbeeld frontend op app.example.com en API op api.example.com.

Waarom gebeurt dit?

Moderne browsers hanteren twee strikte beveiligingsbeleidsregels om CSRF-aanvallen en sessie-kaping te voorkomen:

  1. CORS-beleid: Standaard staat de browser niet toe dat verzoeken tussen domeinen referenties (zoals cookies) bevatten, tenzij de server dit expliciet toestaat.
  2. SameSite-beleid: Vanaf Chrome 80 worden cookies standaard behandeld met SameSite=Lax-gedrag, wat betekent dat ze niet worden verzonden in verzoeken tussen domeinen, tenzij ze expliciet zijn gedefinieerd met SameSite=None.

Het belangrijke punt is dat om dit probleem op te lossen, zowel de client- als de serverzijde correct moeten worden geconfigureerd. Alleen de ene kant aanpassen is niet voldoende.

Stap 1: Correcte serverconfiguratie

Drie gouden regels aan de serverzijde

Regel 1 — Referenties inschakelen: De server-antwoordheader moet de volgende waarde bevatten:

Access-Control-Allow-Credentials: true

Regel 2 — Geen wildcard: Wanneer referenties zijn ingeschakeld, kunt u het *-wildcardteken niet gebruiken in de Access-Control-Allow-Origin-header. U moet het exacte volledige domeinadres van de frontend opgeven:

Access-Control-Allow-Origin: https://app.example.com

Regel 3 — Cookie-attributen: De cookie moet worden ingesteld met twee attributen: SameSite=None en Secure. Zonder deze twee attributen slaat de browser de cookie wel op, maar verzendt deze nooit in verzoeken tussen domeinen.

Voorbeeldcode in Node.js (Express)

const express = require('express');
const cors = require('cors');

const app = express();

app.use(cors({
  origin: 'https://app.example.com', // Exact frontend-domein, zonder /
  credentials: true
}));

app.post('/login', (req, res) => {
  res.cookie('session_token', 'abc123', {
    httpOnly: true,   // Voorkomt JavaScript-toegang tot de cookie
    secure: true,     // Alleen verzenden via HTTPS
    sameSite: 'none', // Sta verzending toe in Cross-Origin-verzoeken
    maxAge: 24 * 60 * 60 * 1000
  });
  res.json({ message: 'Aanmelding succesvol' });
});

Voorbeeldcode in PHP

<?php
// Geef het exacte frontend-domein op, niet *
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");

// Antwoord op Preflight-verzoek
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
    http_response_code(204);
    exit;
}

// De cookie instellen met de vereiste attributen
setcookie('session_token', 'abc123', [
    'expires'  => time() + 86400,
    'path'     => '/',
    'secure'   => true,      // Vereist
    'httponly' => true,
    'samesite' => 'None'     // Vereist voor Cross-Origin
]);

Opmerking: Als u Laravel gebruikt, stel dan supports_credentials in op true in het bestand config/cors.php en voeg het frontend-domein toe aan de allowed_origins-array.

Stap 2: Correcte clientconfiguratie (frontend)

Zelfs met een volledige serverconfiguratie zal de browser nog steeds geen cookies verzenden, tenzij u aan de clientzijde expliciet verklaart dat dit verzoek "met referenties" is.

Fetch API gebruiken

fetch('https://api.example.com/user/profile', {
  method: 'GET',
  credentials: 'include'  // Deze regel is de sleutel tot het oplossen van het probleem
})
  .then(res => res.json())
  .then(data => console.log(data));

Axios gebruiken

// Voor een specifiek verzoek
axios.get('https://api.example.com/user/profile', {
  withCredentials: true
});

// Of globaal voor het hele project
axios.defaults.withCredentials = true;

Probleemoplossingschecklist

Als het probleem na het toepassen van het bovenstaande nog steeds bestaat, controleer dan deze items in volgorde:

  • Staan beide zijden op HTTPS? Het Secure-attribuut betekent dat de cookie alleen werkt via versleutelde verbindingen. Als uw site op HTTP staat, accepteert de browser de cookie niet. (Uitzondering: ontwikkelomgeving op localhost)
  • Is het Origin-adres exact? Het Access-Control-Allow-Origin-adres moet exact overeenkomen met de URL die u in de browser ziet. Zelfs een verschil in www of een afsluitende slash / zal tot mislukking leiden.
  • Is het OPTIONS-verzoek succesvol? Controleer in het Network-tabblad van de browserontwikkeltools het Preflight-verzoek (met de OPTIONS-methode). Dit verzoek moet worden beantwoord met code 200 of 204 en de juiste CORS-headers.
  • Is de cookie opgeslagen? Ga in de browser naar DevTools ← Application ← Cookies en zorg ervoor dat de cookie is opgeslagen met de attributen Secure en SameSite=None.
  • Heeft u een proxy of tussenliggende firewall? Soms herschrijven Cloudflare of webservers zoals Nginx headers. Controleer ook hun configuratie.

Samenvatting

Het verzenden van cookies in verzoeken tussen domeinen vereist coördinatie van drie factoren: de server met Access-Control-Allow-Credentials: true en exacte Origin, de cookie met de attributen SameSite=None; Secure, en de client met activering van credentials: 'include' of withCredentials: true. Door deze drie punten te volgen, wordt het probleem volledig opgelost.


Betrouwbare infrastructuur, gemoedsrust voor ontwikkelaars

Correcte implementatie van CORS en cookiebeheer is slechts een deel van het verhaal; de infrastructuur waarop uw project draait, speelt ook een beslissende rol in de stabiliteit en veiligheid van de dienst:

Radib Hosting — Snelle webhosting met volledige ondersteuning voor gratis SSL en standaard headerconfiguratie; een ideale keuze voor het hosten van de frontend en backend van uw projecten.

Radib Virtual Server — Als uw project volledige toegang, toegewijde bronnen en vrijheid in webserverconfiguratie (Nginx/Apache) vereist, zijn Radib virtuele servers met krachtige hardware en een stabiel netwerk de beste keuze voor professionele API's.

Radib Debugging en Beveiligingsdiensten — Als u te maken heeft met complexe CORS-fouten, authenticatieproblemen of beveiligingsuitdagingen, staat het technische team van Radib, met diepgaande ervaring in het oplossen van problemen en het beveiligen van webapplicaties, klaar om u te helpen het probleem bij de wortel aan te pakken.

 

Was dit antwoord nuttig? 112 gebruikers vonden dit artikel nuttig (112 Stemmen)