title: The user name or password provided is incorrect. in MVC 3 Internet Application
body: <p>I have a "<strong>Internet Application</strong>" - "<strong>A default ASP.NET MVC 3 project with an account controller that uses forms authentication.</strong>" called <strong>MyMv3App</strong>. I run the site in <strong>IIS Express</strong> using Ctrl + F5 and then I go to localhost:10382/Account/Register and I create a user "<strong>test1</strong>". Once the user is created I'm redirected to the Home page. I log off. Then I go to localhost:10382/Account/LogOn and type the username and password for the user "test1" and click on "Log On" button and the user is logged in. Cool, everything OK so far!</p>
  
  <p>Next I add a new <strong>C#</strong> "<strong>Class Library</strong>" project and I name it <strong>MyCustomMembershipProvider</strong>. Then I download the <strong>ProviderToolkitSamples.msi</strong> from here <a href="http://weblogs.asp.net/scottgu/archive/2006/04/13/442772.aspx" rel="nofollow">http://weblogs.asp.net/scottgu/archive/2006/04/13/442772.aspx</a>, run the msi installer, and go to the folder <strong>C:\Program Files (x86)\ASP.NET Provider Toolkit SQL Samples</strong> where all the files get installed. I then add these files to my C# Class Library project MyCustomMembershipProvider I just created, <strong>SQLMembershipProvider.cs</strong>, <strong>SecUtil.cs</strong>, <strong>SqlConnectionHelper.cs</strong> and <strong>SR.cs</strong>. (I need all these files or the C# Class Library project MyCustomMembershipProvider won't compile). Then I add a reference to <strong>System.configuration</strong>, <strong>System.Web</strong> and <strong>System.Web.ApplicationServices</strong> to the C# Class Library project MyCustomMembershipProvider. Then I build the project and then I go to MyMvc3App and
  I add a reference to the MyCustomMembershipProvider project.</p>
  
  <p>Note: Forgot to mention that I changed the namespace for all four files in the project 
  MyCustomMembershipProvider to "namespace MyCustomMembershipProvider" and also I renamed the class name to MyCustomMembershipProvider. And also in SQLMembershipProvider.cs line 110 I changed it from name = "SqlMembershipProvider"; to name = "MyCustomMembershipProvider";</p>
  
  <p>Next I change the web.config file membership section from this:</p>
  
  <pre class="lang-xml prettyprint-override"><code>&lt;membership&gt;
        &lt;providers&gt;
          &lt;clear/&gt;
          &lt;add name="AspNetSqlMembershipProvider" type="System.Web.Security.SqlMembershipProvider" connectionStringName="ApplicationServices"
               enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" requiresUniqueEmail="false"
               maxInvalidPasswordAttempts="5" minRequiredPasswordLength="6" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10"
               applicationName="/" /&gt;
        &lt;/providers&gt;
      &lt;/membership&gt;
  </code></pre>
  
  <p>to this:</p>
  
  <pre class="lang-xml prettyprint-override"><code>&lt;membership defaultProvider="MyCustomMembershipProvider"&gt;
        &lt;providers&gt;
          &lt;clear/&gt;
          &lt;add name="MyCustomMembershipProvider" type="MyCustomMembershipProvider.MyCustomMembershipProvider" connectionStringName="ApplicationServices"
               enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" requiresUniqueEmail="false"
               maxInvalidPasswordAttempts="5" minRequiredPasswordLength="6" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10"
               applicationName="/" /&gt;
        &lt;/providers&gt;
      &lt;/membership&gt;
  </code></pre>
  
  <p>The entire web.config looks like this now:</p>
  
  <pre class="lang-xml prettyprint-override"><code>&lt;?xml version="1.0"?&gt;
  &lt;!--
    For more information on how to configure your ASP.NET application, please visit
    http://go.microsoft.com/fwlink/?LinkId=152368
    --&gt;
  
  &lt;configuration&gt;
    &lt;connectionStrings&gt;
      &lt;add name="ApplicationServices"
           connectionString="data source=.\SQLEXPRESS;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|aspnetdb.mdf;User Instance=true"
           providerName="System.Data.SqlClient" /&gt;
    &lt;/connectionStrings&gt;
  
    &lt;appSettings&gt;
      &lt;add key="webpages:Version" value="1.0.0.0"/&gt;
      &lt;add key="ClientValidationEnabled" value="true"/&gt;
      &lt;add key="UnobtrusiveJavaScriptEnabled" value="true"/&gt;
    &lt;/appSettings&gt;
  
    &lt;system.web&gt;
      &lt;compilation debug="true" targetFramework="4.0"&gt;
        &lt;assemblies&gt;
          &lt;add assembly="System.Web.Abstractions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" /&gt;
          &lt;add assembly="System.Web.Helpers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" /&gt;
          &lt;add assembly="System.Web.Routing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" /&gt;
          &lt;add assembly="System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" /&gt;
          &lt;add assembly="System.Web.WebPages, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" /&gt;
        &lt;/assemblies&gt;
      &lt;/compilation&gt;
  
      &lt;authentication mode="Forms"&gt;
        &lt;forms loginUrl="~/Account/LogOn" timeout="2880" /&gt;
      &lt;/authentication&gt;
  
      &lt;membership defaultProvider="MyCustomMembershipProvider"&gt;
        &lt;providers&gt;
          &lt;clear/&gt;
          &lt;add name="MyCustomMembershipProvider" type="MyCustomMembershipProvider.MyCustomMembershipProvider" connectionStringName="ApplicationServices"
               enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" requiresUniqueEmail="false"
               maxInvalidPasswordAttempts="5" minRequiredPasswordLength="6" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10"
               applicationName="/" /&gt;
        &lt;/providers&gt;
      &lt;/membership&gt;
  
      &lt;profile&gt;
        &lt;providers&gt;
          &lt;clear/&gt;
          &lt;add name="AspNetSqlProfileProvider" type="System.Web.Profile.SqlProfileProvider" connectionStringName="ApplicationServices" applicationName="/" /&gt;
        &lt;/providers&gt;
      &lt;/profile&gt;
  
      &lt;roleManager enabled="false"&gt;
        &lt;providers&gt;
          &lt;clear/&gt;
          &lt;add name="AspNetSqlRoleProvider" type="System.Web.Security.SqlRoleProvider" connectionStringName="ApplicationServices" applicationName="/" /&gt;
          &lt;add name="AspNetWindowsTokenRoleProvider" type="System.Web.Security.WindowsTokenRoleProvider" applicationName="/" /&gt;
        &lt;/providers&gt;
      &lt;/roleManager&gt;
  
      &lt;pages&gt;
        &lt;namespaces&gt;
          &lt;add namespace="System.Web.Helpers" /&gt;
          &lt;add namespace="System.Web.Mvc" /&gt;
          &lt;add namespace="System.Web.Mvc.Ajax" /&gt;
          &lt;add namespace="System.Web.Mvc.Html" /&gt;
          &lt;add namespace="System.Web.Routing" /&gt;
          &lt;add namespace="System.Web.WebPages"/&gt;
        &lt;/namespaces&gt;
      &lt;/pages&gt;
    &lt;/system.web&gt;
  
    &lt;system.webServer&gt;
      &lt;validation validateIntegratedModeConfiguration="false"/&gt;
      &lt;modules runAllManagedModulesForAllRequests="true"/&gt;
    &lt;/system.webServer&gt;
  
    &lt;runtime&gt;
      &lt;assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"&gt;
        &lt;dependentAssembly&gt;
          &lt;assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" /&gt;
          &lt;bindingRedirect oldVersion="1.0.0.0-2.0.0.0" newVersion="3.0.0.0" /&gt;
        &lt;/dependentAssembly&gt;
      &lt;/assemblyBinding&gt;
    &lt;/runtime&gt;
  &lt;/configuration&gt;
  </code></pre>
  
  <p>Now I do the exact same thing I did in the first paragraph; I go to localhost:10382/Account/Register and I create a user, this time I call the user
  "<strong>test2</strong>". Once the user is created I'm redirected to the Home page. I log off. Then I go to
  localhost:10382/Account/LogOn to log in again and type the username and password for the user "<strong>test2</strong>" and click on "Log On" button and I get the error message:</p>
  
  <p><strong>Login was unsuccessful. Please correct the errors and try again.
  The user name or password provided is incorrect.</strong></p>
  
  <p>Why? What did I miss? I haven't touched anything besides the namespace and that <strong>name</strong> variable in SQLMembershipProvider.cs in line 110. </p>
  
  <p>I tried to understand why so I googled and found that adding the machineKey element might work. So I went to this site <a href="http://www.developmentnow.com/articles/machinekey_generator.aspx" rel="nofollow">http://www.developmentnow.com/articles/machinekey_generator.aspx</a> and generated a ASP.NET 2.0 machineKey and copy pasted it into web.config's system.web element:</p>
  
  <pre class="lang-xml prettyprint-override"><code>&lt;machineKey
          validationKey="A5E72C3BF96D34B9401278890361AA0949EAE806B124573AC3C1A8D77936B4E42BB1374D1DA443706C4E575B7F1234CB48F4CF52444CB4B1F343994752416569"
          decryptionKey="47869B2D1F1D3EBC92FCC4C2D7B0EFB707535925E116AEF85F470E138A6C8CB5"
          validation="SHA1" decryption="AES"
  /&gt;
  </code></pre>
  
  <p>I once again did the exact same thing as before; I go to localhost:10382/Account/Register and I create a user, I'm calling the user "<strong>test3</strong>" this time. Once the user is created I'm redirected to the Home page. I log off. Then I go to localhost:10382/Account/LogOn and type the username and password for the user "<strong>test3</strong>" and click on "Log On" button and BAM! the user is once again logged in!?</p>
  
  <p>Why did I have to manually configure a machineKey with a generated validationKey and decryptionKey in web.config for the MyCustomMembershipProvider to be able to work with the login page? As far as I have seen there is not a single article / page / blog that talks about adding a machineKey element to your web.config for your custom membership provider to be able to work!</p>
  
  <p><strong>UPDATE 1</strong>: Adding hashAlgorithmType="SHA1" works as well: </p>
  
  <pre class="lang-xml prettyprint-override"><code>&lt;membership defaultProvider="MyCustomMembershipProvider" hashAlgorithmType="SHA1"&gt;
  </code></pre>
  
  <p>Funny thing though is that MSDN says SHA1 is the default!?</p>
  
  <p>hashAlgorithmType
  Optional String attribute.
  Specifies the name of the encryption algorithm that is used to hash password values.
  The value of this attribute corresponds to the name attribute of a nameEntry element in the cryptoNameMapping configuration section. For information about specifying a custom hash algorithm, see Mapping Algorithm Names to Cryptography Classes.
  <strong>The default is SHA1</strong>.</p>
  
  <p><strong>UPDATE 2</strong>:
  After reading up on Microsoft latest technologies I decided to share some of the findings I discovered regarding their latest Mebership provider; SimpleMembership. I'm at the stage in my personal project where I've decided to drop the CustomMembershipProvider from the ASP.NET 2.0 days I built and use SimpleMembership provider instead. Why? Well you have all the info you'll ever want to know in the following blogpost by Jon Galloway. I'm also adding some more links to resources worth checking out. According to Microsoft SimpleMembership is the successor to ASP.NET 2.0 Membership.</p>
  
  <p><a href="http://weblogs.asp.net/jgalloway/archive/2012/08/29/simplemembership-membership-providers-universal-providers-and-the-new-asp-net-4-5-web-forms-and-asp-net-mvc-4-templates.aspx" rel="nofollow">http://weblogs.asp.net/jgalloway/archive/2012/08/29/simplemembership-membership-providers-universal-providers-and-the-new-asp-net-4-5-web-forms-and-asp-net-mvc-4-templates.aspx</a></p>
  
  <p><a href="http://mvccentral.net/Story/Details/tools/kahanu/securityguard-nuget-package-for-asp-net-membership" rel="nofollow">http://mvccentral.net/Story/Details/tools/kahanu/securityguard-nuget-package-for-asp-net-membership</a></p>
  
  <p><a href="http://blog.longle.net/2012/09/25/seeding-users-and-roles-with-mvc4-simplemembershipprovider-simpleroleprovider-ef5-codefirst-and-custom-user-properties/" rel="nofollow">http://blog.longle.net/2012/09/25/seeding-users-and-roles-with-mvc4-simplemembershipprovider-simpleroleprovider-ef5-codefirst-and-custom-user-properties/</a></p>
  
  <p><a href="http://blog.osbornm.com/archive/2010/07/21/using-simplemembership-with-asp.net-webpages.aspx" rel="nofollow">http://blog.osbornm.com/archive/2010/07/21/using-simplemembership-with-asp.net-webpages.aspx</a></p>
  
  <p><a href="http://blogs.msdn.com/b/rickandy/archive/2012/08/15/initializesimplemembership-attribute-and-simplemembership-exceptions.aspx" rel="nofollow">http://blogs.msdn.com/b/rickandy/archive/2012/08/15/initializesimplemembership-attribute-and-simplemembership-exceptions.aspx</a></p>