RESTful wachtwoord reset

Wat is de juiste manier om een ​​REST-bron te structureren voor het opnieuw instellen van een wachtwoord?

Deze bron is bedoeld als wachtwoordhersteller voor iemand die zijn wachtwoord is kwijtgeraakt of vergeten. Het maakt hun oude wachtwoord ongeldig en e-mailt hen een wachtwoord.

De twee opties die ik heb zijn:

POST /reset_password/{user_name}

of…

POST /reset_password
   -Username passed through request body

Ik ben er vrij zeker van dat het verzoek een POST moet zijn. Ik ben er minder zeker van dat ik een toepasselijke naam heb gekozen. En ik weet niet zeker of de gebruikersnaam moet worden doorgegeven via de URL of de hoofdtekst van het verzoek.


Antwoord 1, autoriteit 100%

Niet-geverifieerde gebruikers

We doen een PUT-verzoek op een api/v1/account/password-eindpunt en vereisen een parameter met het bijbehorende account-e-mailadres om het account te identificeren waarvoor de gebruiker wil om het wachtwoord opnieuw in te stellen (bij te werken):

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

Opmerking:Zoals @DougDomenyvermeldde in zijn commentaar, is het doorgeven van de e-mail als een querystring in de url een veiligheidsrisico. GET-parameters worden niet weergegeven bij het gebruik van https(en u moet altijd een juiste https-verbinding gebruiken voor dergelijke verzoeken), maar er zijn andere beveiligingsrisico’s. U kunt meer over dit onderwerp lezen in deze blogpost hier.

Het doorgeven van de e-mail in de hoofdtekst van het verzoek zou een veiliger alternatief zijn voor het doorgeven als een GET-parameter:

PUT : /api/v1/account/password

Verzoektekst:

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

Het antwoord heeft een 202geaccepteerd reactie betekenis:

Het verzoek is geaccepteerd voor verwerking, maar de verwerking is niet voltooid. Het verzoek kan uiteindelijk wel of niet worden ingewilligd, omdat het kan worden afgewezen wanneer de verwerking daadwerkelijk plaatsvindt. Er is geen mogelijkheid voor het opnieuw verzenden van een statuscode van een asynchrone bewerking zoals deze.

De gebruiker ontvangt een e-mail op [email protected]en het verwerken van het updateverzoek is afhankelijk van de acties die worden ondernomen met de link uit de e-mail.

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

Het openen van de link uit deze e-mail leidt naar een formulier voor het opnieuw instellen van het wachtwoord in de front-end-applicatie die het wachtwoord voor het opnieuw instellen van de link gebruikt als invoer voor een verborgen invoerveld (het token maakt deel uit van de link als een queryreeks) . Een ander invoerveld stelt de gebruiker in staat een nieuw wachtwoord in te stellen. Een tweede invoer om het nieuwe wachtwoord te bevestigen wordt gebruikt voor validatie aan de front-end (om typefouten te voorkomen).

Opmerking:In de e-mail kunnen we ook vermelden dat als de gebruiker geen wachtwoordreset heeft geïnitialiseerd, hij/zij de e-mail kan negeren en de applicatie normaal kan blijven gebruiken met zijn/ haar huidige wachtwoord

Wanneer het formulier wordt verzonden met het nieuwe wachtwoord en het token als invoer, zal het proces voor het opnieuw instellen van het wachtwoord plaatsvinden. De formuliergegevens worden opnieuw verzonden met een PUT-verzoek, maar deze keer inclusief het token en we zullen het resourcewachtwoord vervangen door een nieuwe waarde:

PUT : /api/v1/account/password

Verzoektekst:

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

Het antwoord is een 204geen inhoudreactie

De server heeft aan het verzoek voldaan, maar hoeft geen entiteit-body te retourneren en wil mogelijk bijgewerkte meta-informatie retourneren. Het antwoord KAN nieuwe of bijgewerkte meta-informatie bevatten in de vorm van entiteit-headers, die, indien aanwezig, MOETEN worden geassocieerd met de gevraagde variant.

Geverifieerde gebruikers

Voor geverifieerde gebruikers die hun wachtwoord willen wijzigen, kan het PUT-verzoek onmiddellijk worden uitgevoerd zonder de e-mail (het account waarvoor we het wachtwoord bijwerken is bekend bij de server). In dat geval zal het formulier twee velden bevatten:

PUT : /api/v1/account/password

Verzoektekst:

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

Antwoord 2, autoriteit 54%

UPDATE:(verder hieronder commentaar)

Ik zou voor zoiets gaan:

POST /users/:user_id/reset_password

Je hebt een verzameling gebruikers, waarbij de enkele gebruiker wordt gespecificeerd door de {user_name}. Je zou dan de actie specificeren om op te werken, wat in dit geval reset_passwordis. Het is alsof je zegt “Maak (POST) een nieuwe actie reset_passwordvoor {user_name}“.


Vorige antwoord:

Ik zou voor zoiets gaan:

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

Je zou twee collecties hebben, een gebruikerscollectie en een attributencollectie voor elke gebruiker. De gebruiker wordt gespecificeerd door de :user_iden het attribuut wordt gespecificeerd door password. De bewerking PUTwerkt het geadresseerde lid van de verzameling bij.


Antwoord 3, autoriteit 18%

Laten we even über-RESTful worden. Waarom gebruik je de DELETE-actie voor het wachtwoord niet om een ​​reset te activeren? Logisch, nietwaar? U gooit immers in feite het bestaande wachtwoord weg ten gunste van een ander.

Dat betekent dat je het volgende zou doen:

DELETE /users/{user_name}/password

Nou, twee grote waarschuwingen:

  1. HTTP DELETE wordt verondersteld idempotent te zijn(een mooi woord voor “geen probleem als je het meerdere keren doet”). Als je de standaard dingen doet, zoals het verzenden van een “Wachtwoord Reset” e-mail, dan zul je in de problemen komen. U kunt dit omzeilen door de gebruiker/het wachtwoord te taggen met een booleaanse vlag “Is Reset”. Bij elke verwijdering vink je deze vlag aan; als het niet danis ingesteld, kunt u het wachtwoord opnieuw instellen en uw e-mail verzenden. (Merk op dat het hebben van deze vlag ook andere toepassingen kan hebben.)

  2. U kunt gebruik HTTP DELETE niet via een formulier, dus je moet een AJAX-aanroep doen en/of de DELETE tunnelen via de POST.


Antwoord 4, autoriteit 10%

Vaak wilt u het bestaande wachtwoord van de gebruiker niet verwijderen of vernietigen op het eerste verzoek, omdat dit (onbedoeld of opzettelijk) geactiveerd kan zijn door een gebruiker die geen toegang heeft tot de e-mail. Werk in plaats daarvan een reset-wachtwoordtoken bij in de gebruikersrecord en stuur die in een link in een e-mail. Als u op de link klikt, bevestigt u dat de gebruiker de token heeft ontvangen en zijn wachtwoord wil bijwerken. Idealiter zou dit ook tijdgevoelig zijn.

De REST-actie zou in dit geval een POST zijn: het activeren van de actie Create op de PasswordResets-controller. De actie zelf zou het token bijwerken en een e-mail sturen.


Antwoord 5, autoriteit 10%

Ik ben eigenlijk op zoek naar een antwoord, niet de bedoeling om er een te geven – maar “reset_password” klinkt mij verkeerd in een REST-context omdat het een werkwoord is, geen zelfstandig naamwoord. Zelfs als je zegt dat je een ‘reset action’-zelfstandig naamwoord uitvoert – met deze rechtvaardiging zijn alle werkwoorden zelfstandige naamwoorden.

Ook is het misschien niet bij iemand opgekomen die op zoek is naar hetzelfde antwoord dat je de gebruikersnaam misschien via de beveiligingscontext kunt krijgen en het helemaal niet via de url of de body hoeft te verzenden, wat me nerveus maakt .


Antwoord 6, autoriteit 7%

Ik denk dat een beter idee zou zijn:

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)

Betreffende het aanleveren van de gegevens:

  • Huidige wachtwoord opnieuw instellen

    • e-mail moet in hoofdtekst worden gegeven.
  • Nieuw wachtwoord maken (na reset)

    • nieuw wachtwoord, activeringscode en e-mailadres moeten in de hoofdtekst worden opgegeven.
  • Wachtwoord bijwerken (voor ingelogde gebruiker)

    • oud wachtwoord, nieuw wachtwoord moet in de body worden vermeld.
    • Gebruikers-ID in params.
    • Verificatietoken in de headers.

Antwoord 7, autoriteit 4%

Er zijn een paar overwegingen die u moet nemen:

Wachtwoord resets zijn niet idempotent

Een wachtwoordwijziging is van invloed op de gegevens die worden gebruikt als referenties om het uit te voeren, waardoor toekomstige pogingen ongeldig kunnen worden als het verzoek gewoon woordelijk wordt herhaald terwijl de opgeslagen referenties zijn gewijzigd. Als bijvoorbeeld een tijdelijke reset-token wordt gebruikt om de wijziging toe te staan, zoals gebruikelijk is in een situatie van vergeten wachtwoord, moet die token verlopen bij een succesvolle wachtwoordwijziging, wat weer verdere pogingen om het verzoek te repliceren teniet doet. Dus een REST-benadering van een wachtwoordwijziging lijkt een taak die beter geschikt is voor POSTdan voor PUT.

ID of e-mail in de gegevensbelasting is waarschijnlijk overbodig

Hoewel dat niet tegen REST is en een speciaal doel kan hebben, is het vaak niet nodig om een ​​ID of e-mailadres op te geven voor een wachtwoordreset. Denk er eens over na, waarom zou u het e-mailadres verstrekken als onderdeel van de gegevens voor een verzoek dat op de een of andere manier door authenticatie moet gaan? Als de gebruiker gewoon zijn wachtwoord wijzigt, moet hij zich hiervoor authenticeren (via gebruikersnaam:wachtwoord, e-mail:wachtwoord of toegangstoken die via headers wordt verstrekt). Daarom hebben we vanaf die stap toegang tot hun account. Als ze hun wachtwoord waren vergeten, zouden ze een tijdelijke reset-token hebben gekregen (via e-mail) die ze specifiek als inloggegevens kunnen gebruiken om de wijziging door te voeren. En in dit geval zou authenticatie via token voldoende moeten zijn om hun account te identificeren.

Rekening houdend met al het bovenstaande is dit wat volgens mij het juiste schema is voor een RESTful wachtwoordwijziging:

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

Antwoord 8, autoriteit 2%

Ik zou niet iets hebben dat het wachtwoord verandert en ze een nieuw wachtwoord stuurt als je besluit de /users/{id}/password-methode te gebruiken, en bij je idee te blijven dat het verzoek een hulpbron op zich is. dwz /user-password-request/ is de bron, en is PUT voor gebruik, gebruikersinfo zou in de body moeten staan.
Ik zou het wachtwoord echter niet veranderen, ik stuur een e-mail naar de gebruiker die een link bevat naar een pagina die een request_guid bevat, die samen met een verzoek kan worden doorgegeven aan POST /user/{id}/password/?request_guid= xxxx

Dat zou het wachtwoord veranderen, en het staat niet toe dat iemand een gebruiker afleidt door een wachtwoordwijziging aan te vragen.

Bovendien kan de initiële PUT mislukken als er een openstaand verzoek is.


Antwoord 9

We updaten het wachtwoord van de ingelogde gebruiker
PUT /v1/users/password – identificeer de gebruikers-ID met AccessToken.

Het is niet veilig om een ​​gebruikers-ID uit te wisselen. De Restful API moet de gebruiker identificeren met behulp van AccessToken ontvangen in HTTP-header.

Voorbeeld in spring-boot

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

Other episodes