Omfattande guide för att lösa problemet med att cookies inte skickas i Cross-Origin-förfrågningar (CORS)

Om du har stött på ett scenario där servern korrekt anger cookien (synlig i webbläsarens svar), men i efterföljande förfrågningar inte returnerar webbläsaren cookien till servern, är den här guiden för dig. Detta problem uppstår nästan alltid när frontend och backend i ditt projekt finns på två olika domäner eller portar — till exempel frontend på app.example.com och API på api.example.com.

Varför händer detta?

Moderna webbläsare tillämpar två strikta säkerhetspolicyer för att förhindra CSRF-attacker och sessionskapning:

  1. CORS-policy: Som standard tillåter inte webbläsaren att förfrågningar mellan domäner inkluderar autentiseringsuppgifter (som cookies) om inte servern uttryckligen tillåter detta.
  2. SameSite-policy: Från och med Chrome 80 behandlas cookies som standard med SameSite=Lax-beteende, vilket innebär att de inte kommer att skickas i förfrågningar mellan domäner om de inte uttryckligen definieras med SameSite=None.

Den viktiga punkten är att för att lösa detta problem måste både klient- och serversidan konfigureras korrekt. Det räcker inte att bara ändra en sida.

Steg 1: Korrekt serverkonfiguration

Tre gyllene regler på serversidan

Regel 1 — Aktivera autentiseringsuppgifter: Serverns svarshuvud måste innehålla följande värde:

Access-Control-Allow-Credentials: true

Regel 2 — Inga jokertecken: När autentiseringsuppgifter är aktiverade kan du inte använda jokertecknet * i Access-Control-Allow-Origin-huvudet. Du måste ange den exakta fullständiga domänadressen för frontend:

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

Regel 3 — Cookie-attribut: Cookien måste ställas in med två attribut: SameSite=None och Secure. Utan dessa två attribut kommer webbläsaren att lagra cookien men aldrig skicka den i förfrågningar mellan domäner.

Exempelkod i Node.js (Express)

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

const app = express();

app.use(cors({
  origin: 'https://app.example.com', // Exakt frontend-domän, utan /
  credentials: true
}));

app.post('/login', (req, res) => {
  res.cookie('session_token', 'abc123', {
    httpOnly: true,   // Förhindrar JavaScript-åtkomst till cookien
    secure: true,     // Skickas endast via HTTPS
    sameSite: 'none', // Tillåter sändning i Cross-Origin-förfrågningar
    maxAge: 24 * 60 * 60 * 1000
  });
  res.json({ message: 'Inloggning lyckades' });
});

Exempelkod i PHP

<?php
// Ange den exakta frontend-domänen, inte *
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");

// Svar på Preflight-förfrågan
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
    http_response_code(204);
    exit;
}

// Ställa in cookien med nödvändiga attribut
setcookie('session_token', 'abc123', [
    'expires'  => time() + 86400,
    'path'     => '/',
    'secure'   => true,      // Obligatoriskt
    'httponly' => true,
    'samesite' => 'None'     // Obligatoriskt för Cross-Origin
]);

Notera: Om du använder Laravel, ställ in supports_credentials till true i filen config/cors.php och lägg till frontend-domänen i arrayen allowed_origins.

Steg 2: Korrekt klientkonfiguration (frontend)

Även med fullständig serverkonfiguration kommer webbläsaren fortfarande inte att skicka cookies om du inte uttryckligen förklarar på klientsidan att denna förfrågan är "med autentiseringsuppgifter".

Använda Fetch API

fetch('https://api.example.com/user/profile', {
  method: 'GET',
  credentials: 'include'  // Denna rad är nyckeln till att lösa problemet
})
  .then(res => res.json())
  .then(data => console.log(data));

Använda Axios

// För en specifik förfrågan
axios.get('https://api.example.com/user/profile', {
  withCredentials: true
});

// Eller globalt för hela projektet
axios.defaults.withCredentials = true;

Felsökningschecklista

Om problemet kvarstår efter att ha tillämpat ovanstående, kontrollera dessa punkter i ordning:

  • Är båda sidor på HTTPS? Attributet Secure innebär att cookien endast fungerar över krypterade anslutningar. Om din webbplats är på HTTP kommer webbläsaren inte att acceptera cookien. (Undantag: utvecklingsmiljö på localhost)
  • Är Origin-adressen exakt? Adressen Access-Control-Allow-Origin måste exakt matcha den URL du ser i webbläsaren. Även en skillnad i www eller ett avslutande snedstreck / kommer att orsaka misslyckande.
  • Är OPTIONS-förfrågan framgångsrik? I fliken Network i webbläsarens utvecklarverktyg, kontrollera Preflight-förfrågan (med OPTIONS-metoden). Denna förfrågan måste besvaras med kod 200 eller 204 och korrekta CORS-huvuden.
  • Är cookien lagrad? I webbläsaren, gå till DevTools ← Application ← Cookies och försäkra dig om att cookien är lagrad med attributen Secure och SameSite=None.
  • Har du en proxy eller mellanliggande brandvägg? Ibland skriver Cloudflare eller webbservrar som Nginx om huvuden. Kontrollera även deras konfiguration.

Sammanfattning

Att skicka cookies i förfrågningar mellan domäner kräver samordning av tre faktorer: servern med Access-Control-Allow-Credentials: true och exakt Origin, cookien med attributen SameSite=None; Secure, och klienten med aktivering av credentials: 'include' eller withCredentials: true. Genom att följa dessa tre punkter kommer problemet att lösas fullständigt.


Pålitlig infrastruktur, sinnesro för utvecklare

Korrekt implementering av CORS och cookiehantering är bara en del av historien; infrastrukturen som ditt projekt körs på spelar också en avgörande roll för tjänstens stabilitet och säkerhet:

Radib Hosting — Höghastighetswebbhotell med fullt stöd för gratis SSL och standardkonfiguration av huvuden; ett idealiskt val för att hosta frontend och backend av dina projekt.

Radib Virtual Server — Om ditt projekt kräver full åtkomst, dedikerade resurser och frihet i webbserverkonfiguration (Nginx/Apache), är Radib virtuella servrar med kraftfull hårdvara och stabilt nätverk det bästa valet för professionella API:er.

Radib Debugging and Security Services — Om du kämpar med komplexa CORS-fel, autentiseringsproblem eller säkerhetsutmaningar, finns Radibs tekniska team, med djup erfarenhet av felsökning och säkring av webbapplikationer, här för att hjälpa dig lösa problemet från roten.

 

Hjälpte svaret dig? 112 användare blev hjälpta av detta svar (112 Antal röster)