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
Antworten:
Ja. Header, Anforderungsparameter und Anforderungshauptteil werden während der Kommunikation verschlüsselt.
Sobald Sie sich auf der Serverseite befinden, protokollieren Sie den Anfragetext nicht :-)
Du kannst nicht. Sobald sich die API im WWW befindet, ist sie automatisch jeder Art von Bosheit ausgesetzt. Das Beste, was Sie tun können, ist, vorbereitet zu sein und sich der Bedrohungen bewusst zu sein. Zumindest über diejenigen, die dich betreffen. Schauen Sie hier .
Ein möglicher Ansatz für das Problem könnte darin bestehen, einen API-Manager zu implementieren (oder zu beauftragen) .
On-Premise-API-Manager können die Angriffsfläche reduzieren, da nicht alle Endpunkte hinter dem AM unbedingt öffentlich sind.
Sie könnten mit einigen Produkten in der Cloud das gleiche Ergebnis erzielen, aber sie sind für den Mainstream absurd teuer.
Auf jeden Fall bleiben die API-Verwaltungsendpunkte Angriffen ausgesetzt.
Wenn Sie mit programmatischen Anmeldungen Angriffe mit brutaler Gewalt meinen, sollten ein Schwellenwert (maximale Anzahl zulässiger Anforderungen pro Sekunde) und eine schwarze Liste ausreichen, um das Bestehen des Angreifers zu verhindern. Weitere Informationen finden Sie hier .
Viele der API-Manager bieten sofort einsatzbereite API-Ratenlimitkonfigurationen und Whitelists .
Wenn Sie mit der Google API-Konsole vertraut sind, können Sie erraten, was ein API-Manager tun kann.
Unabhängig davon, ob es sich bei dem Aktualisierungstoken um eine einfache UUID oder um etwas anderes handelt, möchte ich diese Art von Implementierungsdetails nicht offenlegen. Also würde ich vorschlagen, es zu hashen. Je undurchsichtiger die Implementierungsdetails der Sicherheitsschicht sind, desto besser.
Informationen zur JWT-Sicherheit finden Sie hier .
Möglicherweise interessieren Sie sich für JSON Web Token (JWT) - Speicher auf der Clientseite .
quelle
sessionStorage
sie nicht funktionieren. AuchlocalStorage
unddocument.cookie
scheinen unsicher, da sie über JavaScript zugegriffen werden können. Ist mein Ansatz sinnvoll oder möglicherweise unsicher?document.cookie
ein HttpOnly-Cookie mit einer sicheren Flagge, ähnlich dem oben erwähnten Ansatz?