CORS und zulässige Ursprünge
Ein veröffentlichbarer Schlüssel kann eine Liste zulässiger Ursprünge enthalten: die Websites, die ihn verwenden dürfen. Diese Seite erklärt, wo diese Liste geprüft wird, was der Browser bei einer abgelehnten Herkunft anzeigt und wovor die Liste nicht schützt.
Ein Ursprung besteht aus Schema, Host und Port einer Seite, beispielsweise https://www.example.com oder http://localhost:3000. Er enthält keinen Pfad.
Die Liste ist optional
Ein veröffentlichbarer Schlüssel funktioniert auch mit einer leeren Liste. Eine leere Liste bedeutet, dass jeder Ursprung den Schlüssel verwenden darf. So ist ein Schlüssel ohne konfigurierte Ursprünge eingerichtet; Sie können die Liste auch später leeren.
Fügen Sie Ursprünge hinzu, bevor Sie einen Schlüssel auf einer produktiven Website einsetzen. Ist eine Liste eingerichtet, funktioniert eine Kopie Ihres Schlüssels nicht mehr, wenn sie in die Website eines anderen eingefügt wird. Was dadurch geschützt wird und was nicht, erfahren Sie unten.
Serverschlüssel ignorieren diese Liste. Ein Serverschlüssel kann unabhängig von den Einträgen der Liste niemals in einem Browser verwendet werden.
Einen Eintrag angeben
| Regel | Beispiel |
|---|---|
| Nur Schema, Host und optionaler Port. Kein Pfad, keine Abfrageparameter und kein abschließender Schrägstrich. | https://www.example.com, nicht https://www.example.com/ |
https ist erforderlich. http wird nur für localhost, 127.0.0.1 und [::1] akzeptiert. Auf der Seite „API-Schlüssel“ wird [::1] nicht akzeptiert; legen Sie den Eintrag über die Schlüsselverwaltungs-API an. | http://localhost:3000 |
Die Übereinstimmung muss exakt sein. Platzhalter werden nicht unterstützt; eine Subdomain ist ein anderer Ursprung. Ein Eintrag mit * wird unverändert gespeichert, stimmt aber mit keiner Website überein. | https://example.com und https://www.example.com sind zwei Einträge |
Der Port gehört zum Ursprung. Lassen Sie Standardports weg (443 für https, 80 für http). | https://example.com, nicht https://example.com:443 |
| Höchstens 100 Einträge je Schlüssel. Doppelte Einträge werden abgelehnt. |
Einträge werden in Kleinbuchstaben und ohne Standardports gespeichert, damit sie mit den Angaben des Browsers übereinstimmen.
Eine direkt vom Datenträger geöffnete Seite (file://) hat keinen Ursprung, den Sie hinzufügen könnten. Stellen Sie die Seite während der Entwicklung über http://localhost bereit.
Legen Sie die Liste auf der Seite „API-Schlüssel“ unter kaleidr.com/api-keys oder über allowed_origins in der Schlüsselverwaltungs-API fest.
Wo die Liste geprüft wird
| Schritt | Prüfung | Bei einem Fehler |
|---|---|---|
| 1. Sitzungsaustausch | Der Header Origin der Anfrage muss in der Liste des Schlüssels stehen, sofern eine solche Liste vorhanden ist. | 403 origin_not_allowed. Es wird keine Sitzung ausgestellt. Fehlt der Header Origin vollständig, lautet die Antwort 403 origin_required. |
| 2. Jeder Laufzeitaufruf | Ein Sitzungstoken funktioniert nur mit dem Ursprung, für den es ausgestellt wurde. | 403 session_origin_mismatch. |
| 3. Jeder Laufzeitaufruf | Der Ursprung der Sitzung muss weiterhin in der Schlüsselliste stehen. | 401. Durch das Entfernen eines Ursprungs werden bereits für ihn ausgestellte Sitzungen beendet. |
| 4. Basiskartenanfragen mit Schlüssel | Der eingebettete Editor sendet Ihren veröffentlichbaren Schlüssel bei Anfragen für Stil, Sprites und Schriftarten an https://tile.kaleidr.com. Damit der Schlüssel erkannt wird, muss die Website in der Schlüsselliste stehen. | Die Anfrage wird so behandelt, als enthalte sie keinen Schlüssel, und kann mit 429 tile_access_restricted abgelehnt werden. |
| 5. Die Antwort | Die API fügt Access-Control-Allow-Origin nur hinzu, wenn die Anmeldedaten gültig und der Ursprung zugelassen sind. | Der Browser verhindert, dass die Seite die Antwort liest. |
Schritt 5 ist das normale CORS-Verhalten und erklärt, warum Fehler im Browser auf diese Weise erscheinen.
Preflight-Anfrage
Vor einer domainübergreifenden POST-Anfrage mit JSON-Body sendet der Browser eine OPTIONS-Preflight-Anfrage. Kaleidr beantwortet jede solche Anfrage mit 204 und übernimmt den anfragenden Ursprung, da die Preflight-Anfrage keine Anmeldedaten enthält und nicht gegen einen Schlüssel geprüft werden kann. Die Liste wird erst bei der eigentlichen Anfrage angewendet.
| Antwortheader der Preflight-Anfrage | Wert |
|---|---|
Access-Control-Allow-Methods | GET, POST, OPTIONS |
Access-Control-Allow-Headers | Authorization, Content-Type, Accept, X-Api-Key, X-Request-Id |
Access-Control-Max-Age | 600 |
Eine Anfrage, die weitere Header sendet, scheitert bereits bei der Preflight-Prüfung im Browser. Fügen Sie Aufrufen aus einer Webseite keine benutzerdefinierten Header hinzu.
Bei einer zugelassenen Antwort sendet die API außerdem Access-Control-Expose-Headers: Retry-After, X-Request-Id, sodass der Seitencode diese beiden Header auslesen kann. Sie sendet niemals Access-Control-Allow-Credentials, da die API keine Cookies verwendet.
Was bei einem abgelehnten Ursprung angezeigt wird
Wenn der Ursprung oder die Anmeldedaten abgelehnt werden, enthält die Antwort keinen Header Access-Control-Allow-Origin. Der Browser verbirgt die Antwort daher vor Ihrem Code. Die Seite sieht den Inhalt der 401- oder 403-Antwort nicht, sondern einen Netzwerkfehler.
In der Konsole:
Access to fetch at 'https://api.kaleidr.com/inference-api/b2b/v1/sdk/sessions' from origin
'https://www.example.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present
on the requested resource.
gefolgt von einem SDK-Fehler, der [kaleidr:chat] (oder das von Ihnen eingebundene Produkt) enthält. Es wird nichts dargestellt.
Um die tatsächliche Ursache zu finden, öffnen Sie im Browser die Registerkarte Network (Netzwerk), wählen die Anfrage sessions aus und prüfen deren Status und Antwort:
| Status und Code auf der Registerkarte „Network“ | Ursache | Abhilfe |
|---|---|---|
403 origin_not_allowed | Der Ursprung dieser Seite steht nicht in der Schlüsselliste. | Fügen Sie genau den Ursprung hinzu, der im Header Origin der Anfrage angegeben ist. |
401 Invalid or missing API key | Der Schlüssel wurde falsch eingegeben, widerrufen oder ist abgelaufen. | Prüfen Sie den Schlüssel auf der Seite „API-Schlüssel“. |
403 server_key_in_browser | Ein Serverschlüssel wurde von einer Webseite gesendet. | Verwenden Sie auf der Seite einen veröffentlichbaren Schlüssel. Rotieren Sie den Serverschlüssel. |
403 session_origin_mismatch | Ein Sitzungstoken wurde von einem anderen Ursprung als dem ausstellenden verwendet. | Tauschen Sie die Sitzung auf der Seite aus, die sie verwendet. |
Die Preflight-Prüfung scheitert; kein POST erscheint | Die Anfrage enthielt einen Header außerhalb der zulässigen Liste. | Entfernen Sie den benutzerdefinierten Header. |
Sobald Anmeldedaten und Ursprung akzeptiert wurden, sind spätere Fehler für die Seite lesbar und lösen keinen CORS-Fehler aus. Ist ein Schlüssel für diesen Ursprung gültig, aber nicht für das Produkt zugelassen, schlägt der Sitzungsaustausch mit einem lesbaren 403 (product_not_allowed, insufficient_scope oder tier_capability_not_allowed) fehl; das SDK protokolliert kaleidr session exchange failed (403). Eine 429-Antwort für eine gültige Sitzung enthält ihren Antwortinhalt und den Header Retry-After. Die Codes werden unter Authentifizierung und Berechtigungsbereiche erläutert.
Dieselbe Anfrage erzeugt im Terminal niemals einen CORS-Fehler, da CORS eine Browserregel ist. Deshalb können Sie mit curl ein Schlüsselpaar aus Schlüssel und Ursprung schnell überprüfen:
curl -i https://api.kaleidr.com/inference-api/b2b/v1/sdk/sessions \
-H "X-Api-Key: kld_pk_live_…" \
-H "Origin: https://www.example.com" \
-H "Content-Type: application/json" \
-d '{"product":"chat"}'
Ein zugelassener Ursprung liefert 200 mit access-control-allow-origin: https://www.example.com. Ein abgelehnter Ursprung liefert 403 {"detail":"origin_not_allowed"} ohne diesen Header.
Warum ein Serverschlüssel im Browser abgelehnt wird
Ein Serverschlüssel ist ein dauerhaftes Geheimnis. Wer ihn besitzt, kann bis zu seinem Widerruf im Namen Ihrer Organisation die API aufrufen. Da der Quellcode einer Webseite öffentlich ist, gilt ein dort hinterlegter Serverschlüssel als offengelegt.
Kaleidr lehnt ihn an drei Stellen ab:
- Das SDK lehnt beim Einbinden einen Schlüssel mit dem Präfix
kld_sk_…ab, meldet einen Konsolenfehler und sendet keine Netzwerkanfrage. - Die API beantwortet jede Anfrage mit Serverschlüssel und Header
Originmit 403server_key_in_browser. - Die Antwort enthält keinen CORS-Header, sodass der Seitencode die Antwort ohnehin nicht lesen könnte.
Keine dieser Maßnahmen macht die Offenlegung rückgängig. CORS blockiert die Antwort, nicht die Anfrage: Wenn die API die Anfrage ablehnt, wurde der Schlüssel bereits gesendet und ist für jeden Besucher der Seite sichtbar. Wurde ein Serverschlüssel in einer Webseite eingebunden, rotieren Sie ihn.
Die Liste schützt keine Geheimnisse
Nur Browser setzen den Header Origin verlässlich auf den tatsächlichen Ursprung. Ein Skript, ein Kommandozeilenprogramm oder ein Server kann hingegen einen beliebigen Header Origin senden, wie das obige Beispiel mit curl zeigt. Deshalb gilt:
- Die Liste hindert andere Websites daran, Ihren Schlüssel in den Browsern ihrer Besucher zu verwenden. Genau dafür ist sie gedacht, und das funktioniert zuverlässig.
- Die Liste hält entschlossene Angreifer nicht auf, die Ihren veröffentlichbaren Schlüssel kopieren und außerhalb eines Browsers Anfragen mit Ihrem Ursprung senden.
Planen Sie entsprechend. Behandeln Sie alles, worauf ein veröffentlichbarer Schlüssel zugreifen kann, als für jede Person zugänglich, die Ihre Seite lesen kann:
- Begrenzen Sie das Quotenrisiko mit einem monatlichen Limit je Schlüssel und dessen Ratenbegrenzung. Siehe Quoten und Ratenlimits.
- Geben Sie einem veröffentlichbaren Schlüssel den Berechtigungsbereich
vendornur, wenn Sie die dadurch lesbaren Daten auch auf dieser Seite veröffentlichen würden. Siehe Authentifizierung und Berechtigungsbereiche. - Verwenden Sie einen eigenen Schlüssel pro Website, damit Sie einen widerrufen können, ohne die anderen zu beeinträchtigen.
Ein umfassenderes Bild vermittelt das Sicherheitsmodell.
Anmeldedaten in URLs
Aufrufe der Plattform-API übertragen Anmeldedaten in einem Header, niemals in einer URL. Eine Ausnahme bilden Basiskartenanfragen über Kaleidr-Einbettungen: Sie übertragen Browser-Anmeldedaten in der Anfrage-URL, wo sie im Browserverlauf und in Netzwerkprotokollen erscheinen können. Bei veröffentlichbaren Anmeldedaten, die ohnehin öffentlich sind, ist das zulässig. Für Serverschlüssel ist das niemals akzeptabel. Verwenden Sie kld_sk_… in keiner URL.
Die Liste ändern
- Einen Ursprung hinzufügen: Die Änderung gilt ab dem nächsten Sitzungsaustausch von diesem Ursprung. Bei Basiskartenanfragen kann es einige Minuten dauern, bis die Änderung übernommen wird.
- Einen Ursprung entfernen: Neue Sitzungsaustausche von dort werden abgelehnt; bestehende Sitzungen werden bei ihrer nächsten Anfrage beendet.
- Die Liste leeren: Der Schlüssel ist wieder für „jeden Ursprung“ gültig.
Verwandte Themen
- Authentifizierung und Berechtigungsbereiche: Sitzungsaustausch und alle 401- und 403-Fehler.
- Sicherheitsmodell: was ein offengelegter Schlüssel ermöglicht.
- Content Security Policy: welche Hosts Ihre Seite zulassen muss.
- Fehlerbehebung: Probleme nach Symptomen.