wake-up-neo.net

Laravel 5.6 - Passport JWT httponly Cookie-SPA-Authentifizierung für selbstverbrauchende API?

ANMERKUNG: Ich hatte 4 Kopfgelder für diese Frage, aber keine der oben angegebenen Antworten ist die Antwort, die für diese Frage benötigt wird. Alles, was benötigt wird, befindet sich in Update 3 unten und sucht nach Laravel Code, der implementiert werden soll.


UPDATE 3: Dieses Flussdiagramm ist genau der Fluss, den ich zu erreichen versuche, alles unten ist die ursprüngliche Frage mit einigen älteren Updates. Dieses Flussdiagramm fasst alles zusammen, was benötigt wird.

Die grünen Teile im Flussdiagramm unten sind die Teile, die ich zu tun weiß. Die roten Teile zusammen mit ihren Randnotizen sind das, wonach ich suche, um Hilfe bei der Verwendung von Laravel - Code zu erhalten.

enter image description here


Ich habe viel recherchiert, aber die Informationen sind immer kurz und unvollständig, wenn es darum geht, Laravel mit einem JWT-httponly-Cookie für eine selbstverbrauchende API zu verwenden (die meisten Online-Tutorials zeigen nur, dass JWT im lokalen Speicher gespeichert ist, der ist nicht sehr sicher). Es sieht so aus, als sollte nur ein http-Cookie verwendet werden, das eine JWT von Passport enthält, um den Benutzer auf der Javascript-Seite zu identifizieren, wenn er bei jeder Anfrage an den Server überprüft, ob der Benutzer der ist, für den er sich ausgibt.

Es gibt auch einige zusätzliche Dinge, die erforderlich sind, um ein vollständiges Bild davon zu erhalten, wie dieses Setup funktioniert. Diese sind mir in einem einzigen Tutorial noch nicht begegnet:

  1. Laravel Passport (nicht tymon auth), um verschlüsselte JWT zu generieren und diese als httponly-Cookie als Antwort nach dem Login von JS-Seite zu senden. Welche Middleware soll verwendet werden? Wenn Aktualisierungstoken mehr Sicherheit bieten, wie implementieren?
  2. JavaScript (Axios zum Beispiel) API-Pseudocode, der den Aufruf des Auth-Endpunkts vornimmt, wie httponly-Cookies an das Backend übergeben werden und wie das Token zur Überprüfung des Backends gültig ist.
  3. Wenn ein einzelnes Konto von mehreren Geräten aus angemeldet ist, wird ein Gerät gestohlen. Wie kann der Zugriff aller authentifizierten Benutzergeräte widerrufen werden (vorausgesetzt, der Benutzer ändert das Kennwort von einem angemeldeten Gerät aus, über das er die Kontrolle hat)?
  4. Wie würden sich die Controller-Methoden Anmelden/Registrieren, Abmelden, Passwort ändern und Passwort vergessen normalerweise für das Erstellen/Validieren/Widerrufen von Tokens verhalten?
  5. CSRF-Token-Integration.

Ich hoffe, dass eine Antwort auf diese Frage ein leicht zu befolgender Leitfaden für zukünftige Leser und diejenigen ist, die im Moment Schwierigkeiten haben, eine Antwort zu finden, die die oben genannten Punkte einer selbstverbrauchenden API abdeckt.

UPDATE 1:

  1. Bitte beachten Sie, dass ich das CreateFreshApiToken schon einmal ausprobiert habe, aber dies funktionierte nicht, wenn es darum ging, Token des Benutzers zu entziehen (für die obigen Punkte 3 und 4). Dies basiert auf diesem Kommentar eines Kernentwicklers laravel, wenn es um die Middleware CreateFreshApiToken geht:

JWT-Token, die mit dieser Middleware erstellt wurden, werden nirgendwo gespeichert. Sie können nicht widerrufen werden oder "nicht existieren". Sie bieten einfach eine Möglichkeit, Ihre API-Aufrufe über das Cookie laravel_token zu authentifizieren. Es hat nichts mit Zugriffstoken zu tun. Außerdem würden Sie normalerweise keine Token verwenden, die von Kunden in derselben App ausgegeben wurden, die sie ausstellt. Sie würden sie in einer Erst- oder Drittanbieter-App verwenden. Verwenden Sie entweder die Middleware oder die vom Client ausgegebenen Token, jedoch nicht beide gleichzeitig.

Es scheint also möglich zu sein, Punkte 3 und 4 zu erfüllen, um Token zu entziehen. Dies ist jedoch nicht möglich, wenn die Middleware CreateFreshApiToken verwendet wird.

  1. Auf der Clientseite scheint Authorization: Bearer <token> Nicht der richtige Weg zu sein, um mit dem sicheren httpOnly-Cookie umzugehen. Ich denke, dass die Anfrage/Antwort das sichere httpOnly-Cookie als Anfrage/Antwort-Header enthalten soll, wie folgt basierend auf den laravel -Dokumenten:

Bei Verwendung dieser Authentifizierungsmethode weist das Standard-JavaScript-Gerüst Laravel Axios an, immer die Header X-CSRF-TOKEN und X-Requested-With zu senden.

headerswindow.axios.defaults.headers.common = {
    'X-Requested-With': 'XMLHttpRequest',
    'X-CSRF-TOKEN': (csrf_token goes here)
};

Aus diesem Grund suche ich auch nach einer Lösung, die alle oben genannten Punkte abdeckt. Entschuldigung, ich verwende Laravel 5.6 nicht 5.5.

UPDATE 2:

Anscheinend ist die Kombination Kennwort-Erteilung/Token-Erneuerung der richtige Weg. Suchen Sie nach einer einfach zu befolgenden Implementierungsanleitung mit der Kombination Kennwort-Erteilung/Erneuerungstoken-Erteilung .

Passwortgewährung: Diese Gewährung eignet sich für den Umgang mit Kunden, denen wir vertrauen, wie eine mobile App für unsere eigene Website. In diesem Fall sendet der Client die Anmeldeinformationen des Benutzers an den Autorisierungsserver, und der Server stellt das Zugriffstoken direkt aus.

Refresh Token Grant: Wenn der Server ein Zugriffstoken ausgibt, wird auch ein Ablaufdatum für das Zugriffstoken festgelegt. Die Berechtigung zum Aktualisieren von Token wird verwendet, wenn das Zugriffstoken nach Ablauf aktualisiert werden soll. In diesem Fall sendet der Autorisierungsserver beim Ausstellen des Zugriffstokens ein Aktualisierungstoken, mit dem ein neues Zugriffstoken angefordert werden kann.

Ich bin auf der Suche nach einer einfach zu implementierenden, direkten und ganzheitlichen Antwort mit der Kombination aus Passwort-Erteilung/Erneuerungstoken-Erteilung , die alle Teile des obigen Originals abdeckt 5 Punkte mit httpOnly Secure Cookie, Erstellen/Widerrufen/Aktualisieren von Token, Erstellen von Anmeldecookies, Widerrufen von Abmeldecookies, Controllermethoden, CSRF usw.

49
Wonka

Laravel Passport JWT

  1. Um diese Funktion nutzen zu können, müssen Sie die Cookie-Serialisierung deaktivieren. Laravel 5.5 hat ein Problem mit der Serialisierung/Unserialisierung von Cookie-Werten. Weitere Informationen hierzu finden Sie hier ( https://laravel.com/docs/5.5/upgrade )

  2. Stelle sicher das

    • sie haben <meta name="csrf-token" content="{{ csrf_token() }}"> in Ihrem Klingenschablonenkopf

    • axios ist so eingestellt, dass csrf_token für jede Anforderung verwendet wird.

Sie sollten so etwas in resources/assets/js/bootstrap.js Haben

window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
let token = document.head.querySelector('meta[name="csrf-token"]');

if (token) {
  window.axios.defaults.headers.common['X-CSRF-TOKEN'] = token.content;
} else {
  console.error('CSRF token not found: https://laravel.com/docs/csrf#csrf-x-csrf-token');
}
  1. Richten Sie hier erläuterte Authentifizierungsrouten ein ( https://laravel.com/docs/5.5/authentication )
  2. Hier wird das Einrichten des Passes erklärt ( https://laravel.com/docs/5.5/passport ).

Wichtige Teile sind:

  • fügen Sie das Merkmal Laravel\Passport\HasApiTokens zu Ihrem User Modell hinzu
  • setzen Sie die Option driver des Authentifizierungsschutzes api in Ihrem config/auth.php auf passport.
  • fügen Sie die Middleware \Laravel\Passport\Http\Middleware\CreateFreshApiToken::class, zu Ihrer Middleware-Gruppe web in app/Http/Kernel.php hinzu.

Beachten Sie, dass Sie wahrscheinlich Migrationen überspringen und Clients erstellen können.

  1. Stellen Sie eine POST Anfrage, um /login Ihre Anmeldeinformationen zu übergeben. Sie können eine AJAX Anfrage oder ein normales Formular senden.

Wenn die Anmeldeanforderung AJAX (unter Verwendung von Axios)) lautet, sind die Antwortdaten das HTML, aber was Sie interessiert, ist der Statuscode.

axios.get(
  '/login, 
  {
    email: '[email protected]',
    password: 'secret',
  },
  {
    headers: {
      'Accept': 'application/json', // set this header to get json validation errors.
    },
  },
).then(response => {
  if (response.status === 200) {
      // the cookie was set in browser
      // the response.data will be HTML string but I don't think you are interested in that
    }
    // do something in this case
}).catch(error => {
  if (error.response.status === 422) {
    // error.response.data is an object containing validation errors
  }
  // do something in this case
});

Bei der Anmeldung findet der Server den Benutzer anhand der angegebenen Anmeldeinformationen, generiert ein Token basierend auf Benutzerinformationen (ID, E-Mail ...) (dieses Token wird nirgendwo gespeichert) und gibt dann eine Antwort mit einem verschlüsselten Cookie zurück, das das generierte Token enthält .

  1. Führen Sie einen API-Aufruf an eine geschützte Route durch.

Angenommen, Sie haben eine geschützte Route

Route::get('protected', '[email protected]')->middleware('auth:api');

Sie können einen Ajax-Anruf mit Axios wie gewohnt tätigen. Die Cookies werden automatisch gesetzt.

axios.get('/api/protected')
  .then(response => {
    // do something with the response
  }).catch(error => {
    // do something with this case of error
  });

Wenn der Server den Anruf erhält, entschlüsselt er die Anforderung laravel_cookie Und erhält Benutzerinformationen (z. B. ID, E-Mail ...). Mit diesen Benutzerinformationen wird dann eine Datenbanksuche durchgeführt, um zu überprüfen, ob der Benutzer vorhanden ist. Wenn der Benutzer gefunden wird, ist der Benutzer berechtigt, auf die angeforderte Ressource zuzugreifen. Anderenfalls wird ein 401 zurückgegeben.

JWT-Token wird ungültig gemacht. Wie Sie den Kommentar erwähnen, besteht kein Grund zur Sorge, da dieses Token nirgendwo auf dem Server gespeichert wird.

Aktualisieren

Zu Punkt 3 Laravel 5.6 Auth hat eine neue Methode logoutOtherDevices. Weitere Informationen finden Sie hier ( https://laracasts.com/series/whats-new -in-laravel-5-6/episodes/7 ) da die dokumentation sehr leicht ist.

Wenn Sie Ihre Laravel Version nicht aktualisieren können, können Sie überprüfen, wie es in 5.6 gemacht wird, und eine eigene Implementierung für 5.5 erstellen

Punkt 4 aus Ihrer Frage. Schauen Sie sich die Controller in app/Http/Controllers/Auth An.

In Bezug auf access_tokens und refresh_tokens ist dies ein völlig anderer und komplexerer Ansatz. Sie können viele Tutorials online finden, die erklären, wie es geht.

Ich hoffe, es hilft.

PS. Frohes Neues!! :)

10
Mirceac21

Ich habe auch den Laravel Pass in mein Projekt implementiert und ich denke, ich habe die meisten Punkte abgedeckt, die Sie in Ihrer Frage erwähnt haben.

  1. Ich habe die Kennwortgewährung zum Generieren eines Zugriffstokens und eines Aktualisierungstokens verwendet. Sie können diese Schritte ausführen, um den Pass einzurichten und die Passgewährung zu implementieren. Bei Ihrer Anmeldemethode müssen Sie die Benutzeranmeldeinformationen validieren und die Token generieren und den Cookie ( Cookie an die Antwort anhängen ) an die Antwort anhängen. Wenn Sie brauchen, kann ich Ihnen einige Beispiele geben.
  2. Ich habe zwei Middleware für CORS hinzugefügt (Behandlung der Header eingehender Anforderungen) und um zu überprüfen, ob das eingehende Zugriffstoken gültig ist oder nicht, generieren Sie das Zugriffstoken aus dem gespeicherten Aktualisierungstoken ( Aktualisierungstoken ). Ich kann Ihnen das Beispiel zeigen.
  3. Nach der Anmeldung sollte jede Anfrage von der Client-Seite den Authorization-Header (Authorization: Bearer <token>).

Lassen Sie mich wissen, ob Sie mit den obigen Punkten klar sind.

6
Wellwisher
  • Laravel Passport ist eine Implementierung des PHP League OAuth Server
  • Der Kennwortgewährungstyp kann für die Authentifizierung mit Benutzername und Kennwort verwendet werden
  • Denken Sie daran, Ihre Client-Anmeldeinformationen zu verbergen, indem Sie die Authentifizierungsanforderung in einem Proxy ausführen
  • Speichern Sie das Aktualisierungstoken in einem HttpOnly-Cookie, um das Risiko von XSS-Angriffen zu minimieren

Weitere Informationen finden Sie hier

http://esbenp.github.io/2017/03/19/modern-rest-api-laravel-part-4/

6
Ismoil Shifoev

Ich werde versuchen, dies allgemein zu beantworten, damit die Antwort auf alle Frameworks, Implementierungen und Sprachen anwendbar ist, da die Antworten auf alle Fragen aus den allgemeinen Protokoll- oder Algorithmusspezifikationen abgeleitet werden können.

Welchen OAuth 2.0 Grant-Typ soll ich verwenden?

Dies ist das erste, was entschieden werden muss. Wenn es um SPA geht, gibt es zwei mögliche Optionen:

  1. Erteilung des Autorisierungscodes (empfohlen, sofern das Clientgeheimnis auf der Serverseite gespeichert ist)
  2. Berechtigungsnachweis für das Kennwort des Ressourcenbesitzers

Die Gründe, warum ich den impliziten Grant-Typ nicht als Option erwähne, sind:

  1. Der Clientauthentifizierungsschritt durch Angabe des Clientgeheimnisses und des Autorisierungscodes fehlt. Also weniger Sicherheit
  2. Das Zugriffstoken wird als URL-Fragment zurückgesendet (damit das Token nicht an den Server gesendet wird), das weiterhin im Browserverlauf verbleibt
  3. Bei einem XSS-Angriff kann das böswillige Skript das Token sehr gut an einen Remoteserver senden, der die Kontrolle über einen Angreifer hat

(Der Grant-Typ "Client-Anmeldeinformationen" wird in dieser Diskussion nicht berücksichtigt, da er verwendet wird, wenn der Client nicht im Namen eines Benutzers handelt. Beispielsweise für einen Batch-Job.)

Im Fall des Berechtigungscode-Zuteilungstyps ist der Berechtigungsserver normalerweise ein anderer Server als der Ressourcenserver. Es ist besser, den Autorisierungsserver getrennt zu halten und als gemeinsamen Autorisierungsserver für alle SPA innerhalb der Organisation zu verwenden. Dies ist immer die empfohlene Lösung.

Hier (im Berechtigungscode Grant Type) sieht der Ablauf wie folgt aus:

  1. der Benutzer klickt auf der SPA-Startseite auf die Anmeldeschaltfläche
  2. der Benutzer wird auf die Anmeldeseite des Autorisierungsservers umgeleitet. Die Client-ID wird im URL-Abfrageparameter angegeben
  3. Der Benutzer gibt seine Anmeldeinformationen ein und klickt auf die Anmeldeschaltfläche. Der Benutzername und das Kennwort werden über HTTP POST an den Autorisierungsserver gesendet. Die Anmeldeinformationen sollten im Anforderungshauptteil oder -header und NICHT in der URL gesendet werden (da URLs im Browserverlauf und auf dem Anwendungsserver protokolliert werden). Außerdem sollten die richtigen HTTP-Header für die Zwischenspeicherung festgelegt werden, damit die Anmeldeinformationen nicht zwischengespeichert werden: Cache-Control: no-cache, no-store, Pragma: no-cache, Expires: 0
  4. Der Autorisierungsserver authentifiziert den Benutzer anhand einer Benutzerdatenbank (z. B. LDAP-Server), in der der Benutzername und der Hash des Benutzerpassworts (Hashing-Algorithmen wie Argon2, PBKDF2, Bcrypt oder Scrypt) mit einem zufälligen Salt gespeichert sind
  5. Bei erfolgreicher Authentifizierung ruft der Autorisierungsserver die Weiterleitungs-URL anhand der im URL-Abfrageparameter angegebenen Client-ID aus seiner Datenbank ab. Die Weiterleitungs-URL ist die Ressourcen-Server-URL
  6. Der Benutzer wird dann mit einem Autorisierungscode im URL-Abfrageparameter zu einem Ressourcenserver-Endpunkt umgeleitet
  7. Der Ressourcenserver führt dann eine HTTP POST) - Anforderung an den Autorisierungsserver für das Zugriffstoken aus. Der Autorisierungscode, die Client-ID und das Client-Geheimnis sollten im Anforderungshauptteil enthalten sein verwendet werden)
  8. Der Autorisierungsserver würde das Zugriffstoken und das Aktualisierungstoken im Antworttext oder Header zurückgeben (mit dem entsprechenden Caching-Header, wie oben erwähnt).
  9. Der Ressourcenserver leitet den Benutzer (HTTP-Antwortcode 302) jetzt zur SPA-URL weiter, indem er entsprechende Cookies setzt (wird unten ausführlich erläutert).

Auf der anderen Seite sind der Berechtigungsserver und der Ressourcenserver für den Berechtigungsbewilligungstyp für das Kennwort des Ressourcenbesitzers identisch. Es ist einfacher zu implementieren und kann auch verwendet werden, wenn es den Anforderungen und Implementierungszeitplänen entspricht.

Lesen Sie auch meine Antwort zu hier , um weitere Informationen zum Grant-Typ des Ressourcenbesitzers zu erhalten.

Hierbei ist möglicherweise zu beachten, dass in einem SPA alle geschützten Routen erst nach dem Aufrufen eines entsprechenden Dienstes aktiviert werden sollten, um sicherzustellen, dass die Anforderung gültige Token enthält. In ähnlicher Weise sollten die geschützten APIs auch über geeignete Filter verfügen, um die Zugriffstoken zu validieren.

Warum sollte ich die Token nicht im lokalen Speicher oder im Sitzungsspeicher des Browsers speichern?

Viele SPAs speichern Zugriffs- und/oder Aktualisierungstoken im lokalen Speicher oder im Sitzungsspeicher des Browsers. Der Grund, warum wir die Token meiner Meinung nach nicht in diesen Browserspeichern speichern sollten, sind:

  1. Wenn XSS auftritt, kann das böswillige Skript die Token problemlos von dort aus lesen und an einen Remoteserver senden. Auf dieser Seite hätte der entfernte Server oder Angreifer kein Problem damit, sich als der Benutzer des Opfers auszugeben.

  2. localstorage und sessionstorage werden nicht von Subdomains gemeinsam genutzt. Wenn also zwei SPA auf verschiedenen Unterdomänen ausgeführt werden, erhalten wir die SSO-Funktionalität nicht, da das von einer App gespeicherte Token nicht für die andere App in der Organisation verfügbar ist

Wenn die Token jedoch noch in einem dieser Browserspeicher gespeichert sind, muss der richtige Fingerabdruck enthalten sein. Der Fingerabdruck ist eine kryptografisch starke zufällige Folge von Bytes. Die Base64-Zeichenfolge der Rohzeichenfolge wird dann in einem Cookie HttpOnly, Secure, SameSite mit dem Namenspräfix __Secure- Gespeichert. Richtige Werte für die Attribute Domain und Path. Ein SHA256-Hash des Strings wird auch in einem Claim von JWT übergeben. Selbst wenn ein XSS-Angriff das JWT-Zugriffstoken an einen angreifergesteuerten Remoteserver sendet, kann er die ursprüngliche Zeichenfolge nicht in einem Cookie senden. Infolgedessen kann der Server die Anforderung aufgrund des Fehlens des Cookies ablehnen. Außerdem können XSS- und Script-Injection durch die Verwendung eines geeigneten Antwort-Headers content-security-policy Weiter verringert werden.

Hinweis:

  1. SameSite=strict Stellt sicher, dass das angegebene Cookie nicht den Anfragen von einer anderen Site (AJAX oder über folgenden Hyperlink) beigefügt wird. Einfach ausgedrückt: Jede Anfrage von einer Site mit derselben "registrierbaren Domain" wie die Ziel-Site wird zugelassen. Z.B. Wenn " http: //www.example.com " der Name der Site ist, lautet die registrierbare Domain "example.com". Weitere Einzelheiten finden Sie unter Referenznr. 3 im letzten Abschnitt unten. Somit bietet es einen gewissen Schutz gegen CSRF. Dies bedeutet jedoch auch, dass ein authentifizierter Benutzer dem Link nicht folgen kann, wenn die angegebene URL ein Forum ist. Wenn dies eine schwerwiegende Einschränkung für eine Anwendung darstellt, kann SameSite=lax Verwendet werden, das standortübergreifende Anforderungen zulässt, solange die HTTP-Methoden sicher sind. GET, HEAD, OPTIONS und TRACE. Da CSRF auf unsicheren Methoden wie POST, PUT, DELETE und lax basiert, bietet es weiterhin Schutz vor CSRF

  2. Damit ein Cookie in allen Anfragen an eine Subdomain von "example.com" übergeben werden kann, sollte das Domain-Attribut des Cookies auf "example.com" gesetzt sein.

Warum sollte ich Zugriffstoken und/oder Aktualisierungstoken in Cookies speichern?

  1. Wenn wir die Token in Cookies speichern, können wir das Cookie als secure und httpOnly festlegen. Wenn also XSS auftritt, kann das böswillige Skript diese nicht lesen und an den Remote-Server senden. XSS kann weiterhin die Identität des Benutzers im Browser des Benutzers annehmen. Wenn der Browser jedoch geschlossen wird, kann das Skript keinen weiteren Schaden anrichten. Das Flag secure stellt sicher, dass die Token nicht über ungesicherte Verbindungen gesendet werden können - SSL/TLS ist obligatorisch
  2. Durch Festlegen der Stammdomäne im Cookie auf domain=example.com Wird beispielsweise sichergestellt, dass auf das Cookie in allen Unterdomänen zugegriffen werden kann. Auf diese Weise können verschiedene Apps und Server innerhalb der Organisation dieselben Token verwenden. Die Anmeldung ist nur einmal erforderlich

Wie überprüfe ich das Token?

Tokens sind normalerweise JWT-Tokens. Normalerweise ist der Inhalt des Tokens nicht geheim. Daher werden sie normalerweise nicht verschlüsselt. Wenn eine Verschlüsselung erforderlich ist (möglicherweise, weil im Token auch vertrauliche Informationen übergeben werden), gibt es eine separate Spezifikation für JWE. Auch wenn keine Verschlüsselung erforderlich ist, müssen wir die Integrität der Token sicherstellen. Niemand (Benutzer oder Angreifer) sollte in der Lage sein, die Token zu ändern. Wenn dies der Fall ist, sollte der Server dies erkennen und alle Anforderungen mit den gefälschten Token ablehnen können. Um diese Integrität sicherzustellen, werden die JWT-Token mit einem Algorithmus wie HmacSHA256 digital signiert. Um diese Signatur zu generieren, ist ein geheimer Schlüssel erforderlich. Der Autorisierungsserver wird das Geheimnis besitzen und schützen. Immer wenn die Berechtigungsserver-API aufgerufen wird, um ein Token zu validieren, berechnet der Berechtigungsserver die HMAC für das übergebene Token neu. Wenn es nicht mit dem Eingangs-HMAC übereinstimmt, gibt es eine negative Antwort zurück. Das JWT-Token wird in einem Base64-codierten Format zurückgegeben oder gespeichert.

Bei jedem API-Aufruf auf dem Ressourcenserver ist der Berechtigungsserver jedoch nicht zur Validierung des Tokens beteiligt. Der Ressourcenserver kann die vom Autorisierungsserver ausgegebenen Token zwischenspeichern. Der Ressourcenserver kann ein speicherinternes Datenraster (Redis) oder, wenn nicht alles im RAM gespeichert werden kann, eine LSM-basierte Datenbank (Riak mit Level-DB) zum Speichern der Token verwenden.

Bei jedem API-Aufruf überprüft der Ressourcenserver seinen Cache.

  1. Wenn das Zugriffstoken nicht im Cache vorhanden ist, sollten APIs eine entsprechende Antwortnachricht und einen 401-Antwortcode zurückgeben, sodass der SPA den Benutzer zu einer geeigneten Seite umleiten kann, auf der der Benutzer aufgefordert wird, sich erneut anzumelden

  2. Wenn das Zugriffstoken gültig, aber abgelaufen ist (Hinweis: Die JWT-Token enthalten in der Regel unter anderem den Benutzernamen und das Ablaufdatum), sollten APIs eine entsprechende Antwortnachricht und einen 401-Antwortcode zurückgeben, damit der SPA eine entsprechende Ressourcenserver-API aufrufen kann Erneuern Sie das Zugriffstoken mit dem Aktualisierungstoken (mit den entsprechenden Cache-Headern). Der Server ruft dann den Autorisierungsserver mit Zugriffstoken, Aktualisierungstoken und Clientgeheimnis auf, und der Autorisierungsserver kann die neuen Zugriffs- und Aktualisierungstoken zurückgeben, die schließlich (mit geeigneten Cache-Headern) an den SPA weitergeleitet werden. Dann muss der Client die ursprüngliche Anforderung wiederholen. All dies wird vom System ohne Benutzereingriff erledigt. Es könnte ein separates Cookie zum Speichern des Aktualisierungstokens erstellt werden, das dem Zugriffstoken ähnelt, jedoch den entsprechenden Wert für das Attribut Path aufweist, sodass das Aktualisierungstoken nicht jeder Anforderung beigefügt wird, sondern nur in Erneuerungsanforderungen verfügbar ist

  3. Wenn das Aktualisierungstoken ungültig oder abgelaufen ist, sollten APIs eine entsprechende Antwortnachricht und einen 401-Antwortcode zurückgeben, sodass der SPA den Benutzer zu einer geeigneten Seite umleiten kann, auf der der Benutzer aufgefordert wird, sich erneut anzumelden

Warum benötigen wir zwei Token - Zugriffstoken und Aktualisierungstoken?

  1. Zugriffstoken haben normalerweise eine kurze Gültigkeitsdauer, beispielsweise 30 Minuten. Aktualisierungs-Token haben normalerweise eine längere Gültigkeitsdauer, z. B. 6 Monate. Wenn das Zugriffstoken in irgendeiner Weise kompromittiert ist, kann der Angreifer die Identität des Opfernutzers nur annehmen, solange das Zugriffstoken gültig ist. Da der Angreifer das Clientgeheimnis nicht hat, kann er den Autorisierungsserver nicht nach einem neuen Zugriffstoken fragen. Der Angreifer kann jedoch den Ressourcenserver auffordern, das Token zu erneuern (wie im obigen Setup wird die Erneuerungsanforderung über den Ressourcenserver gesendet, um das Speichern des Clientgeheimnisses im Browser zu vermeiden). In Anbetracht der anderen Schritte ist dies jedoch unwahrscheinlich, und der Server kann dies auch Ergreifen Sie zusätzliche Schutzmaßnahmen basierend auf der IP-Adresse.

  2. Wenn diese kurze Gültigkeitsdauer des Zugriffstokens dem Autorisierungsserver hilft, die ausgestellten Token bei Bedarf von den Clients zu widerrufen. Der Autorisierungsserver kann auch einen Cache der ausgegebenen Token verwalten. Die Administratoren des Systems können dann bei Bedarf die Token bestimmter Benutzer als widerrufen markieren. Nach Ablauf des Zugriffstokens muss sich der Benutzer erneut anmelden, wenn der Ressourcenserver auf den Autorisierungsserver wechselt.

Was ist mit CSRF?

  1. Um den Benutzer vor CSRF zu schützen, können wir die Vorgehensweise in Frameworks wie Angular (wie in der Angular= HttpClient Dokumentation erklärt wo der Server ein Nicht-HttpOnly-Cookie senden muss (mit anderen Worten ein lesbares Cookie), das einen eindeutigen unvorhersehbaren Wert für diese bestimmte Sitzung enthält. Es sollte ein kryptographisch starker Zufallswert sein. Der Client wird dann immer das Cookie lesen und senden Sie den Wert in einem benutzerdefinierten HTTP-Header (außer GET & HEAD Anforderungen, für die keine Statusänderungslogik gelten soll). Hinweis CSRF kann aufgrund derselben Origin-Richtlinie keine Daten aus der Ziel-Webanwendung lesen Da die domänenübergreifenden Formulare das Cookie nicht lesen oder keine benutzerdefinierten Header festlegen können, fehlt bei CSRF-Anforderungen der benutzerdefinierte Header-Wert, und der Server kann dies den Angriff zu erkennen

  2. Um die Anwendung vor CSRF-Anmeldungen zu schützen, überprüfen Sie immer den Header referer und akzeptieren Sie Anforderungen nur, wenn referer eine vertrauenswürdige Domäne ist. Wenn der Header referer fehlt oder eine Domain ohne Whitelist ist, lehnen Sie die Anfrage einfach ab. Bei Verwendung von SSL/TLS ist in der Regel referrer vorhanden. Zielseiten (meistens zu Informationszwecken und ohne Anmeldeformular oder gesicherten Inhalt) sind möglicherweise etwas entspannt und erlauben Anfragen mit fehlendem referer -Header

  3. Die HTTP-Methode TRACE sollte auf dem Server blockiert sein, da dies zum Lesen des Cookies httpOnly verwendet werden kann

  4. Setzen Sie außerdem den Header Strict-Transport-Security: max-age=<expire-time>; includeSubDomains, Um nur gesicherte Verbindungen zuzulassen, um zu verhindern, dass Man-in-the-Middle die CSRF-Cookies einer Unterdomäne überschreibt

  5. Zusätzlich sollte die oben erwähnte Einstellung SameSite verwendet werden

Schließlich ist SSL/TLS für alle Kommunikationen obligatorisch - wie heute sind TLS-Versionen unter 1.1 für die PCI/DSS-Konformität nicht akzeptabel. Um die Geheimhaltung der Weiterleitung und die authentifizierte Verschlüsselung zu gewährleisten, sollten geeignete Chiffresuiten verwendet werden. Außerdem sollten die Zugriffs- und Aktualisierungstoken auf eine schwarze Liste gesetzt werden, sobald der Benutzer explizit auf "Abmelden" klickt, um die Möglichkeit eines Token-Missbrauchs zu vermeiden.

Verweise

  1. RFC 6749 - OAuth2.0
  2. OWASP JWT Cheat Sheet
  3. SameSite Cookie IETF Draft
  4. Cookie-Präfixe
  5. RFC 6265 - Cookie
3
Saptarshi Basu