(Aus diesem Thread hervorgegangen, da dies wirklich eine eigene Frage ist und nicht spezifisch für NodeJS usw.)
Ich implementiere einen REST-API-Server mit Authentifizierung und habe die Behandlung von JWT-Token erfolgreich implementiert, sodass sich ein Benutzer über einen / login-Endpunkt mit Benutzername / Kennwort anmelden kann, auf dem ein JWT-Token aus einem Servergeheimnis generiert und an das zurückgegeben wird Klient. Das Token wird dann in jeder authentifizierten API-Anforderung vom Client an den Server übergeben, bei der das Servergeheimnis zur Überprüfung des Tokens verwendet wird.
Ich versuche jedoch, die Best Practices genau zu verstehen, wie und in welchem Umfang das Token validiert werden sollte, um ein wirklich sicheres System zu erstellen. Was genau sollte bei der "Validierung" des Tokens eine Rolle spielen? Reicht es aus, dass die Signatur mithilfe des Servergeheimnisses überprüft werden kann, oder sollte ich auch das Token und / oder die Token-Nutzdaten mit einigen auf dem Server gespeicherten Daten vergleichen?
Ein tokenbasiertes Authentifizierungssystem ist nur so sicher wie die Übergabe von Benutzername / Passwort bei jeder Anforderung, vorausgesetzt, es ist genauso oder schwieriger, ein Token zu erhalten, als das Passwort eines Benutzers. In den Beispielen, die ich gesehen habe, sind die einzigen Informationen, die zum Erstellen eines Tokens erforderlich sind, der Benutzername und das serverseitige Geheimnis. Bedeutet dies nicht, dass ein böswilliger Benutzer, der für eine Minute Kenntnis vom Servergeheimnis erlangt, nun im Namen eines jeden Benutzers Token erstellen kann , wodurch er nicht nur auf einen bestimmten Benutzer zugreifen kann, wie dies bei einem Kennwort der Fall wäre erhalten, aber in der Tat zu allen Benutzerkonten?
Dies bringt mich zu den Fragen:
1) Sollte sich die JWT-Token-Validierung darauf beschränken, die Signatur des Tokens selbst zu überprüfen, sich nur auf die Integrität des Servergeheimnisses zu verlassen oder von einem separaten Validierungsmechanismus begleitet zu werden?
In einigen Fällen habe ich die kombinierte Verwendung von Token und Serversitzungen gesehen, bei denen nach erfolgreicher Anmeldung über den Endpunkt / login eine Sitzung eingerichtet wird. API-Anforderungen validieren das Token und vergleichen die im Token gefundenen decodierten Daten mit einigen in der Sitzung gespeicherten Daten. Die Verwendung von Sitzungen bedeutet jedoch die Verwendung von Cookies und macht in gewissem Sinne den Zweck der Verwendung eines tokenbasierten Ansatzes zunichte. Dies kann auch bei bestimmten Clients zu Problemen führen.
Man könnte sich vorstellen, dass der Server alle derzeit verwendeten Token in einem Memcache oder ähnlichem aufbewahrt, um sicherzustellen, dass selbst wenn das Servergeheimnis kompromittiert wird, sodass ein Angreifer "gültige" Token erstellen kann, nur die genauen Token, die über den Endpunkt / login generiert wurden würde akzeptiert werden. Ist das vernünftig oder nur überflüssig / übertrieben?
2) Wenn die Überprüfung der JWT-Signatur das einzige Mittel zur Validierung von Token ist, dh die Integrität des Servergeheimnisses die Bruchstelle darstellt, wie sollten Servergeheimnisse verwaltet werden? Aus einer Umgebungsvariablen lesen und einmal pro bereitgestelltem Stapel erstellen (randomisiert?)? In regelmäßigen Abständen neu aktualisiert oder gedreht (und wenn ja, wie mit vorhandenen gültigen Token umgegangen wird, die vor der Drehung erstellt wurden, aber nach der Drehung überprüft werden müssen, reicht es möglicherweise aus, wenn der Server zu einem bestimmten Zeitpunkt das aktuelle und das vorherige Geheimnis beibehält). ? Etwas anderes?
Vielleicht bin ich einfach zu paranoid, wenn es um das Risiko geht, dass das Servergeheimnis kompromittiert wird, was natürlich ein allgemeineres Problem ist, das in allen kryptografischen Situationen angegangen werden muss ...
RSAPrivateKey privateKey
??Antworten:
Ich habe auch für meine Anwendung mit Token gespielt. Obwohl ich keineswegs ein Experte bin, kann ich einige meiner Erfahrungen und Gedanken zu diesem Thema teilen.
Der Punkt von JWTs ist im Wesentlichen Integrität. Es bietet einen Mechanismus für Ihren Server, mit dem überprüft wird, ob das ihm zur Verfügung gestellte Token echt ist und von Ihrem Server bereitgestellt wurde. Die über Ihr Geheimnis erzeugte Signatur sorgt dafür. Also, ja, wenn Ihr Geheimnis irgendwie durchgesickert ist, kann diese Person Token generieren, die Ihr Server für seine eigenen halten würde. Ein tokenbasiertes System wäre allein aufgrund der Signaturüberprüfung immer noch sicherer als Ihr Benutzername / Passwort-System. Und in diesem Fall, wenn jemand Ihr Geheimnis trotzdem hat, hat Ihr System andere Sicherheitsprobleme zu lösen als jemand, der gefälschte Token herstellt (und selbst dann stellt das Ändern des Geheimnisses sicher, dass alle mit dem alten Geheimnis erstellten Token jetzt ungültig sind).
Was die Nutzlast betrifft, sagt Ihnen die Signatur nur, dass das Ihnen zur Verfügung gestellte Token genau so war, wie es war, als Ihr Server es gesendet hat. Es liegt natürlich an Ihnen, zu überprüfen, ob der Inhalt der Nutzdaten gültig oder für Ihre Anwendung geeignet ist.
Für Ihre Fragen:
1.) Nach meiner begrenzten Erfahrung ist es definitiv besser, Ihre Token mit einem zweiten System zu überprüfen. Das einfache Überprüfen der Signatur bedeutet lediglich, dass das Token mit Ihrem Geheimnis generiert wurde. Das Speichern aller erstellten Token in einer Art Datenbank (Redis, Memcache / SQL / Mongo oder einem anderen Speicher) ist eine fantastische Möglichkeit, um sicherzustellen, dass Sie nur Token akzeptieren, die Ihr Server erstellt hat. Selbst wenn Ihr Geheimnis durchgesickert ist, spielt es in diesem Szenario keine große Rolle, da generierte Token ohnehin nicht gültig sind. Dies ist der Ansatz, den ich mit meinem System verfolge: Alle generierten Token werden in einer Datenbank (Redis) gespeichert. Bei jeder Anforderung überprüfe ich, ob sich das Token in meiner Datenbank befindet, bevor ich es akzeptiere. Auf diese Weise können Token aus irgendeinem Grund widerrufen werden, z. B. Token, die irgendwie in die Wildnis entlassen wurden, Benutzerabmeldung, Kennwortänderungen, geheime Änderungen usw.
2.) Dies ist etwas, in dem ich nicht viel Erfahrung habe und das ich immer noch aktiv erforsche, da ich kein Sicherheitsexperte bin. Wenn Sie Ressourcen finden, können Sie diese hier posten! Derzeit verwende ich nur einen privaten Schlüssel, den ich von der Festplatte lade, aber das ist offensichtlich alles andere als die beste oder sicherste Lösung.
quelle
Bei der Implementierung von JWTs in Ihrer Anwendung sind folgende Punkte zu beachten:
Halten Sie Ihre JWT-Lebensdauer relativ kurz und lassen Sie sie auf dem Server verwalten. Wenn Sie dies nicht tun und später weitere Informationen in Ihren JWTs benötigen, müssen Sie entweder zwei Versionen unterstützen oder warten, bis Ihre älteren JWTs abgelaufen sind, bevor Sie Ihre Änderung implementieren können. Sie können es einfach auf dem Server verwalten, wenn Sie nur das
iat
Feld im JWT betrachten und dasexp
Feld ignorieren .Erwägen Sie, die URL der Anfrage in Ihr JWT aufzunehmen. Wenn Sie beispielsweise möchten, dass Ihr JWT am Endpunkt verwendet wird
/my/test/path
, fügen Sie ein Feld wie'url':'/my/test/path'
in Ihrem JWT ein, um sicherzustellen, dass es immer nur auf diesem Pfad verwendet wird. Wenn Sie dies nicht tun, stellen Sie möglicherweise fest, dass Benutzer Ihre JWTs an anderen Endpunkten verwenden, auch an solchen, für die sie nicht erstellt wurden. Sie könnten auch in Betracht ziehen, stattdessen eine md5 (URL) einzuschließen, da eine große URL in der JWT die JWT so viel größer macht und sie ziemlich groß werden können.Der JWT-Ablauf sollte für jeden Anwendungsfall konfigurierbar sein, wenn JWTs in einer API implementiert werden. Wenn Sie beispielsweise 10 Endpunkte für 10 verschiedene Anwendungsfälle für JWTs haben, stellen Sie sicher, dass jeder Endpunkt JWTs akzeptieren kann, die zu unterschiedlichen Zeiten ablaufen. Auf diese Weise können Sie einige Endpunkte mehr als andere sperren, wenn beispielsweise die von einem Endpunkt bereitgestellten Daten sehr vertraulich sind.
Anstatt JWTs nach einer bestimmten Zeit einfach abzulaufen, sollten Sie JWTs implementieren, die beide unterstützen:
Alle JWT-Authentifizierungsfehler sollten einen "Fehler" -Antwortheader generieren, der angibt, warum die JWT-Authentifizierung fehlgeschlagen ist. zB "abgelaufen", "keine Verwendungen mehr", "widerrufen" usw. Dies hilft Implementierern zu erkennen, warum ihre JWT ausfällt.
Ignorieren Sie den "Header" Ihrer JWTs, da diese Informationen verlieren und Hackern ein gewisses Maß an Kontrolle geben. Dies betrifft hauptsächlich das
alg
Feld im Header. Ignorieren Sie dies und gehen Sie einfach davon aus, dass der Header das ist, was Sie unterstützen möchten, da Hacker nicht versuchen, denNone
Algorithmus zu verwenden, wodurch die Sicherheitsüberprüfung der Signatur entfernt wird.JWTs sollten eine Kennung enthalten, die angibt, welche App das Token generiert hat. Wenn Ihre JWTs beispielsweise von zwei verschiedenen Clients, mychat und myclassifiedsapp, erstellt werden, sollte jeder seinen Projektnamen oder ähnliches in das Feld "iss" im JWT aufnehmen, z. B. "iss": "mychat".
iat
(ausgegeben at) stattexp
(Ablauf) in Ihrem JWTs. Warum? Da dies imiat
Grunde bedeutet, wann die JWT erstellt wurde, können Sie auf dem Server anpassen, wann die JWT abläuft, basierend auf dem Erstellungsdatum. Wenn jemand inexp
20 Jahren in der Zukunft verstirbt, lebt der JWT im Grunde für immer! Beachten Sie, dass Sie JWTs automatisch ablaufen lassen, wenn sieiat
in der Zukunft liegen. Lassen Sie jedoch ein wenig Spielraum (z. B. 10 Sekunden), falls die Zeit des Clients nicht mit der Serverzeit übereinstimmt ./mysite/userInfo?jwt=XXX
, und diese URL wird zwischengespeichert. Sie melden sich ab und ein paar Minuten später meldet sich ein normaler Benutzer bei Ihrer App an. Sie erhalten den zwischengespeicherten Inhalt - mit Informationen über einen Superuser! Dies geschieht in der Regel weniger auf dem Client als auf dem Server, insbesondere in Fällen, in denen Sie ein CDN wie Akamai verwenden und einige Dateien länger leben lassen. Dies kann behoben werden, indem die relevanten Benutzerinformationen in die URL aufgenommen und auf dem Server überprüft werden, beispielsweise auch für zwischengespeicherte Anforderungen/mysite/userInfo?id=52&jwt=XXX
quelle
created_by
, gibt es in JWT bereits einen Anspruch dafür und er heißtiss
(Emittent).Ich glaube nicht, dass ich ein Experte bin, aber ich möchte einige Gedanken über Jwt teilen.
1: Wie Akshay sagte, ist es besser, ein zweites System zu haben, um Ihr Token zu validieren.
a.: So gehe ich damit um: Ich speichere den generierten Hash mit der Ablaufzeit in einem Sitzungsspeicher. Um ein Token zu validieren, muss es vom Server ausgestellt worden sein.
b.: Es gibt mindestens eine Sache, die die verwendete Signaturmethode überprüft werden muss. z.B :
Einige Bibliotheken, die JWT validieren, akzeptieren diese, ohne den Hash zu überprüfen. Das bedeutet, dass sich ein Hacker, ohne zu wissen, dass Ihr Salz zum Signieren des Tokens verwendet wurde, einige Rechte gewähren könnte. Stellen Sie immer sicher, dass dies nicht passieren kann. https://auth0.com/blog/2015/03/31/critical-vulnerabilities-in-json-web-token-libraries/
c.: Die Verwendung eines Cookies mit einer Sitzungs-ID wäre nicht hilfreich, um Ihr Token zu validieren. Wenn jemand die Sitzung eines Lambda-Benutzers entführen möchte, muss er nur einen Schnüffler verwenden (z. B. Wireshark). Dieser Hacker würde beide Informationen gleichzeitig haben.
Die Art und Weise, wie ich damit umgehe, hängt mit dem Punkt 1.a zusammen. : Ich habe ein Geheimnis mit einer Zufallsvariablen gemischt. Das Geheimnis ist für jeden Token einzigartig.
Wenn Sie die bestmögliche Sicherheit wünschen, sollten Sie die Best Practices nicht blind befolgen. Der beste Weg ist zu verstehen, was Sie tun (ich denke, es ist in Ordnung, wenn ich Ihre Frage sehe) und dann die Sicherheit zu bewerten, die Sie benötigen. Und wenn der Mossad Zugang zu Ihren vertraulichen Daten haben möchte, wird er immer einen Weg finden. (Ich mag diesen Blog-Beitrag: https://www.schneier.com/blog/archives/2015/08/mickens_on_secu.html )
quelle
Viele gute Antworten hier. Ich werde einige der Antworten integrieren, die meiner Meinung nach am relevantesten sind, und weitere Vorschläge hinzufügen.
1) Sollte sich die JWT-Token-Validierung darauf beschränken, die Signatur des Tokens selbst zu überprüfen, sich nur auf die Integrität des Servergeheimnisses zu verlassen oder von einem separaten Validierungsmechanismus begleitet zu werden?
Nein, aus Gründen, die nichts mit dem Kompromiss eines Token-Geheimnisses zu tun haben. Jedes Mal, wenn sich ein Benutzer über einen Benutzernamen und ein Kennwort anmeldet, sollte der Autorisierungsserver entweder das generierte Token oder Metadaten zu dem generierten Token speichern. Stellen Sie sich diese Metadaten als Autorisierungsdatensatz vor. Ein bestimmtes Benutzer- und Anwendungspaar sollte zu einem bestimmten Zeitpunkt nur ein gültiges Token oder eine gültige Berechtigung haben. Nützliche Metadaten sind die Benutzer-ID, die dem Zugriffstoken zugeordnet ist, die App-ID und der Zeitpunkt, zu dem das Zugriffstoken ausgestellt wurde (dies ermöglicht den Widerruf vorhandener Zugriffstoken und die Ausgabe eines neuen Zugriffstokens). Überprüfen Sie bei jeder API-Anforderung, ob das Token die richtigen Metadaten enthält. Sie müssen Informationen darüber beibehalten, wann die einzelnen Zugriffstoken ausgestellt wurden. Damit ein Benutzer vorhandene Zugriffstoken widerrufen kann, wenn seine Kontoanmeldeinformationen gefährdet sind, sich erneut anmelden und ein neues Zugriffstoken verwenden kann. Dadurch wird die Datenbank mit dem Zeitpunkt aktualisiert, zu dem das Zugriffstoken ausgestellt wurde (die erstellte Autorisierungszeit). Überprüfen Sie bei jeder API-Anforderung, ob die Ausgabezeit des Zugriffstokens nach der erstellten Autorisierungszeit liegt.
Andere Sicherheitsmaßnahmen umfassten das Nichtprotokollieren von JWTs und das Erfordernis eines sicheren Signaturalgorithmus wie SHA256.
2) Wenn die Überprüfung der JWT-Signatur das einzige Mittel zur Validierung von Token ist, dh die Integrität des Servergeheimnisses die Bruchstelle darstellt, wie sollten Servergeheimnisse verwaltet werden?
Die Kompromittierung von Servergeheimnissen würde es einem Angreifer ermöglichen, Zugriffstoken für jeden Benutzer auszugeben, und das Speichern von Zugriffstoken-Daten in Schritt 1 würde den Server nicht unbedingt daran hindern, diese Zugriffstoken zu akzeptieren. Angenommen, einem Benutzer wurde ein Zugriffstoken ausgestellt, und später generiert ein Angreifer ein Zugriffstoken für diesen Benutzer. Die Autorisierungszeit des Zugriffstokens wäre gültig.
Wie Akshay Dhalwala sagt, haben Sie größere Probleme, wenn Ihr serverseitiges Geheimnis gefährdet ist, da dies bedeutet, dass ein Angreifer Ihr internes Netzwerk, Ihr Quellcode-Repository oder beides gefährdet hat.
Ein System zur Minderung des Schadens eines gefährdeten Servergeheimnisses und zur Vermeidung des Speicherns von Geheimnissen im Quellcode umfasst jedoch die Rotation von Token-Geheimnissen mithilfe eines Koordinierungsdienstes wie https://zookeeper.apache.org. Verwenden Sie einen Cron-Job, um etwa alle paar Stunden ein App-Geheimnis zu generieren (unabhängig davon, wie lange Ihre Zugriffstoken gültig sind), und senden Sie das aktualisierte Geheimnis an Zookeeper. Konfigurieren Sie auf jedem Anwendungsserver, der das Token-Geheimnis kennen muss, einen ZK-Client, der aktualisiert wird, wenn sich der ZK-Knotenwert ändert. Speichern Sie ein primäres und ein sekundäres Geheimnis. Setzen Sie bei jeder Änderung des Token-Geheimnisses das neue Token-Geheimnis auf das primäre und das alte Token-Geheimnis auf das sekundäre. Auf diese Weise sind vorhandene gültige Token weiterhin gültig, da sie anhand des sekundären Geheimnisses validiert werden. Wenn das sekundäre Geheimnis durch das alte primäre Geheimnis ersetzt wird, sind alle mit dem sekundären Geheimnis ausgestellten Zugriffstoken sowieso abgelaufen.
quelle
IETF hat einen RFC in der oAuth-Arbeitsgruppe in Bearbeitung, siehe: https://tools.ietf.org/id/draft-ietf-oauth-jwt-bcp-05.html
quelle