Our team use Microsoft’s Membership Management Component Prototype for our users management in our application. We’ve wanted to add “forgot my password” screen, and our new member in our team, Dror(pay his blog a visit) was assigned for the mission. While trying to configure the MemberRoles component (in the web.config) to allow password retrieval, we’ve got a strange “bug”(\behavior); When we’ve tried to write this code:
<add name=“AspNetSqlProvider” type=“Microsoft.ScalableHosting.Security.SqlMembershipProvider, MemberRole, Version=184.108.40.206, Culture=neutral, PublicKeyToken=b7c773fb104e7562” connectionStringName=“wsha” enablePasswordRetrieval=“true” enablePasswordReset=“true” requiresQuestionAndAnswer=“false” requiresUniqueEmail=“false” minRequiredPasswordLength=“1” minRequiredNonalphanumericCharacters=“0” passwordFormat=“Hashed” applicationName=“test” description=“Stores and retrieves membership data from the local Microsoft SQL Server database” />
We’ve got a strange error “Configuration Error” (with unknown exception and other “helpful” details), and to make it even stranger, if you set the enablePasswordRetrieval to false, everything works well. So, like always, the first thing I do after I smack the keyboard (It works on my TV at home, why not here ?), I googled for solution (and publish it here, for higher PR ;-)) BUT this time – NO LUCK, I didn’t manage to find something helpful. I couldn’t thought about a better solution than to look at the source via Lutz Reflector so I’ve opened the dll there and checked MemberShipConfigHandler.Create(..) method; There I saw that this method creates an instance of SqlMembershipProvider and call it’s Initialize method with all the data from the web.config. There I found the answer:
if ((this.PasswordFormat == MembershipPasswordFormat.Hashed) && this.EnablePasswordRetrieval)
throw new Exception(“Configured settings are invalid: Hashed passwords can not be retrieved.
Either set the password format to different type, or set supportsPasswordRetrieval to false.”);
So, the error was that we’ve used passwordFormat=”Hashed” instead of “Clear” or “Encrypted”. Well, That’s making a lot of sense because the “Hashed” algorithm is implemented via SHA1, which is one-way encryption so obviously I can’t retrieve the user’s original password.
The real problem(and that’s why I’ve called this behavior a “bug”) is that somewhere in the way, the original helpful exception was caught and replaced with a really bad exception which doesn’t allow the programmer to understand what have he done wrong. This is a very good example of why it’s so important to keep the exception stack with you all the way up.
Back to code…