April 30, 2008
Membership Provider Oddity
I thought I would write this one up as maybe I’m not the only slow one unable to find any reference to information about a way to set a users password to a known value programatically using the MembershipProvider classes. It seems much of System.Web.Security is geared towards interacting with a user and not as an API into the security framework itself. That is unless of course you wish to create you own provider.
If you have a user pauldy and you wish to change his password you create a MembershipUser then using the Membership class’s static method GetAllUsers() to retrieve a Collection of users indexed off the username and assign it to a MembershipUser like so
MembershipUser pauldy = Membership.GetAllUsers()["pauldy"];
It is pretty clear from the API there are two methods for reseting a users password. One of them ChangePassword requires you to know the old user password and lacks any overrides the other is ResetPassword which has an override that is the answer to a question he user supplies giving them the right to modify the user password and returns a random password. As a programmer I am a little interested in why there is no way to simply reset the password to a known value in an administrative fashion. There are methods to create a user with a known password or to delete users using the MembershipProvider but no direct method for simply reseting the password.
There is also a method for retrieving a Password using the GetPassword method that only works if you have the EnablePasswordRetrieval option set to true. Anyone who is evenly slightly security conscious is probably going to have that set to false.
The solution I have found i suboptimal as it hits the database with two writes for what should be just one but it does work. Because unlike most modifications to the MembershipUser the ResetPassword method actually modifies the user information when invoked you can change a users password to a known value by using the following statement.
String pass = "supersecretpass";
MembershipUser pauldy = Membership.GetAllUsers()["pauldy"];
pauldy.ChangePassword(pauldy.ResetPassword(), pass);
Now this effectively changes the password to some random foo generated by the ResetPassword method and uses its output as the current password for the ChangePassword method allowing you to set it to a known value. If anyone knows a better way to do this please post in the comments. The ultimate goal of me diving into this was in a user management app to place a button that allows a privileged user to reset the password of another user and not have them get a messy new password. So I created a function to generate random passwords and use it to make it easier on clients.
protected String genPassword(int genPassLength) {
String approvedCharList = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!$%&*?";
StringBuilder newPass = new StringBuilder();
Random random = new Random(DateTime.Now.Millisecond);
for (int x = 0; x < genPassLength; x++) {
newPass.Append(approvedCharList[random.Next(0, (approvedCharList.Length - 1))]);
}
return newPass.ToString();
}