Resetting Password with ASP.NET 2.0 Membership and Multiple Providers
Thursday 15 February 2007 @ 8:39 am

Resetting Password with ASP.NET 2.0 Membership

Using Multiple Membership Providers

If you ever have wanted to be able to programmatically change (reset) a users password while at the same time continuing to be able to use the question and answer feature, this post is for you.  The problem is that if you use code like this:

 string username = “user”;
 string password = “pass@word”;
 MembershipUser mu = Membership.GetUser(username);  
 mu.ChangePassword(mu.ResetPassword(), password);
You will find that if you have in your web.config requiresQuestionAnswer="true", you will get an error when you try and reset the password.  The elegant solution to this is to create an additional membeship tag in your web.config and reference it when you change passwords.  That is, add another provider like this:
<membership defaultProvider=”SqlMembershipProvider” userIsOnlineTimeWindow=”15″>
<providers>
    <clear/>
    <add name=”SqlMembershipProviderOther” type=”SqlProviderOneShot.SqlMembershipProvider”
    requiresQuestionAndAnswer=”false”
     connectionStringName=”EmailEmailConnectionString” applicationName=”EmailEmail”
    enablePasswordRetrieval=”false” enablePasswordReset=”true” 
    requiresUniqueEmail=”true” passwordFormat=”Hashed”
    minRequiredNonalphanumericCharacters=”0″ writeExceptionsToEventLog=”false”
    minRequiredPasswordLength=”1″ passwordStrengthRegularExpression=”"
    passwordAttemptWindow=”10″ maxInvalidPasswordAttempts=”8″/>
</providers>
</membership>

Then, when you change your password, reference it as follows:


string username = “user”;
string password = “pass@word”;
MembershipUser mu = Membership.Providers[“SqlMembershipProviderOther”].GetUser(username);  
mu.ChangePassword(mu.ResetPassword(), password);

Hope this helps! At some point, I will integrate this functionality into my ObjectDataSource article that lets you display your membership information with a gridview or detailsview.

- Posted in ASP.NET 2.0, Membership  




13 Responses to “Resetting Password with ASP.NET 2.0 Membership and Multiple Providers”

  1. Lionel Thomas Windows XP Internet Explorer 6.0 Says:

    Hi Peter,
    Thanks for the reply. I did look at this post but when I tried to reference the provider from the providers collection it gave me an error.

    MembershipUser mu = Membership.Providers[”MembershipProvider” + strLocation].GetUser(strCurrentUser);

    CS1501: No overload for method ‘GetUser’ takes ‘1′ arguments

    If I add the second parameter it works fine.
    But in the case of the GetAllUsers when I add the 3 parameters(index,pagesize,totalrecords) it paginates the data. This of course changes the logic.

    MembershipUserCollection muc = Membership.Providers[”MembershipProvider” + strLocation].GetAllUsers();

    CS1501: No overload for method ‘GetAllUsers’ takes ‘0′ arguments

    This raises 2 issues for me.
    1. How can I modify your wrapper classes to allow for the overriding of the provider or just change the logic for the different providers? I also want to use roles and profiles.
    2. How does one know this stuff in the first place? I have spent a lot of time studing the classes, methods etc. but there doesn’t seem to be any indication of what methods can be overriden. I am pretty new to microsft classes and wish that I was gaining confidence in their use without making a career out of it.

    Sorry for the venting!

    My main objective is to reuse all the pages in my site by just changing the database for each location. I don’t want a copy of my website for each location. The ability to readily select connection strings and providers at run time seems to be hard to do. Any articles or tutorials of this nature would be much appreciated.

    I thank the gods of the internet for people like you who share their knowledge so freely.

    Thanks and regards,
    Lionel

  2. Polly Woodhouse Windows XP Internet Explorer 6.0 Says:

    Hi Peter,
    Thank you very much for your article which is much appreciated.

    I defined a new Membership Provider in my config file anyway, as I needed to connect to a SQL 2005 db rather than the express version.

    I then set the RequiresQuestionAndAnswer to false as you mentioned and I was then able to change somebody else’s password.

    However, as the RequiresQuestionAndAnswer is now false, it means that the PasswordRecovery control does not ask a user for an answer to their security question, which is a big disadvantage. Also, when creating a new user, it does not ask for a security question either. Is there any way that I can all the sets of functionality to co-exist and somehow set the config file depending what I am trying to do.

    Thank you so much for your help.

    Kind regards,

    Polly

  3. Shawn Dorman Windows XP Internet Explorer 7.0 Says:

    Polly,

    You’ll need two distinct membership providers to do this. The first provider (your default) would be used for all curcumstances EXCEPT changing passwords. The second provider would function identically to your first, except for the RequiresQuestionAndAnswer=”false” option. Use this provider only when changing (resetting) the password. That should do it.

    Thanks!

  4. Stephen Windows XP Internet Explorer 7.0 Says:

    Hi Peter,

    Thanks for the article, as i believe it can solve my problem but when i do …

    …and…

    MembershipUser mu = Membership.Providers[”SqlMembershipProviderOther”].GetUser(UserName, false);

    i get the following error.

    Configuration Error
    Description: An error occurred during the processing of a configuration file required to service this request. Please review the specific error details below and modify your configuration file appropriately.

    Parser Error Message: Could not load type ‘SqlProviderOneShot.SqlMembershipProvider’.

    Source Error:

    Line 19:
    Line 20:

  5. Jeremy Wadsworth Windows XP Internet Explorer 7.0 Says:

    This is a great post. It worked great after passing in the IsUserOnline value with the user name. Thanks a lot.

  6. Kenny Windows XP Mozilla Firefox 2.0.0.6 Says:

    Hi Peter,
    Thank you very much for the article, this is what I’m looking for… However, I’ve received error in this code:

    Membership mu = Membership.Providers[”CustomizedAdminMembershipProvider”].GetUser(Username);

    This is the error:
    No overload for mthod ‘GetUser’ takes ‘1′ arguments

    Any idea why?
    Thank you very much,
    Kenny.

  7. Administrator Windows Vista Internet Explorer 7.0 Says:

    Kenny,
    You are right that GetUser() does not work. You can always get the currently logged in user by doing Context.User.Identity.Name.
    -Peter Kellner

  8. Kenny Windows XP Mozilla Firefox 2.0.0.6 Says:

    Hi Peter,
    I’ve setup my page so that I have 2 textbox, 1 for the username and the other for the new password that I want to set it to. Is there a way so that my setup will work? I’m the Admin and sometime the user want me to reset the password for them, either they forgot the password as well as the answer to the secret question, or something going on with their email.

    Thank you very, very much.
    Kenny.

  9. Ric Plouffe Windows XP Internet Explorer 6.0 Says:

    I have a situation that I have two questions about.

    First, the situation:

    I have implemented a capability in our website where certain “power” users are able to add new website users to our database by uploading a spreadsheet. The spreadsheet contains the new user’s First and Last name and their e-mail; the e-mail becomes their login UserName.

    Upon spreadsheet upload, as records are added to a staging table in our database, I call dbo.aspnet_Membership_CreateUser passing it the parameter values it expects. right now, I am passing a known hashed password and salt value and a known password question and password answer value.

    As a separate process, I have a windows service that polls the database for newly-added users and calls Membership.Provider.ChangePassword to update their password to a unique temporary password and then send them an email with instructions how to log in with their email as the UserName and the temporary password we provide.

    These users, when they log into the website, are forced to change their temporary password with the ChagePassword control before they can do anything else.

    The first question is:

    How can I create a hashed version of the temporary password in T-SQL that is compatible with Membership/Roles and pass it to dbo.aspnet_Membership_CreateUser right from the onset instead of having to change it (again) in my windows process?

    The second and more urgent question is:

    Since new users added in this fashion never see the CreateUserWizard control and therefore never have an opportunity to enter their own password question/answer combination, what would be the best (and most secure) way for me to prompt them for a new password question/answer combination at the time I direct them to change their passowrd?

    Right now I have no “Forgot Password?” functionality because of this conundrum.

    Any guidance would be greatly appreciated…

  10. Ric Plouffe Windows XP Internet Explorer 6.0 Says:

    Never mind the second question. I have extended the ChangePassword control to include the Question/Answer combination.

    The first question is still something I’de like to figure out though. Everything’s working the way I have it set up now but it’s kindof a bubble gum/scotch tape solution.

    Thanks

  11. Atomiton Windows XP Mozilla Firefox 2.0.0.11 Says:

    Kenny… not sure if you’re still reading this… but it’s probably better to just use the ResetPassword() method. It will email them their new password and you don’t have to worry about it. It’s more secure too.

    You will need to implement two membership profiles for this.

    I won’t go into details as there are lots of posts explaining it better than I do.

    However, if you’re looking at Adding an AdminProvider for the built-in SQL Express DB that is created when you enable security from the WAT while leaving the default one for users, this could be your Web.config:

    <membership defaultProvider=ACPMembershipProvider”>
    <providers>
    <clear/>
    <add name=”ACPMembershipProvider” type=”System.Web.Security.SqlMembershipProvider”
    connectionStringName=”ACPDevSQL”
    applicationName=”ACPPortal”
    minRequiredPasswordLength=”3″
    minRequiredNonalphanumericCharacters=”0″
    enablePasswordRetrieval=”true”
    passwordForma=”Encrypted”
    enablePasswordReset=”true”
    requiresQuestionAndAnswer=”true”
    requiresUniqueEmail=”false”/>
    <name=”ACPMembershipProviderAdmin” type=”System.Web.Security.SqlMembershipProvider”
    connectionStringName=”ACPDevSQL”
    applicationName=”ACPPortal”
    minRequiredPasswordLength=”3″
    minRequiredNonalphanumericCharacters=”0″
    enablePasswordRetrieval=”true”
    passwordForma=”Encrypted”
    enablePasswordReset=”true”
    requiresQuestionAndAnswer=”false”
    requiresUniqueEmail=”false”/>
    </providers></membership>

  12. Jerry Windows Vista Internet Explorer 7.0 Says:

    Atomiton

    I am in the same boat as Kenny. I have a client that needs to be able to change a password for their user. Sometimes it is like pulling teeth to get these guys to walk through the process. So I set it up as above, but in order to change the password, I need old and new. If i reset it, it will go to their email and it is lost. So I figure my choices are like this.

    1) change their email to the admins, fire the reset, get the new password. Then change their email back, use the emailed password to change the password to what they wanted.

    2) somehow reset the password and display it on the screen without actually mailing it. Follow the second half of #1 and change to what they wanted.

    3) Figure out how to hash the new password and store that result in the table with the salt key and bypass the provider. Just do a straight stored procedure.

    Any thought to point me in the right direction and maybe shoot holes in my thinking? The biggest thing I need to be able to set the password to a password of my choosing, through an admin account. Everything I can think of comes up messy.

  13. Jerry Windows Vista Internet Explorer 7.0 Says:

    After talking with Peter, and looking at his code again, it worked like a champ. The part that kind of threw me for a loop was using the reset function as the old password. Here is my code in VB. Keep in mind that my provider MembersAdmin is just for the admin section of the client’s site.

    Dim U As MembershipUser = Membership.Providers(”MembersAdmin”).GetUser(SUserName, False)
    If Not U Is Nothing Then
    U.ChangePassword(U.ResetPassword(), strPassword)
    txtPassword.Text = “”
    msgProgress.Text = “Password Changed”
    End If

Leave a Reply