Cookies sind in JavaScript (und den Entwicklungstools) nicht verfügbar, werden aber zusammen mit der XHR-Anfrage gesendet (kein httponly verwendet)

8

Ich verwende sowohl eine Front-End- als auch eine Back-End-Anwendung in einer anderen Domäne mit einer sitzungsbasierten Berechtigung. Ich habe eine funktionierende CORS-Konfiguration eingerichtet, die wie erwartet in localhost funktioniert (z. B. von Port :9000 nach Port :8080 ). Sobald ich die Anwendungen auf sicheren Domains veröffentliche (beide Domains erlauben nur HTTPS), ist der CSRF-Cookie innerhalb von JavaScript nicht mehr zugänglich, was zu einer inkorrekten Folgeanfrage des Frontends führt (fehlende CSRF-Header).

Der Cookie wird vom Backend im Header Set-Cookie ohne mit dem Flag HttpOnly gesetzt. Es ist tatsächlich irgendwo im Browser eingestellt, weil die Folgeanfrage sowohl den Session-Cookie als auch den CSRF-Cookie enthält. Wenn Sie versuchen, mit JavaScript darauf zuzugreifen (z. B. document.cookie in der Konsole), wird eine leere Zeichenfolge zurückgegeben. Die DevTools von Chrome zeigen keine any Cookies in der Frontend-Domain an (die Backend-Domain ist nicht einmal aufgeführt).

Ich erwarte, dass der Cookie gesetzt und in der aktuellen Domain (Front-End-Domain) sichtbar ist. Ich verwende das withCredentials -Flag der Axios -Bibliothek.

Haben Sie eine Idee, warum auf den Cookie nicht über JavaScript oder die DevTools in Chrome zugegriffen werden kann? Hat das etwas mit dem Header Strict-Transport-Security zu tun?

Kopfzeilen

1. Anfangs-GET-Antwortheader

%Vor%

2. Follow-up-POST-Anfragekopf

%Vor%
  

Diese Anfrage sollte einen CSRF-Header enthalten, der automatisch hinzugefügt würde, wenn der Cookie mit JavaScript zugänglich wäre.

    
ssc-hrep3 20.09.2017, 12:38
quelle

4 Antworten

1

Kurz gesagt, es ist nicht möglich, auf stammzellenübergreifende Cookies zuzugreifen, document.cookie kann nur auf den aktuellen ( oder übergeordneten ) zugreifen ) Domain-Cookies.

Der Hinweis darauf, dass dies die Hauptursache ist, war, dass ssc-hrep3 "beide Domains" in seiner Frage erwähnt.

Es ist sehr einfach, diesen Fehler zu machen, wenn Sie von einer Localhost-Bereitstellung mit nur unterschiedlichen Ports für Back-End- und Front-End-Server auf eine mit zwei verschiedenen Hosts wechseln. Dies funktioniert lokal, da Cookies über mehrere Ports verteilt werden und bei Verwendung von zwei verschiedenen Hosts fehlschlagen. (Im Gegensatz zu einigen anderen CORS-Problemen, die auch lokal verfügbar gemacht werden)

Siehe die Antwort von ssc-hrep3 für weitere Informationen und eine Problemumgehung.

    
Ido.Co 30.09.2017, 04:02
quelle
4

1

Sie müssen möglicherweise Access-Control-Allow- Kopfzeilen Header, um die Weitergabe bestimmter Header zu ermöglichen.

Bitte versuchen Sie, zu Testzwecken die folgenden Serverantwort-Header (OPTIONS-Methode) hinzuzufügen:

%Vor%

In der Produktion empfehle ich Header wie folgt zu begrenzen (aber ich bin nicht 100% sicher in der richtigen Header-Liste, muss hier experimentieren, wenn es funktioniert)

%Vor%

Siehe dies für die Referenz Ссылка

2

Ein weiteres Problem, das Sie möglicherweise erleben, ist, dass Sie Cookies in der Domäne festlegen, in der sich Ihr Back-End-Dienst befindet (nicht in der Domäne, von der Sie abfragen)

Bitte überprüfen Sie dies auch

3

Als eine Option des letzten Problems - der Browser kann das Setzen des Cookies für die Domäne b.xxx.com von der Anfrage verbieten, die von a.xxx.com

kommt

In diesem Fall können Sie versuchen, Cookie für die übergeordnete Domain xxx.com zu setzen, damit sie für Ihre Client-Seite verfügbar ist

    
Andrey Muzalevsky 27.09.2017 13:03
quelle
2

TL; DR : Lesezugriff auf domainübergreifende Cookies ist nicht möglich. Das Hinzufügen des CSRF-Tokens zum Antwortheader wäre eine Lösung. Eine weitere Lösung, um CORS & amp; Übergreifende Anfragen würden einen Reverse-Proxy verwenden.

Problem

Wie in meiner Frage oben erwähnt, versucht der JavaScript-Teil meines Frontends (zB https://example1.com versucht auf einen nicht HttpOnly -Cookie von meinem Backend auf zB https://example2.com zuzugreifen. Um darauf zugreifen zu können eine entfernte API mit JavaScript, ich benutze CORS, damit die Anfragen durchlaufen werden können.Ich verwende withCredentials: true auf der Front-End-Seite und Access-Control-Allow-Credentials: true auf der Backend-Seite.Der Set-Cookie -Header dann setzt den Cookie auf den Backend-Ursprung und nicht auf den Front-End-Ursprung, daher ist der Cookie weder in den DevTools noch im document.cookie -Befehl in JavaScript sichtbar.

Cookies, die auf den Backend-Ursprung gesetzt werden, sind immer Teil einer Anfrage an das Backend über CORS. Ich würde jedoch auf den Inhalt des CSRF-Cookies zugreifen müssen, um das Token in den Anfrage-Header einzufügen (um CSRF-Angriffe zu verhindern). Wie ich herausgefunden habe, gibt es keine Möglichkeit, Cookies von einer anderen Domain mit JavaScript zu lesen (oder zu schreiben) - egal, welche CORS-Einstellung verwendet wird (siehe diese StackOverflow-Antworten: [1] , [2] ). Der Browser beschränkt den Zugriff auf den Inhalt eines Cookies auf den Ursprung derselben Domain.

Lösungen

Dies führt zu der Schlussfolgerung, dass es keine Möglichkeit gibt, auf den Inhalt eines nicht HttpOnly -Cookies einer anderen Domain zuzugreifen. Eine Problemumgehung für dieses Problem wäre, das CSRF-Token in einen zusätzlichen, benutzerdefinierten Antwortheader zu setzen. Auf diese Header kann normalerweise auch nicht von einer anderen Domain zugegriffen werden. Sie können jedoch durch die CORS-Einstellung Access-Control-Expose-Headers des Backends angezeigt werden. Dies ist sicher, solange man einen streng begrenzten Access-Control-Allow-Origin Header verwendet.

Eine andere Problemumgehung wäre die Verwendung eines Reverse-Proxy, der die Probleme mit CORS und domänenübergreifenden Anfragen überhaupt umgeht. Die Verwendung eines solchen Reverse-Proxy stellt einen speziellen Pfad auf dem Front-End bereit, der zu dem Back-End (serverseitig) umgeleitet wird. Beispielsweise werden Aufrufe von https://front-end/api an https://back-end/api weitergeleitet. Da alle Anforderungen vom Front-End an den Front-End-Proxy für die gleiche Domäne gesendet werden, behandelt der Browser jeden Anruf als Anforderung der gleichen Domäne, und Cookies werden direkt am Front-End-Ursprung festgelegt. Nachteile dieser Lösung sind potenzielle Leistungsprobleme, da ein anderer Server dazwischen liegt (Verzögerungen) und die Cookies auf zwei Ursprünge gesetzt werden müssen (zweimaliges Anmelden, wenn direkt auf das Backend zugegriffen wird). Das Einrichten eines Reverse-Proxy kann mit Nginx, Apache oder auch sehr einfach mit http-proxy-middleware in Node.js:

erfolgen

%Vor%
    
ssc-hrep3 28.09.2017 08:35
quelle
1

Wie Sie hier lesen können, erlaubt die XHR-Spezifikation das Lesen ausdrücklich nicht Set-Cookie. Der beste Weg dazu wäre, Informationen in einem Header anstelle eines Cookies zu übergeben.

    
Jean Robert 26.09.2017 02:23
quelle