CORS ist ein Browser-Mechanismus, mit dem ein Server erklärt, welche anderen Origins ihn aufrufen dürfen – eine bewusste Lockerung der Same-Origin-Policy. Zwei Umdeutungen lösen den größten Teil der Verwirrung auf: Der Browser setzt es durch (nicht der Server – deshalb funktioniert curl), und der Server behebt es (nicht Ihr Frontend – deshalb hilft kein noch so gutes JavaScript). Alles andere sind Header.
Das Wichtigste in Kürze
| Frage | Antwort |
|---|---|
| Die Grundlage | Same-Origin-Policy: Skripte dürfen Antworten anderer Origins standardmäßig nicht lesen |
| Eine Origin | Schema + Host + Port – alle drei müssen übereinstimmen |
| CORS | Server-Header, die einzelne Origins zulassen; der Browser setzt durch |
| Preflight | OPTIONS als “darf ich?” vor nicht einfachen Anfragen |
| Die ewige Wahrheit | CORS-Fehler werden auf dem Server behoben, Punkt |
Das ganze Protokoll, auf der Leitung
# Preflight: Der Browser fragt vor einem PUT mit Auth-Header nach
OPTIONS /classes/Product HTTP/1.1
Origin: https://app.example.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: x-parse-session-token
# Der Erlaubnisschein des Servers
HTTP/1.1 204 No Content
Access-Control-Allow-Origin: https://app.example.com ← diese Origin darf lesen
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: x-parse-session-token
Access-Control-Max-Age: 7200 ← Antwort cachen; keine wiederholten Preflights
# Dann, und erst dann, geht die eigentliche Anfrage raus.
Wie das aus dem Anwendungscode aussieht – und die Plattform-Wahrheit, die die Tabs vermitteln: CORS ist eine Sache des Browsers, der native Apps nie begegnen:
// Browser JavaScript — Back4app JS SDK
// A cross-origin call that just works: the platform answers the
// preflight and sends the CORS headers, so the browser lets it through
Parse.initialize('APP_ID', 'JS_KEY');
Parse.serverURL = 'https://parseapi.back4app.com'; // different origin than your site
const products = await new Parse.Query('Product').find();
// No proxy hacks, no "disable CORS" — the server side is configured correctly. // Flutter / Dart — Back4app Flutter SDK
// Native apps have no same-origin policy — CORS is a browser concern.
// Flutter Web, however, DOES enforce it: same browser rules apply there.
final query = QueryBuilder<ParseObject>(ParseObject('Product'));
final response = await query.query();
// Works identically on mobile and web because the server sends CORS headers. // iOS / Swift — Back4app Swift SDK
// No browser, no same-origin policy: CORS never applies to native iOS.
// The same backend serves browsers (with CORS headers) and apps alike.
let query = Product.query()
query.find { result in
if case .success(let products) = result { render(products) }
} // Android / Kotlin — Back4app Android SDK
// No browser, no same-origin policy: CORS never applies to native Android.
// The same backend serves browsers (with CORS headers) and apps alike.
val query = ParseQuery.getQuery<ParseObject>("Product")
query.findInBackground { products, e ->
if (e == null) render(products)
} Der Ablauf, entschieden
Zwei Details tragen die meisten Debugging-Sitzungen: Eine einfache Anfrage (GET/HEAD/POST mit Headern von der Safelist und einfachen Content-Types) überspringt den Preflight – deshalb bringt ein hinzugefügter Authorization-Header plötzlich einen Endpoint zum Scheitern, der vorher funktionierte; und Anfragen mit Credentials ziehen alles enger – Cookies fließen nur mit Access-Control-Allow-Credentials: true plus einer exakten Origin, nie mit dem Wildcard, so die Spezifikation.
Häufige CORS-Fehler beheben (Fehler → Ursache → Lösung)
| Die Konsole sagt | Was tatsächlich passiert ist | Lösung (immer serverseitig) |
|---|---|---|
| No ‘Access-Control-Allow-Origin’ header | Der Server hat Ihre Origin nie zugelassen | Ihre Origin in die Allowlist aufnehmen |
| Origin not allowed by Access-Control-Allow-Origin | Die Allowlist existiert; Sie stehen nicht darauf | Exaktes Schema+Host+Port ergänzen |
| Response to preflight… doesn’t pass | OPTIONS unbehandelt oder Header unvollständig | OPTIONS mit Methoden/Headern beantworten |
| Wildcard ’*’ cannot be used with credentials | Cookies + * – verbotene Kombination | Origins explizit auflisten |
| Request header not allowed | Eigener Header fehlt in der Allowlist | Ihn zu Access-Control-Allow-Headers hinzufügen |
Und die Anti-Lösung, die einen Namen verdient: Browser-Flags zum Abschalten und großzügige Dev-Proxys machen den Fehler nur auf Ihrer Maschine unsichtbar – für die Benutzer bleibt das Deployment kaputt. Die echte Lösung ist eine Serverkonfiguration, gemessen in Minuten.
Typische Anwendungsfälle
- SPA und API auf verschiedenen Origins – app.example.com ruft api.example.com auf: der Alltagsfall, für den es CORS gibt.
- Lokale Entwicklung – localhost:3000 gegen ein echtes Backend; lassen Sie die Dev-Origin zu, statt den Schutz abzuschalten.
- Öffentliche APIs – Wildcard-Origin, keine Credentials: korrekt und sicher für wirklich öffentliche Daten.
- Plattformen mit mehreren Frontends – mehrere Apps, ein Backend, eine explizite Liste von Origins pro Umgebung.
- BaaS-Backends – die Plattform beantwortet Preflights und schickt die Header; Ihre Aufgabe schrumpft darauf, die erlaubten Origins zu deklarieren.
Wildcard vs. explizite Origins: Entscheidungsmatrix
| Konfiguration | Richtig, wenn … | Nie, wenn … |
|---|---|---|
Wildcard * | Öffentliche API ohne Credentials | Cookies oder Benutzer-Sessions im Spiel sind |
| Explizite Liste von Origins | Private APIs, Apps mit Credentials | – (das ist die Standardantwort) |
| Anfrage-Origins zurückspiegeln | Fast nie | Zusammen mit Credentials – das klassische Loch |
| Listen pro Umgebung | Hygiene für Dev, Staging und Prod | Prod die localhost-Einträge von Dev erbt |
Eine sicherheitsbezogene Umdeutung schließt die Matrix ab: CORS ist keine Zugriffskontrolle – native Apps und Server ignorieren es vollständig, es schützt also Browser-Benutzer vor bösartigen Websites, nicht Ihre API vor Aufrufern. Diese Aufgabe erledigen Authentifizierung und Berechtigungen auf der Datenschicht; CORS entscheidet nur, welche Skripte welcher Websites die Antworten lesen dürfen.
Grenzen und Trade-offs
- Es regelt nur Browser. Alles, was kein Browser ist, geht daran vorbei – halten Sie eine Liste von Origins nie für Autorisierung.
- Preflights kosten einen Roundtrip bei nicht einfachen Anfragen; das Caching über
Access-Control-Max-Ageist die billige, vergessene Lösung. - Fehlkonfiguration scheitert geschlossen und laut – gut für die Sicherheit, brutal für das Debuggen ohne die Tabelle Fehler → Lösung von oben.
- Listen von Origins sind Umgebungszustand. Staging-Origins sickern in Produktionskonfigurationen; auditieren Sie die Liste wie jedes andere Credential.
- CORS ≠ CSRF ≠ CSP. Benachbarte Abkürzungen, getrennte Abwehrmechanismen – Cookies brauchen weiterhin SameSite- oder Token-Schutz, Seiten weiterhin eine Content-Policy, während CORS allein den Lesezugriff über Origin-Grenzen hinweg regelt.
CORS mit Back4app
Back4app ist eine Open-Source-Plattform für Backend as a Service (BaaS), die eine verwaltete Datenbank, automatisch generierte REST- und GraphQL-APIs, Authentifizierung, Dateispeicher und Serverless-Funktionen mit Cloud Code kombiniert. Die Pflichtaufgabe CORS kommt erledigt mit: Die Plattform-APIs beantworten Preflights und schicken korrekte Header, sodass Browser-Apps das Backend von erlaubten Origins aus ohne Proxy-Tricks aufrufen – der JavaScript-Tab oben ist bereits die ganze Erfahrung –, während die Tabs für Flutter, Swift und Kotlin die stillere Wahrheit zeigen: Native Clients begegnen der Zeremonie überhaupt nie. Die echte Sicherheit bleibt, wo sie hingehört: Sessions, ACLs und Klassenberechtigungen, serverseitig bei jeder Anfrage durchgesetzt, von jeder Origin aus.
Häufige Fragen
Was ist CORS, einfach erklärt?
Das Berechtigungssystem des Browsers für API-Aufrufe über Site-Grenzen hinweg. Standardmäßig dürfen Skripte einer Origin keine Antworten einer anderen lesen – das ist die Same-Origin-Policy. CORS ist die Art, wie ein Server zustimmt: Antwort-Header, die erklären, welche Origins, Methoden und Header er akzeptiert. Der Browser setzt durch, der Server erklärt, Ihr Frontend-Code ist nur der Bote.
Was genau ist eine Origin?
Das Tripel aus Schema, Host und Port – die Origin (der Ursprung), aus der eine Seite stammt. https://app.example.com und https://api.example.com sind verschiedene Origins (der Host unterscheidet sich); ebenso die http- und die https-Variante derselben Site (das Schema unterscheidet sich) und :3000 gegenüber :8080 in der Entwicklung (der Port unterscheidet sich). Jede CORS-Entscheidung vergleicht diese drei Teile – nichts anderes an der URL zählt.
Was verursacht den klassischen CORS-Fehler?
Der Browser hat eine andere Origin aufgerufen, und in der Antwort fehlte ein Access-Control-Allow-Origin-Header, der zu Ihrer passt – also hat der Browser Ihr Skript am Lesen gehindert. Die Anfrage hat den Server oft problemlos erreicht; die Blockade findet clientseitig statt, beim Lesen. Deshalb ist die Lösung immer Serverkonfiguration und nie Frontend-Code.
Was ist eine Preflight-Anfrage?
Die vorgezogene Erlaubnisabfrage des Browsers für nicht einfache Anfragen: Bevor er ein PUT, ein DELETE oder irgendetwas mit eigenen Headern wie einem Autorisierungs-Token schickt, sendet er eine OPTIONS-Anfrage mit der Frage "darf ich?". Die Header des Servers beantworten, welche Methoden, Header und Origins erlaubt sind; erst danach geht die eigentliche Anfrage raus. Preflights lassen sich über Access-Control-Max-Age cachen.
Warum funktioniert meine Anfrage in curl, aber nicht im Browser?
Weil CORS eine Durchsetzung im Browser ist und keine Ablehnung durch den Server. Werkzeuge wie curl und native Mobile-Apps kennen keine Same-Origin-Policy, sie lesen die Antwort also bereitwillig. Der Browser wendet die Policy im Namen seines Benutzers an – der Unterschied, den Sie sehen, ist der Ort der Durchsetzung, und genau das beweist, dass CORS keine Zugriffskontrolle ist.
Ist Access-Control-Allow-Origin: * sicher?
Für wirklich öffentliche APIs ohne Credentials: ja. Das Wildcard ist im Credential-Modus verboten – Browser verweigern Cookies dagegen grundsätzlich –, und beliebige Origins zurückzuspiegeln und dabei Credentials zuzulassen ist die klassische Fehlkonfiguration, die CORS vom Schutzschild zum Loch macht. Private APIs listen ihre Origins explizit auf.
Kann ich CORS nicht einfach abschalten, um den Fehler loszuwerden?
Nur in dem Sinne, in dem das Abnehmen eines Rauchmelders ein Feuer löscht. Browser-Flags und großzügige Proxys verdecken das Symptom auf Ihrer Maschine, während der Defekt bei jedem Benutzer ankommt. Die richtige Lösung dauert Minuten: Konfigurieren Sie den Server (oder das Dashboard der Plattform) so, dass er die Origins zulässt, die ihn aufrufen sollen.
Was ist der Unterschied zwischen CORS, CSRF und CSP?
Drei verschiedene Aufgaben. CORS regelt, welche Origins Antworten eines Servers lesen dürfen. CSRF ist ein Angriff – das Mitreiten auf den Cookies eines Benutzers, um Anfragen zu fälschen –, dem man mit Tokens und SameSite-Cookies begegnet, nicht mit CORS. CSP ist die eigene Policy einer Seite, die einschränkt, was sie laden und ausführen darf, das Werkzeug gegen XSS. Benachbarte Abkürzungen, orthogonale Mechanismen.