Upgrading to ASP.NET 4.5/MVC 4 forms authentication fails
Asked Answered
S

3

15

I've just downoaded a VS 2012 along with ASP.NET 4.5 and MVC 4.0 and was kicking the tires with a sample app and found that the forms authentication that works perfectly with ASP.NET 4.0/MVC 3 no longer seems to work with the latest release.

When I make a call to the Login function in the action controller, the WebSecurity.Login call fails:

public ActionResult Login(LoginModel model, string returnUrl)
{
    if (ModelState.IsValid && WebSecurity.Login(model.UserName, model.Password, persistCookie: model.RememberMe))
    {
        return RedirectToLocal(returnUrl);
    }

    // If we got this far, something failed, redisplay form
    ModelState.AddModelError("", "The user name or password provided is incorrect.");
    return View(model);
}

I've replaced this code with the equivalent in my VS 2010 source, and that also fails (using the now deprecated FormsAuthentication.Authenticate function).

My question is: Has anybody ported a MVC3 to MVC4 app and found a workaround to this issue? I'm using IIS Express, so I guess that may be causing some problem somehow, but if you have any ideas, I'd appreciate it.

I copied my configuration from my working asp.net 4/MVC3 app as follows, but no luck (here's the relevant parts):

  <connectionStrings>
    <add name="DefaultConnection" connectionString="Data Source=tcp:sql2k1201.dbprovider.net;Initial Catalog=SQL2012_db;User ID=SQL2012_db_user;Password=dbpassword;" providerName="System.Data.SqlClient" />
  </connectionStrings>

  <system.web>
    <compilation debug="true" targetFramework="4.5" />
    <httpRuntime targetFramework="4.5" />

    <authentication mode="Forms">
      <forms loginUrl="~/Account/Login" timeout="2880"/>
    </authentication>

    <membership>
      <providers>
        <clear/>
        <add name="AspNetSqlMembershipProvider" type="System.Web.Security.SqlMembershipProvider" connectionStringName="DefaultConnection"
           enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" requiresUniqueEmail="false"
           maxInvalidPasswordAttempts="5" minRequiredPasswordLength="6" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10"
           applicationName="/" />
      </providers>
    </membership>

    <profile>
      <providers>
        <clear/>
        <add name="AspNetSqlProfileProvider" type="System.Web.Profile.SqlProfileProvider" connectionStringName="DefaultConnection" applicationName="/" />
      </providers>
    </profile>

    <roleManager enabled="true">
      <providers>
        <clear/>
        <add name="AspNetSqlRoleProvider" type="System.Web.Security.SqlRoleProvider" connectionStringName="DefaultConnection" applicationName="/" />
      </providers>
    </roleManager>
Sealed answered 18/8, 2012 at 20:3 Comment(0)
L
3

The issue here is that the default mvc4 internet template is using SimpleMembership to manage membership/roles information. The code in the template has assumption of this and can only work with simplemembership. When you install universal providers the account controller code blows up since it cannot understand universal providers. Look at this post which explains further on this scenario 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

Lunitidal answered 30/8, 2012 at 16:46 Comment(1)
Pranav - thanks for pointing out that article. I noticed that loads of comments about the article mentioned that the new providers were anything but simple, and there is no smooth migration path if you want to convert existing membership/roles to the new schema. It seems to me while they may have tried to simplify a complex system, they have made it more so, and just trying out the new stuff by making a quick change to the web.config results in new tables that don't work with the prior setup. I have more to learn about this for sure!Sealed
S
36

If your forms authentication ticket needs to be shared between applications using an older version of the .NET framework, you must explicitly configure your .NET 4.5 apps to use the earlier machine compatibility modes, or they will not be able to encrypt/decrypt the forms authentication ticket.

In your .net 4.5 application's web.config, set the compatibility mode attribute:

<system.web>
 <machineKey compatibilityMode="Framework20SP2" /> 
</system.web>

This will allow your .NET 4.5 apps to work with forms authentication tickets generated by earlier .NET versions.

Note: If any of your servers do not have .NET Framework 2.0 SP2 installed, you will need to set the compatibility mode to "Framework20SP1" instead.

MSDN - MachineKeySection.CompatibilityMode Property

Sortilege answered 21/8, 2012 at 18:43 Comment(5)
James - I tried your suggestion just now and it doesn't seem to make any difference, and I can't log in. Do you think it has anything to do with IIS Express?Sealed
This setting applies for both IIS and IIS Express. Since you're sharing the forms auth ticket, you could try the following settings as well <add key="enableSimpleMembership" value="false" /> and <add key="autoFormsAuthentication" value="false" /> under <appSettings>.Sortilege
James, thank you so much - you have solved my problem in this question #11533243Appomattox
Thanks - we were integrating two .NET 4.5 applications on the same server, but kept on getting "Forms authentication failed for the request. Reason: The ticket supplied was invalid.". Seems something in one of the applications is causing it to be treated like a non 4.5 app.Catholicize
@JamesH I have been looking all over for this solution. I am using a webforms asp.net 4.0 login and my new MVC applications had the httpRuntime target framework set to 4.5.1 by default. Added compatibilityMode to the machineKey fix it. Thank you so much! +1Claro
L
3

The issue here is that the default mvc4 internet template is using SimpleMembership to manage membership/roles information. The code in the template has assumption of this and can only work with simplemembership. When you install universal providers the account controller code blows up since it cannot understand universal providers. Look at this post which explains further on this scenario 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

Lunitidal answered 30/8, 2012 at 16:46 Comment(1)
Pranav - thanks for pointing out that article. I noticed that loads of comments about the article mentioned that the new providers were anything but simple, and there is no smooth migration path if you want to convert existing membership/roles to the new schema. It seems to me while they may have tried to simplify a complex system, they have made it more so, and just trying out the new stuff by making a quick change to the web.config results in new tables that don't work with the prior setup. I have more to learn about this for sure!Sealed
F
2

For me, I had an issue because there are some changes to the web.config settings you need (from http://www.asp.net/whitepapers/mvc4-release-notes)

<appSettings>
  <add key="webpages:Version" value="2.0.0.0" />
  <add key="PreserveLoginUrl" value="true" />
</appSettings>

Fixing these settings (which it doesn't look like you've added) got things working for me when I had login issues.

Forecourse answered 19/8, 2012 at 23:6 Comment(3)
The web.config I included was only a snippet that had the changes I added for forms authentication. The key/values you have above are in the default web.config, and I didn't remove them (there in my full web.config). Thanks for responding, though.Sealed
I was just looking over the call to 'WebSecurity.InitializeDatabaseConnection("DefaultConnection", "UserProfile", "UserId", "UserName", autoCreateTables: false);' and looked at the "UserProfile" table in my DB and it was empty. Did they change the schema? When I go to the "ASP.net web site configuration" tool, it shows my users, but the app still will not allow me to login.Sealed
Thanks... PreserveLoginUrl was the key for my problem. Login was working fine but when using [Authorize(Roles="admin")] it was failing.Pest

© 2022 - 2024 — McMap. All rights reserved.