Comment implémenter les réinitialisations de mot de passe?

Je travaille sur une application dans ASP.NET, et je me demandais comment je pourrais implémenter une fonction de Password Reset si je voulais lancer la mienne.

Plus précisément, j’ai les questions suivantes:

  • Quel est un bon moyen de générer un identifiant unique difficile à casser?
  • Devrait-il y avoir une timer? Si oui, combien de temps devrait-il être?
  • Dois-je enregistrer l’adresse IP? Est-ce même important?
  • Quelles informations dois-je demander sous l’écran “Réinitialisation du mot de passe”? Juste une adresse email? Ou peut-être une adresse e-mail et une information qu’ils “connaissent”? (Équipe favorite, nom du chiot, etc.)

Y a-t-il d’autres considérations dont je dois être conscient?

NB : D’autres questions ont complètement dépassé la mise en œuvre technique. En effet, la réponse acceptée dépasse les détails évidents. J’espère que cette question et les réponses qui en découleront entreront dans les détails évidents, et j’espère qu’en formulant cette question de manière beaucoup plus étroite, les réponses seront moins «floues» et plus «gore».

Edit : des réponses qui expliquent également comment une telle table serait modélisée et gérée dans SQL Server ou tout lien ASP.NET MVC vers une réponse seraient appréciées.

Beaucoup de bonnes réponses ici, je ne prendrai pas la peine de tout répéter …

Sauf pour un problème, qui est répété par presque toutes les réponses ici, même si c’est faux:

Les guids sont (de manière réaliste) uniques et statistiquement impossibles à deviner.

Ce n’est pas vrai, les GUID sont des identificateurs très faibles et ne doivent PAS être utilisés pour autoriser l’access au compte d’un utilisateur.
Si vous examinez la structure, vous obtenez un total de 128 bits au maximum … ce qui n’est pas considéré de nos jours.
Dont la première moitié est invariante typique (pour le système générateur), et la moitié de ce qui rest est dépendant du temps (ou autre chose similaire).
Dans l’ensemble, c’est un mécanisme très faible et facilement brutal.

Alors n’utilisez pas ça!

Au lieu de cela, utilisez simplement un générateur de nombres aléatoires cryptographiquement fort ( System.Security.Cryptography.RNGCryptoServiceProvider ) et obtenez au moins 256 bits d’entropie brute.

Tout le rest, comme les nombreuses autres réponses fournies.

EDIT 2012/05/22: Suite à cette réponse populaire, je n’utilise plus les GUID moi-même dans cette procédure. Comme l’autre réponse populaire, j’utilise maintenant mon propre algorithme de hachage pour générer la clé à envoyer dans l’URL. Cela a aussi l’avantage d’être plus court. Recherchez dans System.Security.Cryptography pour les générer, et j’utilise généralement un SALT.

Tout d’abord, ne réinitialisez pas immédiatement le mot de passe de l’utilisateur.

Tout d’abord, ne réinitialisez pas immédiatement le mot de passe de l’utilisateur lorsqu’il le demande. Il s’agit d’une faille de sécurité, car quelqu’un pourrait deviner les adresses électroniques (c.-à-d. Votre adresse électronique dans l’entreprise) et réinitialiser les mots de passe à sa guise. Les meilleures pratiques de nos jours incluent généralement un lien de “confirmation” envoyé à l’adresse électronique de l’utilisateur, confirmant qu’il souhaite le réinitialiser. Ce lien est l’endroit où vous souhaitez envoyer le lien de clé unique. J’envoie le mien avec un lien comme: domain.com/User/PasswordReset/xjdk2ms92

Oui, définissez un délai d’expiration sur le lien et stockez la clé et le délai d’attente sur votre backend (et salez si vous en utilisez un). Le délai d’attente de 3 jours est la norme et assurez-vous d’informer l’utilisateur de 3 jours au niveau du Web lorsqu’il demande une réinitialisation.

Utilisez une clé de hachage unique

Ma réponse précédente disait d’utiliser un GUID. Je suis en train de modifier ceci pour conseiller à tout le monde d’utiliser un hachage généré aléatoirement, par exemple en utilisant le RNGCryptoServiceProvider . Et, assurez-vous d’éliminer tous les “vrais mots” du hachage. Je me souviens d’un appel téléphonique spécial de 6 heures du matin où une femme avait reçu un mot “c” dans sa clé hachée “supposée être aléatoire” qu’un développeur avait faite. Doh!

Procédure complète

  • L’utilisateur clique sur “réinitialiser” le mot de passe.
  • L’utilisateur est invité à envoyer un courrier électronique.
  • L’utilisateur entre un email et clique sur envoyer. Ne confirmez pas ou ne refusez pas le courrier électronique, car cela est également une mauvaise pratique. Dites simplement: “Nous avons envoyé une demande de réinitialisation de mot de passe si l’e-mail est vérifié.” ou quelque chose de cryptique.
  • Vous créez un hachage à partir du RNGCryptoServiceProvider , stockez-le en tant qu’entité distincte dans une table ut_UserPasswordRequests et ut_UserPasswordRequests un lien avec l’utilisateur. Ainsi, vous pouvez suivre les anciennes demandes et informer l’utilisateur que les anciens liens ont expiré.
  • Envoyez le lien vers l’e-mail.

L’utilisateur obtient le lien, comme http://domain.com/User/PasswordReset/xjdk2ms92 , et clique dessus.

Si le lien est vérifié, vous demandez un nouveau mot de passe. Simple et l’utilisateur doit définir son propre mot de passe. Ou, définissez votre propre mot de passe crypté ici et informez-le de son nouveau mot de passe ici (et envoyez-le lui par courrier électronique).

Tout d’abord, nous devons savoir ce que vous savez déjà sur l’utilisateur. De toute évidence, vous avez un nom d’utilisateur et un ancien mot de passe. Que savez-vous d’autre? As-tu une adresse e-mail? Avez-vous des données concernant la fleur préférée de l’utilisateur?

En supposant que vous avez un nom d’utilisateur, un mot de passe et une adresse e-mail active, vous devez append deux champs à votre table utilisateur (en supposant qu’il s’agit d’une table de firebase database): une date appelée new_passwd_expire et une chaîne new_passwd_id.

En supposant que vous ayez l’adresse électronique de l’utilisateur, lorsque quelqu’un demande une réinitialisation du mot de passe, vous mettez à jour le tableau utilisateur comme suit:

 new_passwd_expire = now() + some number of days new_passwd_id = some random ssortingng of characters (see below) 

Ensuite, vous envoyez un courrier électronique à l’utilisateur à cette adresse:

Cher Untel

Quelqu’un a demandé un nouveau mot de passe pour le compte d’utilisateur sur . Si vous avez demandé cette réinitialisation du mot de passe, suivez ce lien:

http://example.com/yourscript.lang?update= < new_password_id >

Si ce lien ne fonctionne pas, vous pouvez aller à http://example.com/yourscript.lang et entrer les informations suivantes dans le formulaire:

Si vous n’avez pas demandé de réinitialisation du mot de passe, vous pouvez ignorer cet e-mail.

Merci, yada yada

Maintenant, codez votre script.lang: Ce script a besoin d’un formulaire. Si la mise à jour var transmettait l’URL, le formulaire demande simplement le nom d’utilisateur et l’adresse électronique de l’utilisateur. Si la mise à jour n’est pas passée, elle demande le nom d’utilisateur, l’adresse électronique et le code d’identification envoyé dans le courrier électronique. Vous demandez également un nouveau mot de passe (deux fois bien sûr).

Pour vérifier le nouveau mot de passe de l’utilisateur, vous vérifiez que le nom d’utilisateur, l’adresse électronique et le code d’identification correspondent tous, que la demande n’a pas expiré et que les deux nouveaux mots de passe correspondent. En cas de succès, vous changez le mot de passe de l’utilisateur en nouveau mot de passe et effacez les champs de réinitialisation du mot de passe du tableau des utilisateurs. Veillez également à déconnecter l’utilisateur / effacer tous les cookies liés à la connexion et redirect l’utilisateur vers la page de connexion.

Essentiellement, le champ new_passwd_id est un mot de passe qui ne fonctionne que sur la page de réinitialisation du mot de passe.

Une amélioration potentielle: vous pouvez supprimer de l’e-mail. “Quelqu’un a demandé une réinitialisation du mot de passe pour un compte à cette adresse e-mail …”. Ainsi, en identifiant le nom d’utilisateur, seul l’utilisateur sait si l’e-mail est intercepté. Je n’ai pas commencé de cette façon car si quelqu’un attaque le compte, il connaît déjà le nom d’utilisateur. Cette obscurité supplémentaire stoppe les attaques d’opportunités par un intermédiaire si une personne malveillante intercepte l’e-mail.

Pour vos questions:

générer la chaîne aléatoire: il n’a pas besoin d’être extrêmement aléatoire. Tout générateur de GUID ou même md5 (concat (salt, current_timestamp ())) est suffisant, ou sel est quelque chose dans l’enregistrement de l’utilisateur, comme le compte d’horodatage a été créé. Ce doit être quelque chose que l’utilisateur ne peut pas voir.

timer: Oui, vous en avez besoin pour garder votre firebase database saine. Pas plus d’une semaine n’est vraiment nécessaire, mais au moins 2 jours, car vous ne savez jamais combien de temps un retard de messagerie peut durer.

Adresse IP: L’e-mail pouvant être retardé de plusieurs jours, l’adresse IP n’est utile que pour la journalisation et non pour la validation. Si vous voulez vous connecter, faites-le, sinon vous n’en avez pas besoin.

Écran de réinitialisation: Voir ci-dessus.

Espérons que ça couvre. Bonne chance.

Un GUID envoyé à l’adresse e-mail d’enregistrement est probablement suffisant pour la plupart des applications standard, avec un délai encore meilleur.

Après tout, si la boîte aux lettres des utilisateurs a été compromise (c’est-à-dire qu’un pirate dispose de la connexion / du mot de passe pour l’adresse électronique), vous ne pouvez pas faire grand chose à ce sujet.

Vous pouvez envoyer un email à l’utilisateur avec un lien. Ce lien contiendrait des chaînes difficiles à deviner (comme le GUID). Du côté du serveur, vous stockeriez également la même chaîne que vous avez envoyée à l’utilisateur. Maintenant, lorsque l’utilisateur appuie sur le lien, vous pouvez trouver dans votre entrée db avec la même chaîne secrète et réinitialiser son mot de passe.

1) Pour générer l’identifiant unique, vous pouvez utiliser l’algorithme de hachage sécurisé. 2) timer attachée? Voulez-vous dire une expiration pour le lien de réinitialisation pwd? Oui, vous pouvez avoir un ensemble d’expiration 3) Vous pouvez demander d’autres informations que l’e-mailId pour valider .. Comme la date de naissance ou certaines questions de sécurité 4) Vous pouvez également générer des caractères aléatoires et demander de les entrer avec la requête .. pour s’assurer que la demande de mot de passe n’est pas automatisée par certains logiciels espions ou des choses comme ça ..