Ich implementiere ein tokenbasiertes Authentifizierungssystem für eine REST-API unter Verwendung eines kurzlebigen Zugriffstokens und eines langlebigen Aktualisierungstokens. Dies ist eine abstrakte Übersicht über die relevanten API-Endpunkte (HTTPS wird für alle Endpunkte erzwungen):
Endpunkte:
POST /register/
POST /login/
POST /logout/
POST /password/change/
Implementierung:
POST /register/
::
- Anfrage: Der Client sendet Benutzernamen, E-Mail und Passwort in JSON.
- Serveraktionen:
- Überprüft die Eingabe, erstellt einen Benutzer in der Datenbank (speichert Benutzer-ID, Benutzername, E-Mail und Kennwort-Hash).
- Erstellt ein kurzlebiges Zugriffstoken im JWT-Format (enthält Benutzer-ID, Ausstellungsdatum und Ablaufdatum).
- Erstellt ein langlebiges Aktualisierungstoken als UUID-Zeichenfolge und speichert es in der Datenbank (speichert die Benutzer-ID und das Aktualisierungstoken).
- Antwort: Der Server gibt das Zugriffstoken und das Aktualisierungstoken in JSON zurück.
POST /login/
::
- Anfrage: Client sendet Benutzername und Passwort in JSON.
- Serveraktionen:
- Überprüft die Eingabe und prüft, ob die Anmeldeinformationen gültig sind, indem die Datenbank überprüft wird.
- Wenn Anmeldeinformationen gültig sind, werden wie zuvor erwähnt kurzlebige Zugriffstoken und langlebige Aktualisierungstoken erstellt.
- Antwort: Entspricht dem
/register/
Zugriffstoken und dem Aktualisierungstoken in JSON.
POST /logout/
::
- Anforderung: Der Client sendet ein Aktualisierungstoken im
Authorization
Header alsBearer
Token. - Serveraktionen:
- Überprüft das Aktualisierungstoken durch Überprüfen der Aktualisierungstoken-Datenbank.
- Entfernt das Aktualisierungstoken aus der Datenbank.
Hinweis: Dadurch bleibt das Zugriffstoken gültig, aber da es nur von kurzer Dauer ist (ca. 1 Stunde, denke ich, sollte es in Ordnung sein).
- Antwort: Gibt zurück, ob die Abmeldeanforderung in JSON erfolgreich verarbeitet wurde.
POST /password/change/
::
- Anforderung: Der Client sendet das Zugriffstoken im
Authorization
Header alsBearer
Token und sendet außerdem das alte und das neue Kennwort in JSON über HTTPS. - Serveraktionen:
- Dekodiert das Zugriffstoken, um den Benutzer abzurufen, und überprüft das alte Kennwort des Benutzers mit der Datenbank.
- Setzt den Kennwort-Hash des Benutzers in der Datenbank auf den Hash des neuen Kennworts.
- Entfernt alle Aktualisierungstoken, die dem Benutzer in der Aktualisierungstoken-Datenbank zugeordnet sind, um vorhandene Sitzungen im Wesentlichen abzumelden (kurzlebige Zugriffstoken bleiben gültig).
- Antwort: Gibt zurück, ob die Kennwortänderungsanforderung in JSON erfolgreich verarbeitet wurde.
Fragen:
- Ist dieser Ansatz sicher? Speziell:
- Ist das Senden des Benutzernamens und des Kennworts über JSON sicher, wenn dies über HTTPS erfolgt? Wie kann ich verhindern, dass nicht autorisierte Domänen diesen Endpunkt anrufen? Wie würde ich außerdem programmatische Anmeldungen verhindern?
- Sollten die Aktualisierungstoken gehasht werden, bevor sie in der Datenbank gespeichert werden, oder bin ich nur paranoid?
- Wenn der Client ein Webbrowser wäre, wie würde ich das Aktualisierungstoken sicher auf dem Client speichern?
- Eine Idee zum Speichern des Aktualisierungstokens ist: Wenn sich der Benutzer anmeldet, speichert der Server das Token zusätzlich zum Senden des Aktualisierungstokens an den Client in einem
HttpOnly
Cookie mit einemsecure
Flag. Die Autorisierung erfolgt weiterhin über denAuthorization
Header. Wenn der Client jedoch zum ersten Mal geladen wird, kann er eineGET
Anforderung an einen Endpunkt senden , der prüft, ob das Cookie ein gültiges Aktualisierungstoken enthält, und es in diesem Fall an den Benutzer in JSON zurückgeben. Mit anderen Worten, das einzige Mal, dass das Cookie tatsächlich verwendet wird, besteht darin, das Aktualisierungstoken im Cookie an den Client zurückzugeben. Ist dieser Ansatz sicher? Ich denke, es wird CSRF verhindern, da es keine Nebenwirkungen gibt, wenn das Aktualisierungstoken vom Cookie angefordert wird. Aber gibt es eine andere Möglichkeit, wie ein Angreifer das Aktualisierungstoken abfangen könnte (unter der Annahme von HTTPS)?
- Eine Idee zum Speichern des Aktualisierungstokens ist: Wenn sich der Benutzer anmeldet, speichert der Server das Token zusätzlich zum Senden des Aktualisierungstokens an den Client in einem