web-dev-qa-db-de.com

JWT-Client überprüfen?

Ich habe eine nodejs-API mit einem eckigen Frontend. Die API verwendet erfolgreich JWT mit Pass, um die Endpunkte abzusichern. 

Ich bin mir jetzt bewusst, dass mein Frontend nach Ablauf der Token dem Benutzer immer noch erlaubt, meine API-Endpunkte anzufordern, ohne dass er dazu aufgefordert wird, seine Anmeldedaten erneut einzugeben, um ein neues Token zu erhalten. 

So generiert mein Backend das Token:

function generateToken(user) {
  return jwt.sign(user, secret, {
    expiresIn: 10080 // in seconds
  });
}

Um diese Logik zu implementieren, muss das JWT-Token auf der Clientseite überprüft werden. Q1, ist dies ein vernünftiger Ansatz. 

F2, die Bibliothek JWT , die ich verwende, scheint einen öffentlichen Schlüssel zu benötigen, um die Funktion verify() zu verwenden. Ich habe anscheinend keinen öffentlichen Schlüssel, nur ein Geheimnis, das ich gerade erfunden habe, also wurde es nicht mit einem Paar erzeugt. Woher kommt mein öffentlicher Schlüssel oder gibt es eine andere Möglichkeit, meinen Token ohne dies zu überprüfen? 

Es scheint alles offensichtlich zu sein und ich habe etwas verpasst. Entschuldigung, wenn es sich um eine dumme Frage handelt, aber ich kann die Antwort nicht zu finden?

7
George Edwards

TL; DR

  1. Sie müssen überprüfen die Signatur von JWS im Server immer.
  2. Überprüfung der clientseitigen Signatur gibt nicht viel, es sei denn, Sie haben einen bestimmten Fall, in dem es sinnvoll ist tun Sie es nicht.
  3. Sie müssen die Signatur eines JWS-Tokens nicht überprüfen, um das Ablaufdatum zu überprüfen im Client. (Sofern Sie die Ansprüche nicht verschlüsselt haben, auch bekannt als JWE, müssen Sie in diesem Fall etwas Ähnliches tun, da Sie einen Schlüssel zum Entschlüsseln der Ansprüche benötigen.).
  4. Sie müssen auch nicht die Signatur eines JWS überprüfen, um das Ablaufdatum auf dem Server zu überprüfen. Dies sollte jedoch so sein, dass Sie die Gewissheit haben, dass niemand das Ablaufdatum geändert hat. Andernfalls schlägt die Überprüfung fehl wird sich unterscheiden)
  5. Um unverschlüsselte Ansprüche zu lesen, müssen Sie sie nur entschlüsseln. Sie können jwt-decode im Client verwenden.

Ich bin mir jetzt bewusst, dass der Benutzer nach dem Ablauf der Token über mein Front-End weiterhin meine API-Endpunkte anfordern kann. [...]

Um diese Logik zu implementieren, muss das JWT-Token meines Erachtens clientseitig überprüft werden

Wenn ich Sie richtig verstanden habe, möchten Sie prüfen, ob eine JWS auf der Clientseite abgelaufen ist. Zu diesem Zweck müssen Sie die Tokensignatur nicht überprüfen (obwohl die von Ihnen verwendete Bibliothek zu tun scheint beides gleichzeitig ), sondern können auch die Ablaufsteuerung deaktivieren mit ignoreExpiration flag). (Es sei denn, Sie verschlüsseln die Ansprüche, auch bekannt als JWE) Das RFC 7515 (JWS) sagt nichts über den Ablauf aus. Nachrichtensignatur oder MAC-Validierung kontrolliert nicht den Ablauf (und sollte auch nicht, weil Signaturen Ihnen Authentizität und Integrität verleihen). Sogar das RFC 7519 (JWT) kontrolliert nicht den Ablaufanspruch für die Lösung, ob ein JWT gültig ist oder nicht .

Auch alle Ansprüche sind optional .

Sie können also überprüfen, ob ein JWT abgelaufen ist oder nicht, ohne die Signatur zu überprüfen. Daher benötigen Sie weder einen öffentlichen Schlüssel (für asymmetrische Verschlüsselung wie RSA) noch einen geheimen Schlüssel (für symmetrische Verschlüsselung wie AES). In JWT- und JWS-Token sind die Ansprüche nur im Nur-Text-Base64-Format codiert. Sie können also einfach die Nutzdaten decodieren, ohne zu überprüfen, ob die Signatur gültig ist und den Ablaufanspruch lesen. Wenn Sie die Nutzdaten verschlüsseln (auch bekannt als JWE), können Sie dies nicht tun.

Eine Notiz aus jjwt library

JWTs können kryptografisch signiert (zu einem [~ # ~] jws [~ # ~]) oder verschlüsselt (macht es zu einem [~ # ~] jwe [~ # ~]).

Hier ist eine ligthweigte Bibliothek von auth0 zum Dekodieren der base64-kodierten Ansprüche eines JWT/JWS-Tokens. Ein Typ fragt sogar nach Überprüfung des Ablaufs .

Ich weiß nicht, warum Sie der Meinung sind, dass Sie diese Steuerung clientseitig durchführen sollten. Der einzige Vorteil besteht darin, dass Sie vermeiden, API-Anforderungen zu senden, von denen der Client weiß, dass sie fehlschlagen. Und sie sollten fehlschlagen, da der Server überprüfen sollte, ob das Token nicht abgelaufen ist. Eine vorherige Signaturüberprüfung (mit geheimem/privatem Schlüssel) ist offensichtlich.

Das RFC 7519 sagt über diese Behauptung:

Die Angabe "exp" (expiration time) gibt die Ablaufzeit an, ab der das JWT DARF NICHT zur Verarbeitung angenommen werden.

In einer Web-App wie der, die Sie als Tokens bezeichnen, können zustandslose Server Client-Anforderungen authentifizieren. Das Ziel des optionalen Anspruchs [~ # ~] [~ # ~] besteht darin, dem Server eine gewisse Kontrolle über das generierte JWS zu ermöglichen (wenn wir JWT für die Authentifizierung verwenden, ist das Signieren ein müssen, damit wir über JWS sprechen sollten).

Ohne Ablauf sind die Token für immer oder solange gültig, bis sich der zum Signieren verwendete Schlüssel ändert (dies führt dazu, dass der Überprüfungsprozess fehlschlägt). Übrigens ist ngültig machenSitzungen einer der bekanntesten Nachteile bei der Verwendung der statuslosen Authentifizierung.

Die Ungültigmachung einer Sitzung wird zu einem echten Problem, wenn wir Informationen in die JWS-Nutzdaten (oder Ansprüche) aufnehmen, die für die Autorisierung verwendet werden, z. B. welche Rollen der Benutzer hat.

From Verwenden Sie JWT nicht mehr für Sitzungen

im Ernst, es kann auch bedeuten, dass jemand ein Token mit der Rolle eines Administrators hat, obwohl Sie gerade die Rolle eines Administrators widerrufen haben. Da Sie Token auch nicht ungültig machen können, können Sie deren Administratorzugriff nicht entfernen

Die Ablaufsteuerung löst dieses Problem nicht und ist meiner Meinung nach eher darauf ausgerichtet, Sitzungsentführungen oder CSRF-Angriffe zu vermeiden.

Ein Angreifer, der CSRF verwendet, kann mit einer abgelaufenen JWS eine Anforderung an Ihre API senden, wobei die Ablaufsteuerung übersprungen wird.

Ein anderes Problem ist die Überprüfung der Signatur im Client mithilfe des öffentlichen oder geheimen Schlüssels.

Was Ihre Frage betrifft

Ich verwende anscheinend einen öffentlichen Schlüssel, um die Funktion verify () zu verwenden. Ich habe anscheinend keinen öffentlichen Schlüssel, nur ein Geheimnis, das ich mir gerade ausgedacht habe, also wurde es nicht mit einem Paar generiert.

Die Überprüfungsmethode, auf die Sie hingewiesen haben, besagt ausdrücklich, dass sie einen öffentlichen oder geheimen Schlüssel akzeptiert.

jwt.verify(token, secretOrPublicKey, [options, callback])

secretOrPublicKey ist eine Zeichenfolge oder ein Puffer, der entweder das Geheimnis für HMAC-Algorithmen oder den PEM-codierten öffentlichen Schlüssel für RSA und ECDSA enthält

Ich nehme an, Sie verwenden keine und Sie verwenden eine Zeichenfolge wie 'shhhh'.

var token = jwt.sign({ data: '¿Donde esta Santiago?'}, 'shhhh');

Dann solltest du tun

var decoded = jwt.verify(token, 'shhhhh');

Hier stellt sich jedoch die Frage, ob die clientseitige Signaturüberprüfung wirklich erforderlich ist.

Ich denke nicht, zumindest nicht für diese Art von Anwendung, bei der der Client nur die JWS verwendet, um eine nachfolgende Anfrage an den Server zu senden: "Hey Server, ich bin Gabriel und ich habe hier ein Papier (Token), das dies und das sicherstellt dieses Papier ist von Ihnen unterschrieben. " Wenn der Client das JWS nicht validiert und ein MITM dem Client erfolgreich ein von ihm signiertes JWS (statt des vom Server signierten JWS) gegeben hat, schlägt die nachfolgende Anforderung einfach fehl. Wie bei der Ablaufsteuerung verhindert die Signaturüberprüfung nur, dass der Client eine Anfrage stellt, die fehlschlägt.

Für die clientseitige Überprüfung muss jetzt der öffentliche oder geheime Schlüssel gesendet werden. Das Senden eines öffentlichen Schlüssels stellt keine Sicherheitsbedenken dar, ist jedoch ein zusätzlicher Aufwand und eine Verarbeitung mit geringen Vorteilen.

Das Senden geheimer Schlüssel (wie "shhhh") kann ein Sicherheitsproblem darstellen, da es sich um denselben Schlüssel handelt, der zum Signieren von Token verwendet wird.

11
gabrielgiussi

Q1: Die Tokenüberprüfung auf dem Client ist eine schlechte Idee. Sie können ein Token zusammen mit demselben abgelaufenen Datum auf dem Client speichern und dann ein Token aktualisieren/entfernen. Meiner Meinung nach ist es jedoch besser, ein Datum auf Server-Seite prüfen zu lassen, da es eine einfache Regel gibt: Vertrauen Sie dem Client nicht Es kann immer bösartigen Code senden. 

Q2: JWT benötigt keinen öffentlichen Schlüssel. Es muss immer ein privater Schlüssel auf der Serverseite gespeichert werden, wenn jemand Ihren geheimen Schlüssel kennt und Ihr Token keinen Sinn macht. Sie können nur etwas Nutzlast hinzufügen, um es komplexer zu machen.

1
Dmitry

Ich denke, JWT-Token auf Clientseite zu überprüfen, ist keine gute Idee.
IMO;

  1. Wenn sich ein Benutzer anmeldet, generieren Sie ein Zugriffs- und Aktualisierungstoken und geben Sie dem Benutzer so etwas zurück.

    { "accessToken": <<accessToken>> "refreshToken": <<refreshToken>> "expiresAt": <<expiresAt>> } 

    Der Client kann also verstehen, wann das Zugriffstoken abläuft, und es mit einem Aktualisierungstoken aktualisieren.

  2. Verschlüsseln Sie die Daten, die Sie in das Zugriffstoken eingeben, da die Möglichkeit besteht, ohne geheimen Schlüssel auf die Daten zuzugreifen. Aber natürlich muss jemand einen geheimen Schlüssel zur Bestätigung haben. 

0
ugursogukpinar