Das Problem: die Same-Origin Policy
Eine OriginBegriff · OriginDie Kombination aus Schema, Host und Port einer URL, z. B. https://example.com:443 – Grundlage der Same-Origin Policy. besteht aus Schema + Host + Port. Lädt eine Seite von https://app.example.com Daten per fetch() von https://api.example.com, ist das eine Cross-Origin-Anfrage. Ohne Freigabe darf das JavaScript die Antwort nicht lesen – sonst könnte jede Website im Hintergrund mit deinen Cookies dein Webmail oder Online-Banking auslesen.
Zwei Abläufe
Einfache Anfrage
GET, HEAD oder POST mit Standard-Headern gehen direkt raus. Der Browser prüft erst die Antwort.
01GET /orders
Origin: https://app.example.com
- Server verarbeitet die Anfrage
02200 OK
Access-Control-Allow-Origin: https://app.example.com
- Header passt → JavaScript darf lesen
Fehlt der Header, kommt die Antwort trotzdem an – JavaScript sieht nur einen Fehler.
Mit Preflight
Bei PUT/DELETE, eigenen Headern wie Authorization oder Content-Type: application/json fragt der Browser vorher per PreflightBegriff · PreflightEine OPTIONS-Anfrage, mit der der Browser vor einer „nicht-einfachen“ Cross-Origin-Anfrage prüft, ob Methode und Header erlaubt sind. nach.
01OPTIONS /orders
Access-Control-Request-Method: PUT
02204 No Content
Allow-Methods: PUT · Allow-Headers: Authorization
- Erlaubt → jetzt die echte Anfrage
03PUT /orders/42
Authorization: Bearer …
04200 OK
Access-Control-Allow-Origin: https://app.example.com
Schlägt der Preflight fehl, wird die eigentliche Anfrage gar nicht erst gesendet.
Die wichtigsten Header
- Origin
RichtungBrowser → Server
BedeutungVon welcher Origin die Anfrage stammt
- Access-Control-Allow-Origin
RichtungServer → Browser
BedeutungErlaubte Origin (oder * für alle, aber nicht mit Cookies)
- Access-Control-Allow-Methods
RichtungServer → Browser
BedeutungErlaubte HTTP-Methoden (Preflight)
- Access-Control-Allow-Headers
RichtungServer → Browser
BedeutungErlaubte eigene Header (Preflight)
- Access-Control-Allow-Credentials
RichtungServer → Browser
Bedeutungtrue = Cookies/Auth dürfen mitgeschickt werden
- Access-Control-Max-Age
RichtungServer → Browser
BedeutungWie lange der Preflight gecacht werden darf
| Kriterium | Richtung | Bedeutung |
|---|---|---|
| Origin | Browser → Server | Von welcher Origin die Anfrage stammt |
| Access-Control-Allow-Origin | Server → Browser | Erlaubte Origin (oder * für alle, aber nicht mit Cookies) |
| Access-Control-Allow-Methods | Server → Browser | Erlaubte HTTP-Methoden (Preflight) |
| Access-Control-Allow-Headers | Server → Browser | Erlaubte eigene Header (Preflight) |
| Access-Control-Allow-Credentials | Server → Browser | true = Cookies/Auth dürfen mitgeschickt werden |
| Access-Control-Max-Age | Server → Browser | Wie lange der Preflight gecacht werden darf |
Typische Fehler
Wildcard mit Cookies
Allow-Origin: * und credentials: 'include' schließen sich aus. Die konkrete Origin zurückgeben.
Preflight läuft in die Auth
Die OPTIONS-Anfrage trägt kein Token. Middleware, die sie mit 401 abweist, bricht CORS.
Header doppelt oder verschluckt
Proxy und App setzen beide CORS-Header – oder der Proxy entfernt sie. CORS an genau einer Stelle konfigurieren.
Caching ohne Vary
Wird die Origin dynamisch zurückgegeben, gehört Vary: Origin dazu, sonst liefert ein Cache die falsche Freigabe.