Pour mon projet, j'ai besoin d'une fonctionnalité " mot de passe oublié".
Je ne sais pas encore comment implémenter ce type de fonctionnalité, alors j'espérais trouver des "meilleures pratiques" sur Internet, mais je n'ai rien trouvé d'utile qui traite tous les aspects importants de cette fonctionnalité assez courante.
Mes propres réflexions à ce sujet sont assez simples:
Si un utilisateur voulait changer son mot de passe, je pouvais créer un jeton unique uniqueTokenForTheUser
attaché à une "demande de changement de mot de passe" qui serait essentiellement l'identifiant de mon backend pour dire si c'était le bon utilisateur qui avait envoyé la demande.
Par exemple, je générerais/enverrais un e-mail à [email protected]
avec un lien
http://www.example.com/changePassword?token=uniqueTokenForTheUser
uniqueTokenForTheUser
serait stocké dans une table qui est vérifiée par un thread dans un certain intervalle et supprime l'enregistrement une fois le jeton expiré au cas où l'utilisateur n'aurait pas réellement changé son mot de passe.
Bien que cela me semble assez simple, je voulais vérifier s'il y avait des "meilleures pratiques", par exemple en ce qui concerne la génération et la suppression de ce jeton particulier.
Toutes suggestions ou références à des articles/tutoriels sont les bienvenues!
Liens supplémentaires suggérés par les commentaires:
Utilisez HTTPS uniquement pour cela, puis nous verrons les détails de la mise en œuvre.
Tout d'abord, vous allez vouloir vous protéger contre énumération des utilisateurs .
Autrement dit, ne révélez pas dans la page si l'utilisateur existe ou non. Cela ne doit être divulgué que dans l'e-mail lui-même.
Deuxièmement, vous voudrez éviter fuite de référent . Assurez-vous qu'aucun lien externe ou ressource externe n'est présent sur votre lien cible. Une façon d'atténuer cela est de rediriger une fois le lien initial suivi afin que le jeton ne soit plus dans la chaîne de requête. Sachez que si quelque chose ne va pas (par exemple, votre base de données est brièvement en panne) et qu'un modèle d'erreur standard est affiché, cela peut entraîner une fuite du jeton s'il contient des références externes.
Générez un jeton avec 128 bits d'entropie avec un CSPRNG. Stockez ce côté serveur à l'aide de SHA-2 pour empêcher toute vulnérabilité de fuite de données sur votre table de réinitialisation de permettre à un attaquant de réinitialiser les mots de passe. Notez que le sel n'est pas nécessaire. Expirez ces jetons après un court laps de temps (par exemple quelques heures).
En plus de fournir le jeton non haché à l'utilisateur dans le lien de courrier électronique, donnez à l'utilisateur la possibilité d'accéder à la page manuellement, puis collez la valeur du jeton. Cela peut empêcher les valeurs de chaîne de requête d'être enregistrées dans l'historique du navigateur et dans les journaux de proxy et de serveur par défaut.
Vous pouvez éventuellement vous assurer que l'identifiant de session pour la session qui a lancé la réinitialisation du mot de passe est celui qui a suivi le lien . Cela peut aider à protéger un compte où l'attaquant a accès au courrier électronique de l'utilisateur (par exemple, en configurant une règle d'avance rapide avec un accès limité au compte de messagerie). Cependant, tout cela empêche vraiment un attaquant de suivre de manière opportuniste une réinitialisation demandée par l'utilisateur - l'attaquant pourrait toujours demander son propre jeton de réinitialisation pour la victime s'il souhaite cibler votre site particulier.
Une fois que le mot de passe a été réinitialisé sur celui de l'utilisateur, vous devrez expirer le jeton et envoyer à l'utilisateur un e-mail pour lui faire savoir que cela s'est produit juste au cas où un attaquant aurait réussi à réinitialiser son mot de passe (sans nécessairement avoir le contrôle). de leur compte mail) - défense en profondeur. Vous devez également faire pivoter l'identifiant de session en cours et expirer tous les autres pour ce compte d'utilisateur . Cela supprime la nécessité pour l'utilisateur de se reconnecter, tout en effaçant toutes les sessions montées par un attaquant, bien que certains utilisateurs aiment que le site les déconnecte afin d'obtenir une confirmation de confirmation que leur mot de passe a bien été réinitialisé. La redirection vers la page de connexion donne également à certains gestionnaires de mots de passe la possibilité d'enregistrer l'URL de connexion et le nouveau mot de passe, bien que beaucoup détectent déjà le nouveau mot de passe à partir de la page de réinitialisation.
Vous pouvez également envisager d'autres options hors bande pour le mécanisme de réinitialisation et les notifications de modification. Par exemple, par SMS ou alertes par téléphone mobile.
Votre ligne de pensée est sur la bonne voie. Cependant, je suggère de décrire le flux de votre fonctionnalité de mot de passe oublié à partir d'une étape précédente. Quelqu'un prétend avoir oublié son mot de passe, vous devez vous assurer que vous identifiez que cette personne est bien le propriétaire du compte pour lequel vous allez démarrer le mot de passe procédure de récupération.
Le flux ci-dessous suppose un service où les gens peuvent s'inscrire, comme un site Web (en d'autres termes, une liste d'e-mails enregistrés et/ou de noms d'utilisateur peut être créée à l'aide de la fonctionnalité d'inscription).
première étape: identifier l'utilisateur
étape deux: démarrer la procédure de récupération
Étape 3: mettre à jour leur mot de passe
Vous êtes proche de la meilleure pratique avec votre approche. Un petit ajout serait:
Vous pouvez exiger que le nom d'utilisateur corresponde au jeton plutôt que de simplement déduire l'utilisateur du jeton.
Vous devriez plutôt utiliser https que http.
Les autres questions:
En ce qui concerne la génération: une façon habituelle de les générer est d'utiliser des UUID, mais comme le soulignent les commentaires, vous devriez plutôt utiliser une chaîne complètement aléatoire et suffisamment longue.
En ce qui concerne la suppression: vous pouvez nettoyer régulièrement les anciens jetons inutilisés comme vous l'avez suggéré. Utilisez peut-être un délai qui permet au courrier de passer par la liste d'e-mails habituelle, par ex. 15 minutes.
Quelques réflexions à ce sujet:
Pour plus de lecture sur le sujet, je recommande Troy Hunt .