Search code examples
c#model-view-controllermembership-providerumbraco7password-recovery

Best practice to send a member their forgotten password


I am building a login/registration section for our members area in Umbraco 7.1.7.

I would like to send a user their password in plain text via email.

The idea is, if the user forgets their password, they can simply enter their email address (which also serves as their username) and clicks the button: enter image description here
Now, I know Umbraco uses the ASP.NET Membership Provider and hashes passwords, which is nice but I need to access the plaintext version to send in the email.

I have changed my web.config to include this:

<membership defaultProvider="UmbracoMembershipProvider" userIsOnlineTimeWindow="15">
     <providers>
       <clear />
       <add name="UmbracoMembershipProvider" 
            type="Umbraco.Web.Security.Providers.MembersMembershipProvider, Umbraco" 
            minRequiredNonalphanumericCharacters="0" 
            minRequiredPasswordLength="0" 
            useLegacyEncoding="true" 
            enablePasswordRetrieval="true" 
            enablePasswordReset="true" 
            requiresQuestionAndAnswer="false" 
            defaultMemberTypeAlias="Member" 
            passwordFormat="clear" />

and my Controller Action method looks like this:

// Forgot password logic to send email
[ActionName("MvcMemberForgot")]
public ActionResult MvcMemberForgot(MvcMemberForgotModel model)
{
    string emailaddress = model.Email.ToString();    // The users entered email address.
    var member = Services.MemberService.GetByEmail(emailaddress);

    var sb = new StringBuilder();   // To build the message.
    sb.Append("Here is the password you chose for this email address: ");  
    sb.Append(password);  // I need a password value here...

    // Send the email.  
    library.SendMail("[email protected]", emailaddress, "Password", sb.ToString(), true);
    return CurrentUmbracoPage();
}

I can use var x = member.RawPasswordValue; to return the hashed password, is there a way to get the password the user typed in when they registered in a similar way?


Solution

  • I wouldn't send the emails to people in plain text, that's very poor security practice. The way I approached this recently was to do the following:

    • add a property to the member (a label) for storing a reset timestamp
    • have a reset request form that validates the user by email address, and then sets the label to a timestamp set 30 minutes to the future
    • send the member an email with a link to another form page, passing in their email and timestamp
    • on the form, get the email and timestamp, verify that the email exists, and that the timestamp hasn't expired
    • if they pass those tests, give them the option to enter and confirm a new password that you then save against the user (clearing the timestamp from the label at the same time)

    My approach was based on the code from this example repo: https://github.com/warrenbuckley/CWS-Umbraco-Standard-Membership which contains a lot of useful examples of working with members!