Behandlung der Token-Erneuerung / des Ablaufs der Sitzung in einer RESTful-API

17

Ich erstelle eine RESTful-API, die JWT-Token für die Benutzerauthentifizierung verwendet (ausgestellt von einem loginEndpunkt und anschließend in allen Headern gesendet). Die Token müssen nach einer festgelegten Zeitspanne aktualisiert werden (Aufrufen eines renewEndpunkts, der ein erneutes Token zurückgibt) ).

Es ist möglich, dass die API-Sitzung eines Benutzers ungültig wird, bevor das Token abläuft. Daher überprüfen alle meine Endpunkte zunächst, ob: 1) das Token noch gültig ist und 2) die Sitzung des Benutzers noch gültig ist. Das Token kann nicht direkt ungültig gemacht werden, da es von den Clients lokal gespeichert wird.

Daher müssen alle meine Endpunkte meinen Kunden zwei mögliche Bedingungen mitteilen: 1) dass es Zeit ist, das Token zu erneuern, oder 2) dass die Sitzung ungültig geworden ist und sie nicht mehr auf das System zugreifen dürfen. Ich kann mir zwei Alternativen für meine Endpunkte vorstellen, um ihren Clients zu signalisieren, wenn eine der beiden Bedingungen eintritt (vorausgesetzt, die Clients können an beide Optionen angepasst werden):

  1. Geben Sie einen http 401-Code (nicht autorisiert) zurück, wenn die Sitzung ungültig geworden ist, oder geben Sie einen 412-Code zurück (Vorbedingung fehlgeschlagen), wenn das Token abgelaufen ist und es Zeit ist, den renewEndpunkt aufzurufen , der einen 200-Code (ok) zurückgibt.
  2. Geben Sie 401 zurück, um zu signalisieren, dass entweder die Sitzung ungültig ist oder das Token abgelaufen ist. In diesem Fall ruft der Client sofort den renewEndpunkt auf. Wenn er 200 zurückgibt, wird das Token aktualisiert. Wenn renewer aber auch 401 zurückgibt, bedeutet dies, dass der Client nicht im System ist.

Welche der beiden oben genannten Alternativen würden Sie empfehlen? Welches wäre standardmäßiger, einfacher zu verstehen und / oder ruhiger? Oder würden Sie einen ganz anderen Ansatz empfehlen? Sehen Sie bei beiden Optionen offensichtliche Probleme oder Sicherheitsrisiken? Zusätzliche Punkte, wenn Ihre Antwort externe Referenzen enthält, die Ihre Meinung stützen.

AKTUALISIEREN

Leute, bitte konzentriert euch auf die eigentliche Frage: Welche der beiden http-Code-Alternativen zur Signalisierung einer Erneuerung / Sitzungsinvalidierung ist die beste? Es macht nichts aus, dass mein System JWT- und serverseitige Sitzungen verwendet. Dies ist eine Besonderheit meiner API für sehr spezifische Geschäftsregeln und nicht für den Teil, für den ich Hilfe suche.

Óscar López
quelle
Wie würde eine Benutzersitzung vor Ablauf des Tokens ungültig werden, wenn eine kurze Ablaufzeit (ca. 5 Minuten) angenommen wird?
Jack
Aufgrund einer Geschäftsregel kann ein anderer Teil des Systems die Sitzung ungültig machen.
Óscar López
1
JWTs dienen dem Identitätsnachweis, wie in "Diese Anforderung stammt nachweislich von Benutzer X". Lautet Ihre Geschäftsregel etwa "Benutzer X darf nicht mehr mit Ressource Y interagieren", sollte dies separat von der JWT überprüft werden .
Jack
@ Jack genau! Das ist genau mein Punkt und der Grund, warum ich eine zusätzliche, statusbehaftete Ebene zum Speichern von Sitzungsinformationen verwenden muss. Plain JWT, so schön es auch sein mag, ist einfach nicht für die Arbeit geeignet.
Óscar López
1
Vielleicht interessiert Sie meine Antwort dann :)
Jack

Antworten:

22

Das klingt wie ein Fall von Authentifizierung gegenüber Genehmigung .

JWTs sind kryptografisch signierte Ansprüche über den Absender einer Anfrage. Ein JWT enthält möglicherweise Ansprüche wie "Diese Anforderung gilt für Benutzer X" und "Benutzer X hat Administratorrollen". Das Erhalten und Bereitstellen dieses Beweises durch Passwörter, Signaturen und TLS ist die Domäne der Authentifizierung - der Beweis, dass Sie der sind, für den Sie sich ausgeben.

Was diese Behauptungen für Ihren Server bedeuten - was bestimmte Benutzer und Rollen tun dürfen - ist das Problem der Autorisierung . Der Unterschied zwischen den beiden kann mit zwei Szenarien beschrieben werden. Angenommen, Bob möchte den Lagerraum seines Unternehmens betreten, muss sich aber zuerst mit einem Wachmann namens Jim auseinandersetzen.

Szenario A - Authentifizierung

  • Bob: Hallo Jim, ich möchte einen eingeschränkten Speicherplatz betreten.
  • Jim: Hast du dein Abzeichen?
  • Bob: Nein, ich habe es vergessen.
  • Jim: Entschuldigung Kumpel, kein Eintritt ohne Abzeichen.

Szenario B - Autorisierung

  • Bob: Hallo Jim, ich möchte den eingeschränkten Speicherplatz betreten. Hier ist mein Abzeichen.
  • Jim: Hey Bob, du brauchst Level 2 Freischaltung, um hier einzutreten. Entschuldigung.

JWT-Ablaufzeiten sind ein Authentifizierungsgerät, das andere daran hindert, sie zu stehlen. Wenn alle Ihre JWTs eine Ablaufzeit von fünf Minuten haben, ist es bei weitem nicht so schlimm, wenn sie gestohlen werden, weil sie schnell unbrauchbar werden. Die besprochene "Sitzungsablauf" -Regel hört sich jedoch wie ein Autorisierungsproblem an. Eine Änderung des Status bedeutet, dass Benutzer X nicht mehr berechtigt ist, etwas zu tun, wozu er früher in der Lage war. Zum Beispiel könnte Benutzer Bob entlassen worden sein - es spielt keine Rolle, dass sein Abzeichen angibt, dass er Bob ist, weil ihm das bloße Sein von Bob keine Autorität mehr für das Unternehmen verleiht.

Diese beiden Fälle haben unterschiedliche HTTP-Antwortcodes: 401 Unauthorizedund 403 Forbidden. Der unglücklicherweise als 401 bezeichnete Code ist für Authentifizierungsprobleme wie fehlende, abgelaufene oder widerrufene Anmeldeinformationen vorgesehen. 403 ist für die Autorisierung vorgesehen, bei der der Server genau weiß, wer Sie sind, aber Sie dürfen nur nicht das tun, was Sie versuchen. Wenn ein Benutzerkonto gelöscht wird, führt der Versuch, an einem Endpunkt etwas mit einem JWT zu tun, zu einer verbotenen Antwort. Wenn das JWT jedoch abgelaufen ist, ist das korrekte Ergebnis 401 Unauthorized.

Ein übliches JWT-Muster besteht darin, "langlebige" und "kurzlebige" Token zu haben. Langlebige Token werden wie kurzlebige Token auf dem Client gespeichert, sind jedoch in ihrem Umfang begrenzt und werden nur mit Ihrem Autorisierungssystem verwendet, um kurzlebige Token zu erhalten. Wie der Name schon sagt, haben langlebige Token sehr lange Verfallszeiten - Sie können sie verwenden, um tagelang oder wochenlang neue Token anzufordern. Kurzlebige Token sind die von Ihnen beschriebenen Token, die mit sehr kurzen Ablaufzeiten für die Interaktion mit Ihrem System verwendet werden. Langlebige Token sind nützlich, um die Funktion "Angemeldet bleiben" zu implementieren. Sie müssen also nicht alle fünf Minuten Ihr Kennwort eingeben, um ein neues kurzlebiges Token zu erhalten.

Das von Ihnen beschriebene Problem der "Sitzungsinvalidierung" klingt ähnlich wie der Versuch, eine langlebige JWT für ungültig zu erklären, da kurzlebige selten serverseitig gespeichert werden, während langlebige für den Fall, dass sie widerrufen werden müssen, nachverfolgt werden. In einem solchen System würde der Versuch, Anmeldeinformationen mit einem widerrufenen, langlebigen Token abzurufen, zu 401 Unauthorized führen, da der Benutzer möglicherweise technisch in der Lage ist, Anmeldeinformationen abzurufen, das von ihm verwendete Token jedoch nicht für die Aufgabe geeignet ist. Wenn der Benutzer dann versucht, ein neues, langlebiges Token unter Verwendung seines Benutzernamens und seines Kennworts zu erhalten, kann das System mit 403 Forbidden antworten, wenn er aus dem System geworfen wird.

Jack
quelle
3
Dies ist die Anleitung, nach der ich gesucht habe, und Sie haben einen sehr relevanten Einblick in die Diskussion gebracht - dass es sich um einen Fall von Authentifizierung oder Autorisierung handelt und jeder Fall anders gehandhabt werden sollte. Vielen Dank!
Óscar López
16

Ihre API-Sitzung sollte in einer RESTful-Welt überhaupt nicht existieren. RESTful-Operationen sollen zustandslos sein, Session enthält State und hat somit keinen Platz in einer RESTful-Welt.

Das JWT sollte Ihre einzige Möglichkeit sein, um zu bestimmen, ob ein Benutzer noch zum Zugriff auf einen Endpunkt berechtigt ist oder nicht. Eine Sitzung sollte dabei absolut keine Rolle spielen. In diesem Fall verfügen Sie nicht über eine RESTful-API.

Wenn Sie die Sitzung vollständig entfernen, was Sie tun sollten, wenn Sie eine RESTful-API anstreben, und nur das JWT als Authentifizierungsfaktor verwenden, ist ein Benutzer entweder berechtigt, Ihren Endpunkt zu verwenden, oder nicht. In diesem Fall ist der 401 UnauthorizedAntwortcode angemessen - und sollte den renewEndpunkt mit grant_type=refresh_tokenoder ohne Angabe der von Ihnen verwendeten Erneuerungskennung anrufen .

Aktualisieren:

Aus dem Kommentar geht hervor, dass der Validierungsfluss des aktuell verwendeten JWT nicht korrekt ist. Die Validierung soll so aussehen:

  Client        RESTful API      JWT Issuer
     |              |                |
     |----- 1. ---->|                | 
     |              |------ 2. ----->|-----
     |              |                | 3. |
     |              |<----- 4. ------|<----
-----|<---- 5. -----|                |
| 6. |              |                |
---->|----- 7. ---->|                |
     |              |------ 8. ----->|-----
     |              |                | 9. |
     |              |<----- 10. -----|<----
     |              |                |
     |              |------          |
     |              | 11. |          |
     |<---- 12. ----|<-----          |
     |              |                |
     .              .                .

1. Ask RESTful API for a JWT using login endpoint.
2. Ask Issuer to create a new JWT.
3. Create JWT.
4. Return JWT to the RESTful API.
5. Return JWT to Client.
6. Store JWT to append it to all future API requests.
7. Ask for data from API providing JWT as authorization.
8. Send JWT to Issuer for verification.
9. Issuer verifies JWT.
10. Issuer returns 200 OK, verification successful.
11. Retrieve and format data for Client.
12. Return data to Client.

Der Server RESTful APImuss die Gültigkeit des Tokens prüfen, das als Autorisierung gesendet wird. Das liegt nicht in der Verantwortung der Client. Es scheint, als ob Sie dies derzeit nicht tun. Implementieren Sie die Überprüfung des JWT auf diese Weise, und Sie benötigen überhaupt keine Sitzungen.

Andy
quelle
Danke für deine Antwort. Einverstanden wäre die Verwendung einer Sitzung kein 100% -REST-Ansatz, aber wie oben erwähnt, muss ich einigen Benutzern den Zugriff verweigern, bevor das Token abläuft.
Óscar López
2
@ ÓscarLópez Dann machen Sie einfach die Tokens ungültig, die die Benutzer verwenden. Sie können mit dem bereitgestellten Token (das jetzt ungültig ist) nicht mehr auf die API zugreifen, und Sie benötigen keine Sitzung.
Andy
1
Die Token werden auf dem Client gespeichert. Wie kann ich sie dort ungültig machen? Ich müsste nachverfolgen, welche davon gültig sind ... und hier erhebt der Staat seinen hässlichen Kopf. Manchmal ist es unvermeidlich.
Óscar López
Ein böswilliger Client könnte ein zuvor gültiges Token so lange senden, wie es die Ablaufzeit zulässt, aber ich muss ihn sofort aus dem System werfen - daher ist das Festlegen einer kurzen Erneuerungszeit ebenfalls keine Option.
Óscar López
4
@Laiv Ich habe das Sequenzdiagramm im Editor erstellt.
Andy
1

Ich gebe also zu, dass es für mich wenig sinnvoll ist, mir Sorgen darüber zu machen, welcher Ansatz am REST-fähigsten ist, wenn Sie bereits REST-Konventionen mit der Sitzung brechen, aber ich verstehe, dass Sie Ihre geschäftlichen Anforderungen erfüllen.

Aus REST-Sicht ist der Client entweder authentifiziert oder nicht. Der Architektur ist es egal, warum (das führt zu einem unnötigen Zustand). Um Ihre Hauptfrage zu beantworten, hätte ich überhaupt keinen Endpunkt für die Erneuerung. Ein angemeldeter Client sendet nur immer sein JWT und der Server validiert es immer und akzeptiert es entweder durch Senden des entsprechenden Erfolgscodes auf der Grundlage der Aktion 200, 201 usw.) oder lehnt es mit einem 401 oder 403 ab, je nachdem, wie dies erforderlich ist.

Jetzt wird das JWT mit einem Account in Verbindung gebracht. Dieses Konto ist möglicherweise gesperrt oder gedrosselt oder was auch immer. Das Token selbst ist möglicherweise gültig, die Aktion wird jedoch an anderer Stelle abgelehnt. Wenn der Fall ist, dass das Benutzerkonto aufgrund von Geschäftsregeln gesperrt ist, dann ist es immer noch ein 401 oder 403, je nachdem, wie viele Informationen Sie dem Kunden geben möchten (verschiedene Unternehmen haben unterschiedliche Meinungen dazu).

Wenn Sie schließlich behaupten, dass das Konto möglicherweise entsperrt und gültig ist, die JWT jedoch nur widerrufen werden muss, würde ich mich NOCH immer an die 401 oder 403 halten und so etwas wie eine Zertifikatswiderrufsliste ungültiger JWTs pflegen, in die Sie eine einfügen können , solange es sich selbst bereinigt, wenn das JWT abgelaufen wäre (die meisten Datenbanken haben eine Möglichkeit, dies zu tun, oder Sie können Ereignisse im App-Code haben).

Paul
quelle
jwt sollen staatenlos sein. In dem Moment, in dem Sie den Inhalt hinterfragen und ihn gegen eine Datenbank validieren, ist er nicht mehr zustandslos. Dadurch wird er überflüssig, da es bessere Lösungen für Statefull-Sitzungen gibt
Stavm,