Quelle est la bonne façon de structurer une ressource RESTful pour réinitialiser un mot de passe?
Cette ressource est destinée à être une réinitialisation de mot de passe pour quelqu'un qui a perdu ou oublié son mot de passe. Il invalide leur ancien mot de passe et leur envoie un mot de passe par e-mail.
Les deux options que j'ai sont:
POST /reset_password/{user_name}
ou...
POST /reset_password
-Username passed through request body
Je suis presque sûr que la demande doit être un POST. Je suis moins sûr d'avoir choisi un nom approprié. Et je ne sais pas si le nom_utilisateur doit être transmis via l'URL ou le corps de la requête.
la source
Utilisateurs non authentifiés
Nous faisons une
PUT
demande sur unapi/v1/account/password
point de terminaison et avons besoin d'un paramètre avec l'e-mail de compte correspondant pour identifier le compte pour lequel l'utilisateur souhaite réinitialiser (mettre à jour) le mot de passe:Remarque: comme @DougDomeny l'a mentionné dans son commentaire, transmettre l'e-mail en tant que chaîne de requête dans l'url est un risque de sécurité. Les paramètres GET ne sont pas exposés lors de l'utilisation
https
(et vous devez toujours utiliser unehttps
connexion appropriée pour de telles demandes), mais d'autres risques de sécurité sont impliqués. Vous pouvez en savoir plus sur ce sujet dans cet article de blog ici .Passer l'e-mail dans le corps de la requête serait une alternative plus sûre que de le transmettre en tant que paramètre GET:
Demander le corps:
La réponse a une signification de réponse
202
acceptée :L'utilisateur recevra un e-mail à
[email protected]
et le traitement de la demande de mise à jour dépend des actions entreprises avec le lien de l'e-mail.L'ouverture du lien à partir de cet e-mail dirigera vers un formulaire de réinitialisation de mot de passe sur l'application frontale qui utilise le jeton de réinitialisation du mot de passe du lien comme entrée pour un champ de saisie masqué (le jeton fait partie du lien en tant que chaîne de requête). Un autre champ de saisie permet à l'utilisateur de définir un nouveau mot de passe. Une deuxième entrée pour confirmer le nouveau mot de passe sera utilisée pour la validation sur le front-end (pour éviter les fautes de frappe).
Remarque: dans l'e-mail, nous pourrions également mentionner que si l'utilisateur n'a initialisé aucune réinitialisation de mot de passe, il peut ignorer l'e-mail et continuer à utiliser l'application normalement avec son mot de passe actuel.
Lorsque le formulaire est soumis avec le nouveau mot de passe et le jeton comme entrées, le processus de réinitialisation du mot de passe aura lieu. Les données du formulaire seront à nouveau envoyées avec une
PUT
demande, mais cette fois avec le jeton et nous remplacerons le mot de passe de la ressource par une nouvelle valeur:Demander le corps:
La réponse sera une réponse
204
sans contenuUtilisateurs authentifiés
Pour les utilisateurs authentifiés qui souhaitent modifier leur mot de passe, la
PUT
demande peut être effectuée immédiatement sans l'e-mail (le compte pour lequel nous mettons à jour le mot de passe est connu du serveur). Dans ce cas, le formulaire soumettra deux champs:Demander le corps:
la source
Soyons uber-RESTful pendant une seconde. Pourquoi ne pas utiliser l'action DELETE pour le mot de passe pour déclencher une réinitialisation? Cela a du sens, n'est-ce pas? Après tout, vous supprimez effectivement le mot de passe existant au profit d'un autre.
Cela signifie que vous feriez:
Maintenant, deux grandes mises en garde:
HTTP DELETE est censé être idempotent (un mot sophistiqué pour dire "pas grand chose si vous le faites plusieurs fois"). Si vous faites des choses standard comme l'envoi d'un e-mail de "réinitialisation du mot de passe", vous allez rencontrer des problèmes. Vous pouvez contourner ce marquage de l'utilisateur / mot de passe avec un indicateur booléen «Est réinitialisé». À chaque suppression, vous vérifiez cet indicateur; si ce n'est pas réglé alors vous pouvez réinitialiser le mot de passe et envoyer votre e - mail. (Notez que cet indicateur peut avoir d'autres utilisations.)
Vous ne pouvez pas utiliser HTTP DELETE via un formulaire , vous devrez donc faire un appel AJAX et / ou tunneler DELETE via le POST.
la source
DELETE
bien s'intégrer ici. Vous remplaceriez le mot de passe par un mot de passe généré au hasard, je suppose, ce quiDELETE
pourrait être trompeur. Je préfère leCreate (POST) new reset_password action
, où le nom (ressource) sur lequel vous agiriez est "l'action reset_password". Cela convient également à l'envoi d'e-mails, car l'action encapsule tous ces détails de niveau inférieur.POST
n'est pas idempotent.Souvent, vous ne souhaitez pas supprimer ou détruire le mot de passe existant de l'utilisateur lors de la demande initiale, car cela peut avoir été déclenché (involontairement ou intentionnellement) par un utilisateur qui n'a pas accès à l'e-mail. Au lieu de cela, mettez à jour un jeton de réinitialisation du mot de passe sur l'enregistrement utilisateur et envoyez-le dans un lien inclus dans un e-mail. Cliquer sur le lien confirmera que l'utilisateur a reçu le jeton et souhaite mettre à jour son mot de passe. Idéalement, cela serait également sensible au facteur temps.
L'action RESTful dans ce cas serait un POST: déclenchement de l'action de création sur le contrôleur PasswordResets. L'action elle-même mettrait à jour le jeton et enverrait un e-mail.
la source
Je cherche en fait une réponse, pas l'intention d'en fournir une - mais "reset_password" me semble faux dans un contexte REST parce que c'est un verbe, pas un nom. Même si vous dites que vous faites un nom "action de réinitialisation" - en utilisant cette justification, tous les verbes sont des noms.
De plus, quelqu'un qui recherche la même réponse n'a peut-être pas pensé que vous pourriez obtenir le nom d'utilisateur via le contexte de sécurité et que vous ne deviez pas du tout l'envoyer via l'url ou le corps, ce qui me rend nerveux.
la source
reset-password
ressemble peut-être à un verbe, mais vous pouvez facilement l'inverser (password-reset
) pour en faire un nom. Et si vous avez modélisé votre application à l'aide de Event Sourcing ou même si vous avez juste n'importe quel type d'audit, il est logique que vous ayez en fait une véritable entité avec ce nom et que vous puissiez même autoriser les GET pour les utilisateurs ou les administrateurs à voir historique (masquant évidemment le texte du mot de passe). Cela ne me rend pas du tout nerveux. Et en ce qui concerne la récupération automatique du nom d'utilisateur côté serveur - vous pouvez, mais comment gérez-vous des choses comme l'administration / l'usurpation d'identité?reset-password
parviens à bien décrire ses effets.Je pense que la meilleure idée serait:
Concernant la fourniture des données:
Pour réinitialiser le mot de passe actuel
Pour créer un nouveau mot de passe (après réinitialisation)
Pour mettre à jour le mot de passe (pour l'utilisateur connecté)
la source
Il y a quelques considérations à prendre:
Les réinitialisations de mot de passe ne sont pas idempotentes
Un changement de mot de passe affecte les données utilisées comme informations d'identification pour l'exécuter, ce qui pourrait par conséquent invalider les tentatives futures si la demande est simplement répétée textuellement alors que les informations d'identification stockées ont changé. Par exemple, si un jeton de réinitialisation temporaire est utilisé pour autoriser la modification, comme il est habituel dans une situation de mot de passe oublié, ce jeton doit expirer en cas de changement de mot de passe réussi, ce qui annule à nouveau les tentatives de réplication de la demande. Ainsi, une approche RESTful d'un changement de mot de passe semble être un travail mieux adapté
POST
quePUT
.ID ou e-mail dans le chargement de données est probablement redondant
Bien que cela ne soit pas contraire à REST et puisse avoir un but particulier, il est souvent inutile de spécifier un identifiant ou une adresse e-mail pour une réinitialisation de mot de passe. Pensez-y, pourquoi fourniriez-vous l'adresse e-mail dans le cadre des données à une demande qui est censée passer par l'authentification d'une manière ou d'une autre? Si l'utilisateur change simplement son mot de passe, il doit s'authentifier pour ce faire (via nom d'utilisateur: mot de passe, email: mot de passe ou jeton d'accès fourni via les en-têtes). Par conséquent, nous avons accès à leur compte à partir de cette étape. S'ils avaient oublié leur mot de passe, ils auraient reçu un jeton de réinitialisation temporaire (par e-mail) qu'ils pourraient utiliser spécifiquement comme informations d'identification pour effectuer la modification. Et dans ce cas, l'authentification via jeton devrait suffire à identifier leur compte.
En tenant compte de tout ce qui précède, voici ce que je pense être le schéma approprié pour un changement de mot de passe RESTful:
la source
POST
vs.PUT
RFC 7231 spécifie qu'une mise à jour partielle peut être réalisée par chevauchement des données de deux ressources, mais il est douteux que quelque chose comme/v1/account/password
compense réellement une bonne ressource. ToutPOST
comme le swiss-army-kniff du Web qui peut être utilisé si aucune des autres méthodes n'est faisable, ilPATCH
pourrait également être possible de définir le nouveau mot de passe.Je n'aurais pas quelque chose qui changerait le mot de passe et leur en enverrait un nouveau si vous décidez d'utiliser la méthode / users / {id} / password et que vous vous en tenez à votre idée que la demande est une ressource en soi. ie / user-password-request / est la ressource, et utilise PUT, les informations utilisateur doivent être dans le corps. Je ne changerais pas le mot de passe cependant, Id envoyer un e-mail à l'utilisateur qui contient un lien vers une page qui contient un request_guid, qui pourrait être transmis avec une demande à POST / user / {id} / password /? Request_guid = xxxxx
Cela changerait le mot de passe et ne permettrait pas à quelqu'un de détourner un utilisateur en demandant un changement de mot de passe.
De plus, le PUT initial pourrait échouer s'il y a une demande en suspens.
la source
Nous mettons à jour le mot de passe de l'utilisateur connecté PUT / v1 / users / password - identifiez l'identifiant de l'utilisateur à l'aide d'AccessToken.
L'échange d'identifiant d'utilisateur n'est pas sécurisé. L'API Restful doit identifier l'utilisateur à l'aide d'AccessToken reçu dans l'en-tête HTTP.
Exemple dans spring-boot
la source