2

I'm using the asp.net forms authentication and i need to be able to reset the password for a user.

This is the code:

protected void resetPassword(string username)
{
    MembershipUser user = Membership.GetUser(username);
    if (user != null)
    {
        string newPassword = user.ResetPassword();
        Membership.UpdateUser(user);
        MailMessage message = new MailMessage("", user.Email, "change password", "your Password changed to: " + newPassword);
        userManager.sendMail(message);
    }
}

And here is my web.config file:

<?xml version="1.0"?>
<configuration>
  <appSettings>
    <add key="ChartImageHandler" value="storage=file;timeout=20;dir=c:\TempImageFiles\;" />
  </appSettings>
  <system.webServer>
    <handlers>
      <remove name="ChartImageHandler" />
      <add name="ChartImageHandler" preCondition="integratedMode" verb="GET,HEAD,POST"
       path="ChartImg.axd" type="System.Web.UI.DataVisualization.Charting.ChartHttpHandler, System.Web.DataVisualization, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
    </handlers>
  </system.webServer>
  <connectionStrings>
    <add name="CRM_DBConnectionString" connectionString="Data Source=.\SQLEXPRESS;AttachDbFilename=C:\CRM\CRM\DAL_new\CRM_DB.mdf;Integrated Security=True;User Instance=True" providerName="System.Data.SqlClient"/>
    <add name="CRM_DBConnectionString2" connectionString="Data Source=.\SQLEXPRESS;AttachDbFilename=C:\CRM\DAL_new\CRM_DB.mdf;Integrated Security=True;User Instance=True" providerName="System.Data.SqlClient"/>
  </connectionStrings>
  <system.web>
    <httpHandlers>
      <add path="ChartImg.axd" verb="GET,HEAD,POST" type="System.Web.UI.DataVisualization.Charting.ChartHttpHandler, System.Web.DataVisualization, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
       validate="false" />
    </httpHandlers>
    <pages>
      <controls>
        <add tagPrefix="asp" namespace="System.Web.UI.DataVisualization.Charting"
         assembly="System.Web.DataVisualization, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
      </controls>
    </pages>
    <roleManager enabled="true"/>
    <authentication mode="Forms">
      <forms loginUrl="./login_page/Default.aspx" name=".ASPXFORMSAUTH" protection="All" timeout="43200" requireSSL="false" slidingExpiration="true" cookieless="UseCookies" enableCrossAppRedirects="false" />
    </authentication>
    <compilation debug="true" targetFramework="4.0">
      <assemblies>
        <add assembly="System.Web.Extensions.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
        <add assembly="System.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A"/>
        <add assembly="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
        <add assembly="System.Web.DataVisualization, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
      </assemblies>
    </compilation>
  </system.web>
  <system.net>
    <mailSettings>
      <smtp from="[email protected]">
        <network host="smtp.gmail.com" password="########" port="587" userName="######@gmail.com"/>
      </smtp>
    </mailSettings>
  </system.net>
  <system.serviceModel>
    <bindings>
      <basicHttpBinding>
        <binding name="BasicHttpBinding_IBlServer" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536" messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered" useDefaultWebProxy="true">
          <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384"/>
          <security mode="None">
            <transport clientCredentialType="None" proxyCredentialType="None" realm=""/>
            <message clientCredentialType="UserName" algorithmSuite="Default"/>
          </security>
        </binding>
      </basicHttpBinding>
    </bindings>
    <client>
      <endpoint address="http://localhost:51109/Service1.svc" binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IBlServer" contract="CrmServiceReference.IBlServer" name="BasicHttpBinding_IBlServer"/>
    </client>
  </system.serviceModel>
</configuration>

The line: string newPassword = user.ResetPassword(); throws the exception:

System.ArgumentNullException was unhandled by user code
  Message=Value cannot be null.
Parameter name: passwordAnswer

I've been through lots of similar question here and on other sites, but i can't seem to get it right. It either ends up with an error about ResetPassword() that has to get a parameter, or mucks up other code on the page that retrieves user account for other manipulation.

The solution here mucks up other MembershipUser user = Membership.GetUser(username); lines in my code.

So where and how to i configure my web.config if i want the following:
1. A user can reset his password for himself using the security Q&A (this already works)
2. An admin can reset the password for a user. The user will get an E-Mail with the new password.

Thanks in advance,
Summerbulb

2 Answers 2

2

Do you have custom membership settings provided? I don't see them in the config. I had the same issue too, and ended up dropping the password question/answer. Are you hashing passwords and password answers? If using the hash option, this won't work without knowing the correct answer. If you are doing the encrypted route, then you could reflectively call the Decrypt methods in the SqlMembershipProvider class to decrypt the data, which is a little pain but works.

Similarly, you have a few other options. Turn off the password question/answer, but custom implement this yourself. Membership framework was not meant for sys admin features. Secondly, store the answer manually (essentially duplicate it) in clear text or encrypted using your algorithm, and decrypt it.

The password question and answer is all driven from config, so lastly, you could also consider making two membership providers, the second one with requiresquestionandanswer to false:

<add name="AdminProvider" type="<point to SQL membership" requiresQuestionAndAnswer="false" />

In your admin screen, do:

Membership.Providers[1].ResetPassword();

And then it work work because it's configuration states no question and answer is needed.

Let me know if you need more info.

Sign up to request clarification or add additional context in comments.

7 Comments

'encrypted using your algorithm' NEVER ever do that, use built-in cryptographic services
'you could also consider making two membership providers' - But there isn't a first one. Do i need it? If i add your member provider won't that affect all the MembershipUser user = membership.GetUser(username); in the code?
@summerbulb You must define membership section, otherwise 'user' variable will always be null (or GetUser will probably throw an exception before). Long story short, without membership section in your web.config your code will not work.
@Tomas As you can see, our config file contains no membership section, yet 'user' is defined and 'GetUser()' works fine. The only problem in that snippet is with 'ResetPassword()'.
@summerbulb I see, you are using default SqlMembershipProvider (it is defined in machine.config. ASP.NET uses it if you do not define one). Just add new provider for admin use only as Brian suggested.
|
1

What you need for part 2 (An admin can reset the password for a user. The user will get an E-Mail with the new password.) you can see here

http://www.ezineasp.net/post/ASP-Net-2-0-Password-Recovery-Control-With-Email.aspx

For me it works. If user forgot his password, he gets e-mail with new password.Only You need to set enablePasswordReset to true.

3 Comments

'You need to set enablePasswordReset to true.' - Where and how? I am quite sure that the config section in the link you posted was auto generated somehow.
I added line "enablePasswordReset=true" to my web.config and if user forgot password he gets new password after password recovery and you don't need to write your function resetPassword().
<membership> <providers> <clear/> <add name="AspNetSqlMembershipProvider" connectionStringName="LocalSqlServer" applicationName="/" type="System.Web.Security.SqlMembershipProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" enablePasswordRetrieval="true" enablePasswordReset="false" passwordFormat="Clear"/> </providers> </membership>

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.