wake-up-neo.com

RESTful Passwort zurücksetzen

Wie kann eine RESTful-Ressource zum Zurücksetzen eines Kennworts richtig strukturiert werden?

Diese Ressource soll ein Passwort-Resetter für jemanden sein, der sein Passwort verloren oder vergessen hat. Das alte Passwort wird ungültig und es wird ein Passwort per E-Mail an sie gesendet.

Die zwei Optionen, die ich habe, sind:

POST /reset_password/{user_name}

oder...

POST /reset_password
   -Username passed through request body

Ich bin mir ziemlich sicher, dass die Anfrage ein POST sein sollte. Ich bin weniger sicher, dass ich einen passenden Namen ausgewählt habe. Ich bin mir nicht sicher, ob der Benutzername durch die URL oder den Anfragetext geleitet werden soll.

83
Chris Dutrow

UPDATE: (weiter unten kommentiert)

Ich würde so etwas machen:

POST /users/:user_id/reset_password

Sie haben eine Sammlung von Benutzern, bei denen der einzelne Benutzer durch {user_name} angegeben wird. Sie geben dann die Aktion an, für die die Aktion ausgeführt werden soll, in diesem Fall reset_password. Es ist, als würde man sagen "Erzeuge (POST) eine neue reset_password-Aktion für {user_name}".


Vorherige Antwort:

Ich würde so etwas machen:

PUT /users/:user_id/attributes/password
    -- The "current password" and the "new password" passed through the body

Sie hätten zwei Sammlungen, eine Benutzersammlung und eine Attributsammlung für jeden Benutzer. Der Benutzer wird durch :user_id und das Attribut durch password angegeben. Die Operation PUT aktualisiert das angesprochene Mitglied der Sammlung.

47
Daniel Vassallo

Nicht authentifizierte Benutzer

Wir machen eine PUT Anfrage für eine api/v1/account/password Endpunkt und benötigen einen Parameter mit der entsprechenden Konto-E-Mail, um das Konto zu identifizieren, für das der Benutzer das Kennwort zurücksetzen (aktualisieren) möchte:

PUT : /api/v1/account/password?email={[email protected]}

Hinweis: Wie @ DougDomeny in seinem Kommentar erwähnt vorbei Die E-Mail als Abfragezeichenfolge in der URL ist ein Sicherheitsrisiko. GET-Parameter werden bei der Verwendung von https nicht verfügbar gemacht (und Sie sollten für solche Anforderungen immer eine ordnungsgemäße https -Verbindung verwenden), es bestehen jedoch andere Sicherheitsrisiken. Weitere Informationen zu diesem Thema finden Sie in dieser Blog-Beitrag hier .

Das Übergeben der E-Mail im Anforderungshauptteil ist eine sicherere Alternative zum Übergeben als GET-Parameter:

PUT : /api/v1/account/password

Körper anfordern:

{
    "email": "[email protected]"
}

Die Antwort hat ein 202 akzeptiert Antwortbedeutung:

Die Anforderung wurde zur Verarbeitung angenommen, die Verarbeitung wurde jedoch nicht abgeschlossen. Die Anforderung kann möglicherweise bearbeitet werden oder auch nicht, da sie möglicherweise nicht zugelassen wird, wenn die Verarbeitung tatsächlich stattfindet. Es gibt keine Möglichkeit, einen Statuscode aus einer solchen asynchronen Operation erneut zu senden.

Der Benutzer erhält eine E-Mail an [email protected] und die Verarbeitung der Aktualisierungsanforderung hängen von den Aktionen ab, die mit dem Link aus der E-Mail ausgeführt wurden.

https://example.com/password-reset?token=1234567890

Das Öffnen des Links aus dieser E-Mail führt zu einem Formular zum Zurücksetzen des Passworts in der Front-End-Anwendung, in dem das Token zum Zurücksetzen des Passworts als Eingabe für ein ausgeblendetes Eingabefeld verwendet wird (das Token ist Teil des Links als Abfragezeichenfolge). Über ein weiteres Eingabefeld kann der Benutzer ein neues Passwort festlegen. Eine zweite Eingabe zur Bestätigung des neuen Passworts wird für die Validierung im Front-End verwendet (um Tippfehler zu vermeiden).

Hinweis: In der E-Mail können wir auch erwähnen, dass der Benutzer die E-Mail ignorieren kann, falls er kein Passwort zurückgesetzt hat und benutze die Anwendung normal mit seinem/ihrem aktuellen Passwort

Wenn das Formular mit dem neuen Kennwort und dem Token als Eingabe gesendet wird, wird der Vorgang zum Zurücksetzen des Kennworts ausgeführt. Die Formulardaten werden erneut mit der Anforderung PUT gesendet, diesmal jedoch einschließlich des Tokens, und das Ressourcenpasswort wird durch einen neuen Wert ersetzt:

PUT : /api/v1/account/password

Körper anfordern:

{
    "token":"1234567890",
    "new":"password"
}

Die Antwort wird ein 204 kein Inhalt Antwort

Der Server hat die Anforderung erfüllt, muss jedoch keinen Entity-Body zurückgeben und möchte möglicherweise aktualisierte Metainformationen zurückgeben. Die Antwort kann neue oder aktualisierte Metainformationen in Form von Entity-Headern enthalten, die, falls vorhanden, der angeforderten Variante zugeordnet werden MÜSSEN.

Authentifizierte Benutzer

Für authentifizierte Benutzer, die ihr Kennwort ändern möchten, kann die Anforderung PUT sofort ohne die E-Mail ausgeführt werden (das Konto, für das wir das Kennwort aktualisieren, ist dem Server bekannt). In diesem Fall enthält das Formular zwei Felder:

PUT : /api/v1/account/password

Körper anfordern:

{
    "old":"password",
    "new":"password"
}
59
Wilt

Lassen Sie uns für eine Sekunde überruhig werden. Warum nicht die DELETE-Aktion für das Passwort verwenden, um einen Reset auszulösen? Sinnvoll, nicht wahr? Schließlich verwerfen Sie das vorhandene Passwort zugunsten eines anderen.

Das bedeutet, dass Sie Folgendes tun würden:

DELETE /users/{user_name}/password

Nun zwei große Einschränkungen:

  1. HTTP DELETE soll idempotent sein (ein schickes Wort für "keine große Sache, wenn Sie es mehrmals tun"). Wenn Sie Standardaufgaben wie das Versenden einer E-Mail zum Zurücksetzen des Kennworts ausführen, treten Probleme auf. Sie können dieses Problem umgehen, indem Sie den Benutzer/das Kennwort mit einem booleschen "Is Reset" -Flag kennzeichnen. Bei jedem Löschen markieren Sie dieses Kennzeichen. Wenn es nicht gesetzt ist , können Sie das Passwort zurücksetzen und Ihre E-Mail senden. (Beachten Sie, dass dieses Flag möglicherweise auch für andere Zwecke verwendet wird.)

  2. Sie können HTTP DELETE nicht über ein Formular verwenden , daher müssen Sie AJAX aufrufen und/oder DELETE über den POST tunneln.

16
Craig Walker

Häufig möchten Sie das vorhandene Kennwort des Benutzers bei der ursprünglichen Anfrage nicht löschen oder löschen, da dieses (unbeabsichtigt oder absichtlich) von einem Benutzer ausgelöst wurde, der keinen Zugriff auf die E-Mail hat. Aktualisieren Sie stattdessen ein Reset-Kennwort-Token für den Benutzerdatensatz, und senden Sie es in einem in einer E-Mail enthaltenen Link. Durch Klicken auf den Link wird bestätigt, dass der Benutzer das Token erhalten hat und sein Kennwort aktualisieren möchte. Im Idealfall wäre dies auch zeitempfindlich.

Die RESTful-Aktion wäre in diesem Fall ein POST: Auslösen der Erstellungsaktion auf dem PasswordResets-Controller. Die Aktion selbst würde das Token aktualisieren und eine E-Mail senden.

11
Mark Swardstrom

Ich suche eigentlich nach einer Antwort, die nicht die Bereitstellung einer Antwort bedeutet - aber "reset_password" klingt für mich in einem REST -Kontext falsch, weil es ein Verb und kein Substantiv ist. Selbst wenn Sie sagen, dass Sie ein Substantiv "Reset-Aktion" ausführen - bei Verwendung dieser Ausrichtung sind alle Verben Substantive.

Möglicherweise ist es auch nicht aufgefallen, dass jemand nach der gleichen Antwort sucht, dass Sie den Benutzernamen möglicherweise über den Sicherheitskontext abrufen und ihn nicht über die URL oder den Körper senden müssen, was mich nervös macht.

8
orbfish

Ich denke, eine bessere Idee wäre:

DELETE /api/v1/account/password    - To reset the current password (in case user forget the password)
POST   /api/v1/account/password    - To create new password (if user has reset the password)
PUT    /api/v1/account/{userId}/password    - To update the password (if user knows is old password and new password)

Zur Bereitstellung der Daten:

  • Um das aktuelle Passwort zurückzusetzen

    • e-Mail sollte in der Nachricht angegeben werden.
  • So erstellen Sie ein neues Passwort (nach dem Zurücksetzen)  

    • das neue Passwort, der Aktivierungscode und die E-Mail-ID sollten in der Nachricht angegeben werden.
  • So aktualisieren Sie das Passwort (für den eingeloggten Benutzer)  

    • altes Passwort, neues Passwort sollte im Body erwähnt werden. 
    • UserId in Params. 
    • Auth Token in den Kopfzeilen.
5
codesnooker

Es sind einige Überlegungen zu beachten:

Das Zurücksetzen von Kennwörtern ist nicht idempotent

Eine Kennwortänderung wirkt sich auf die Daten aus, die als Anmeldeinformationen verwendet werden. Dies führt dazu, dass zukünftige Versuche ungültig werden, wenn die Anforderung einfach wörtlich wiederholt wird, während sich die gespeicherten Anmeldeinformationen geändert haben. Wenn zum Beispiel ein temporäres Reset-Token verwendet wird, um die Änderung zuzulassen, wie es bei einem vergessenen Passwort üblich ist, sollte dieses Token bei erfolgreicher Passwortänderung abgelaufen sein, wodurch weitere Versuche zur Replizierung der Anforderung wieder zunichte gemacht werden. Daher scheint ein RESTful-Ansatz für eine Kennwortänderung ein Job zu sein, der für POST besser geeignet ist als für PUT.

URLs mit ID-Platzhaltern sind nicht RESTful

Eine Ressource, die als /password-reset/{user_id} angegeben ist, impliziert, dass die tatsächliche URL, die auf die Ressource verweist, mit Out-of-Band-Informationen erstellt werden muss (d. H. Wir müssen über Vorwissen von user_id verfügen) und nicht durch Erkennung ermittelt werden. Außerdem wird davon ausgegangen, dass wir zum Zeitpunkt der Anfrage auf diese Informationen zugreifen können, was in vielen Situationen nicht der Fall ist.

ID oder E-Mail in der Datenlast ist wahrscheinlich redundant

Obwohl dies nicht gegen REST ist und möglicherweise einen speziellen Zweck erfüllt, ist es häufig nicht erforderlich, eine ID oder E-Mail-Adresse für das Zurücksetzen des Kennworts anzugeben. Denken Sie darüber nach, warum sollten Sie die E-Mail-Adresse einer Anfrage als Teil der Daten angeben, die auf die eine oder andere Weise die Authentifizierung durchlaufen soll? Wenn der Benutzer lediglich sein Passwort ändert, muss er sich dazu authentifizieren (über Benutzername: Passwort, E-Mail: Passwort oder Zugriffstoken, das über Header bereitgestellt wird). Daher haben wir von diesem Schritt aus Zugriff auf ihr Konto. Wenn sie ihr Passwort vergessen hätten, wäre ihnen ein temporäres Reset-Token (per E-Mail) zur Verfügung gestellt worden, das sie speziell als Anmeldeinformationen für die Änderung verwenden können. In diesem Fall sollte die Authentifizierung über Token ausreichen, um ihren Account zu identifizieren.

Wenn Sie all das in Betracht ziehen, ist hier das, was ich als das richtige Schema für eine RESTful-Passwortänderung halte:

Benutzer kennt ihr Passwort:

Method: POST
url: /v1/account/password
Auth (via headers): [email protected]:my 0ld pa55Word
data load: {"password": "This 1s My very New Passw0rd"}

Der Benutzer kennt sein Passwort nicht (Passwort wird per E-Mail zurückgesetzt):

Method: POST
url: /v1/account/password
Access Token (via headers): pwd_rst_token_b3xSw4hR8nKWE1d4iE2s7JawT8bCMsT1EvUQ94aI
data load: {"password": "This 1s My very New Passw0rd"}
3
Michael Ekoka

Ich hätte nicht etwas, das das Passwort ändert und ein neues sendet, wenn Sie sich für die Methode/users/{id}/password entscheiden und an Ihrer Vorstellung festhalten, dass die Anforderung eine eigene Ressource ist. dh/user-password-request/ist die Ressource und ist PUT, die Benutzerinformationen sollten sich im Hauptteil befinden .. __ Ich würde das Passwort jedoch nicht ändern Seite, die eine request_guid enthält, die zusammen mit einer Anfrage an POST/user/{id}/password /? request_guid = xxxxx übergeben werden kann

Das würde das Passwort ändern, und es lässt nicht zu, dass jemand einen Benutzer mit einer Passwortänderung anstößt.

Außerdem könnte der anfängliche PUT fehlschlagen, wenn eine ausstehende Anforderung vorliegt.

2
bpeikes

Wir aktualisieren das protokollierte Benutzerkennwort PUT/v1/users/password - Identifizieren Sie die Benutzer-ID mithilfe von AccessToken.

Es ist nicht sicher, die Benutzer-ID auszutauschen. Die Restful-API muss den Benutzer anhand des im HTTP-Header empfangenen AccessToken identifizieren.

Beispiel im Springboot

@putMapping(value="/v1/users/password")
public ResponseEntity<String> updatePassword(@RequestHeader(value="Authorization") String token){
/* find User Using token */
/* Update Password*?
/* Return 200 */
}
0
Dan