Wie kann ich ein JWT-Token widerrufen?

73

Ich verwende Spring Security OAuth2- und JWT-Token. Meine Frage lautet: Wie kann ich ein JWT-Token widerrufen?

Wie hier erwähnt, http://projects.spring.io/spring-security-oauth/docs/oauth2.html , erfolgt der Widerruf durch ein Aktualisierungstoken. Aber es scheint nicht zu funktionieren.

Sabu
quelle
2
Dies ist nicht möglich, es sei denn, Sie erstellen eine Aufzeichnung der auf dem Autorisierungsserver ausgegebenen Token. Die Ressourcen-API, die das Token verwendet, müsste auch prüfen, ob das Token widerrufen wurde.
Shaun das Schaf
Hast du etwas gefunden oder nicht? Auch wenn ich eine Aufzeichnung von Token erstellen will, denke ich, dass Oauth nicht staatenlos ist?
Aman Verma
+1 zu Shauns Kommentaren und fügt hinzu, dass es normalerweise den Punkt zunichte macht, JWTs (oder By-Value) -Token zu haben, um dies zu tun.
Hans Z.
2
Shauns Kommentar ist falsch oder zumindest nicht ganz richtig. Sie müssen zwischen Zugriffs- und Aktualisierungstoken unterscheiden. Obwohl es nicht sinnvoll ist, Zugriffstoken ungültig zu machen, können Sie dies mit Aktualisierungstoken tun. In einem Szenario, in dem Sie eine Ablaufzeit von beispielsweise 15 für Zugriffstoken und möglicherweise eine Woche für Aktualisierungstoken haben, können Sie leicht erkennen, was Sie durch Ungültigmachen des Aktualisierungstokens erreichen können. Auf diese Weise müssen Sie nichts an Ressourcenserver weitergeben und verlieren nicht die Staatenlosigkeit.
Fechter
... Dies setzt natürlich voraus, dass Sie Ihre Access-Token nur auf dem Auth-Server aktualisieren.
Fechter

Antworten:

94

Im Allgemeinen wäre die einfachste Antwort zu sagen, dass Sie ein JWT-Token nicht widerrufen können, aber das stimmt einfach nicht . Die ehrliche Antwort lautet, dass die Kosten für die Unterstützung des Widerrufs von JWT so hoch sind, dass sie die meiste Zeit nicht wert sind oder eine Alternative zu JWT eindeutig überdenken.

In einigen Szenarien benötigen Sie möglicherweise sowohl JWT als auch einen sofortigen Token-Widerruf. Lassen Sie uns also durchgehen, was erforderlich ist, aber zuerst werden wir einige Konzepte behandeln.

JWT ( Learn JSON Web Tokens ) gibt nur ein Token-Format an. Dieses Widerrufsproblem würde auch für jedes Format gelten, das in einem normalerweise als eigenständiges Token oder nach Wert bezeichneten Token verwendet wird. Ich mag die letztere Terminologie, weil sie einen guten Kontrast zu den Referenztoken bildet.

By-Value-Token - Zugeordnete Informationen, einschließlich der Token-Lebensdauer, sind im Token selbst enthalten, und die Informationen können als von einer vertrauenswürdigen Quelle stammend überprüft werden (digitale Signaturen zur Rettung).

Referenztoken - Die zugehörigen Informationen werden im serverseitigen Speicher gespeichert, der dann unter Verwendung des Tokenwerts als Schlüssel abgerufen wird. Als serverseitiger Speicher werden die zugehörigen Informationen implizit als vertrauenswürdig eingestuft

Vor dem JWT-Urknall haben wir uns bereits mit Token in unseren Authentifizierungssystemen befasst. Es war üblich, dass eine Anwendung bei der Benutzeranmeldung eine Sitzungskennung erstellte, die dann verwendet wurde, damit der Benutzer den Anmeldevorgang nicht jedes Mal wiederholen musste. Diese Sitzungskennungen wurden als Schlüsselindizes für den serverseitigen Speicher verwendet. Wenn dies ähnlich klingt wie etwas, das Sie kürzlich gelesen haben, haben Sie Recht, dies wird tatsächlich als Referenztoken klassifiziert.

Unter Verwendung der gleichen Analogie ist es trivial, den Widerruf für Referenztoken zu verstehen. Wir löschen nur den serverseitigen Speicher, der diesem Schlüssel zugeordnet ist, und wenn der Schlüssel das nächste Mal bereitgestellt wird, ist er ungültig.

Für By-Value-Token müssen wir nur das Gegenteil implementieren. Wenn Sie den Widerruf des Tokens anfordern, speichern Sie etwas, mit dem Sie dieses Token eindeutig identifizieren können, sodass Sie beim nächsten Empfang zusätzlich prüfen können, ob es widerrufen wurde. Wenn Sie bereits der Meinung sind, dass sich so etwas nicht skalieren lässt, müssen Sie die Daten nur bis zum Ablauf des Tokens speichern. In den meisten Fällen können Sie wahrscheinlich nur einen Hash des Tokens speichern, damit dies immer der Fall ist etwas von einer bekannten Größe sein.

Als letzte Anmerkung und um dies auf OAuth 2.0 zu zentrieren, ist der Widerruf von Zugriffstoken nach Wert derzeit nicht standardisiert. Der OAuth 2.0-Token-Widerruf besagt jedoch ausdrücklich, dass er weiterhin erreicht werden kann, solange sowohl der Autorisierungsserver als auch der Ressourcenserver einer benutzerdefinierten Vorgehensweise zustimmen:

Im ersteren Fall ( in sich geschlossene Token ) kann eine (derzeit nicht standardisierte) Backend-Interaktion zwischen dem Autorisierungsserver und dem Ressourcenserver verwendet werden, wenn ein sofortiger Widerruf des Zugriffstokens gewünscht wird.

Wenn Sie sowohl den Autorisierungsserver als auch den Ressourcenserver steuern, ist dies sehr einfach zu erreichen. Wenn Sie andererseits die Autorisierungsserverrolle an einen Cloud-Anbieter wie Auth0 oder eine Drittanbieter-Komponente wie Spring OAuth 2.0 delegieren, müssen Sie die Dinge höchstwahrscheinlich anders angehen, da Sie wahrscheinlich nur das erhalten, was bereits standardisiert ist.

Eine interessante Referenz

Dieser Artikel erklärt einen anderen Weg, dies zu tun: Blacklist JWT Es enthält einige interessante Praktiken und Muster, gefolgt von RFC7523

João Angelo
quelle
Anstatt einen Hash pro nicht abgelaufenem Token zu speichern (was zwar überschaubar ist, aber möglicherweise viele Hashes enthält), können Sie auch einen Hash pro widerrufenem Token speichern und prüfen, ob er nicht vorhanden ist?
Jonathan Hartley
2
Der Text ist nicht sehr klar, aber ja, ich habe darüber gesprochen, etwas nur für widerrufene By-Value-Token zu speichern und auch nur, bis ihr normaler Ablauf nicht erreicht wurde. Jedes Token wird wie gewohnt validiert und anschließend zusätzlich überprüft, ob es nicht widerrufen wurde.
João Angelo
20

Das JWT kann nicht widerrufen werden.

Aber hier ist eine alternative Lösung, die als JWT alt für neues Austauschschema bezeichnet wird .

Da wir das ausgestellte Token nicht vor Ablauf der Gültigkeitsdauer ungültig machen können, verwenden wir immer ein Kurzzeit-Token, z. B. 30 Minuten. Wenn das Token abgelaufen ist, verwenden wir das alte Token, um ein neues Token auszutauschen. Der kritische Punkt ist eine alte Token ein neues Token austauschen kann nur .

Auf dem Center Auth Server verwalten wir eine Tabelle wie folgt:

table auth_tokens(
    user_id,
    jwt_hash,
    expire
)

Benutzer-ID in JWT-Zeichenfolge enthalten. jwt_hash ist ein Hashwert der gesamten JWT-Zeichenfolge, z. B. SHA256. Das Ablauffeld ist optional.

Folgendes ist der Arbeitsablauf:

  1. Der Benutzer fordert die Anmelde-API mit Benutzername und Kennwort an, der Authentifizierungsserver stellt ein Token aus und registriert das Token (fügen Sie eine Zeile in die Tabelle ein.)
  2. Wenn das Token abgelaufen ist, fordert der Benutzer die Austausch-API mit dem alten Token an. Zuerst überprüft der Authentifizierungsserver das alte Token wie gewohnt mit Ausnahme der Ablaufprüfung, erstellt dann den Token-Hashwert und sucht dann über der Tabelle nach der Benutzer-ID:
    • Wenn der gefundene Datensatz und user_id und jwt_hash übereinstimmen, geben Sie ein neues Token aus und aktualisieren Sie die Tabelle.
    • Wenn der gefundene Datensatz, aber user_id und jwt_hash nicht übereinstimmen, bedeutet dies, dass jemand das zuvor ausgetauschte Token verwendet hat. Das Token wird gehackt, Datensätze von user_id gelöscht und mit Warninformationen beantwortet.
    • Wenn der Datensatz nicht gefunden wird, muss sich der Benutzer erneut anmelden oder nur das Kennwort eingeben.
  3. Wenn Sie das Kennwort geändert oder sich abgemeldet haben, löschen Sie den Datensatz anhand der Benutzer-ID.

Um das Token kontinuierlich zu verwenden, müssen sowohl der legale Benutzer als auch der Hacker kontinuierlich ein neues Token austauschen. Nur eines kann erfolgreich sein. Wenn eines fehlschlägt, müssen sich beide beim nächsten Austausch erneut anmelden.

Wenn der Hacker das Token erhalten hat, kann es für kurze Zeit verwendet werden, kann jedoch nicht gegen ein neues ausgetauscht werden, wenn ein legaler Benutzer das nächste Mal ein neues ausgetauscht hat, da die Gültigkeitsdauer des Tokens kurz ist. Auf diese Weise ist es sicherer.

Wenn es keinen Hacker gibt, muss der normale Benutzer auch regelmäßig neue Token austauschen, z. B. alle 30 Minuten. Dies entspricht einer automatischen Anmeldung. Die zusätzliche Last ist nicht hoch und wir können die Ablaufzeit für unsere Anwendung anpassen.

Quelle: http://www.jianshu.com/p/b11accc40ba7

Huanghq
quelle
1
Der Hauptnachteil dieser Lösung besteht darin, dass gleichzeitig nur ein Benutzer angemeldet sein kann.
Michał Stochmal
Was passiert, wenn der Benutzer das System nicht mehr verwendet und der Hacker gegen ein neues Token eintauscht? Klingt so, als ob der Hacker weiterhin Token verwenden und austauschen kann, bis sich der Benutzer erneut anmeldet. Yuck.
Chris H.
11

Dies beantwortet Ihre Frage in Bezug auf das Spring-Framework nicht genau. In diesem Artikel wird jedoch erläutert, warum Sie, wenn Sie die Möglichkeit benötigen, JWTs zu widerrufen, möglicherweise nicht in erster Linie mit JWTs arbeiten und stattdessen reguläre verwenden möchten. undurchsichtige Inhaber-Token.

https://www.dinochiesa.net/?p=1388

Ian Storm Taylor
quelle
Warum nicht einen Cache oder eine RDBM mit einem Cron verwenden und jeden Eintrag regelmäßig löschen oder so etwas, anstatt zu warten?
user1438644
9

Eine Möglichkeit, eine JWT zu widerrufen, besteht darin, ein verteiltes Ereignissystem zu nutzen, das Dienste benachrichtigt, wenn Aktualisierungstoken widerrufen wurden. Der Identitätsanbieter sendet ein Ereignis, wenn ein Aktualisierungstoken widerrufen wird und andere Backends / Dienste auf das Ereignis warten. Wenn ein Ereignis empfangen wird, aktualisieren die Backends / Services einen lokalen Cache, der eine Gruppe von Benutzern verwaltet, deren Aktualisierungstoken widerrufen wurden.

Dieser Cache wird dann überprüft, wenn eine JWT überprüft wird, um festzustellen, ob die JWT widerrufen werden soll oder nicht. Dies alles basiert auf der Dauer der JWTs und dem Ablaufzeitpunkt der einzelnen JWTs.

Dieser Artikel, JWTs widerrufen , veranschaulicht dieses Konzept und enthält eine Beispiel-App für Github.

kstra
quelle
Dieser Link "JWTs widerrufen" gibt jetzt einen 404 zurück.
DenverCoder9
0

Was ist mit dem Speichern des JWT-Tokens und dem Verweisen auf den Benutzer in der Datenbank? Wenn Sie die Guards / Sicherheitssysteme in Ihrer Backend-Anwendung nach dem JWT-Vergleich um einen zusätzlichen DB-Join erweitern, können Sie sie praktisch "widerrufen", indem Sie sie aus der DB entfernen oder aus der DB löschen.

Codepushr
quelle
Sie müssen das Token wie ein Kennwort behandeln. Anstatt das Token selbst zu speichern, würden Sie einen Hash davon a la bcrypt, scrypt usw. speichern. Sie würden jedoch einen zusätzlichen Token-Validierungsschritt einführen, der eine Zentralisierung und Negation erfordert Eine der Stärken von JWT. Wollen Sie JWT zu diesem Zeitpunkt wirklich? Tatsächlich hat jemand auf den folgenden Artikel verlinkt, der dieselbe Meinung ausführlicher zum Ausdruck bringt: dinochiesa.net/?p=1388
Chris H.
-2

Ich habe eine Möglichkeit gefunden, das Problem zu beheben : Wie kann ein bereits generiertes vorhandenes JWT-Token mit Java verfallen?

In diesem Fall müssen wir eine beliebige Datenbank oder einen In-Memory-Speicher verwenden, in dem

Schritt 1: Sobald das Token zum ersten Mal für einen Benutzer generiert wurde, speichern Sie es in einer Datenbank mit dem Token und es ist " issedAt () ".

Ich habe es in DB in diesem JSON-Format gespeichert.

Beispiel: { "username" : "username", "token" : "token", "issuedAt" : "issuedAt"}

Schritt 2: Wenn Sie eine Webdienstanforderung für denselben Benutzer mit einem zu validierenden Token erhalten, rufen Sie den Zeitstempel " issitedAt () " vom Token ab und vergleichen Sie ihn mit dem gespeicherten (DB / in-memory) ausgegebenen Zeitstempel.

Schritt 3: Wenn der gespeicherte ausgegebene Zeitstempel neu ist (mit der after () / before () -Methode), geben Sie zurück, dass das Token ungültig ist (in diesem Fall läuft das Token nicht ab, aber wir gewähren keinen Zugriff mehr auf dieses Token).

So habe ich das Problem gelöst.

Sindhu Raju
quelle
Dies ist wie das Speichern von Passwörtern in einer Datenbank. Tu das nicht. Sie könnten stattdessen einen Hash a la bcrypt, scrypt usw. speichern, aber der Punkt ist, das Token wie ein Passwort zu behandeln.
Chris H.