Upgrading to ASP.NET 4.5/MVC 4 forms authentication fails - forms-authentication

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>

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

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

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.

Related

ASP.Net Membership Error CREATE DATABASE failed. Some file names listed could not be created. Check related errors

I am trying to add AP.Net membership to my database. I have had success with this in the past so I have some idea of what I am doing. My project is a VB.Net website with Framework 4.5.2. I used asp_regsql.exe in framework 4 to add the schema to my db. I created the following web.config entries (per MSDN articles):
<connectionStrings>
<add name="AFKMSConnectionString" providerName="System.Data.SqlClient" connectionString="working as intended" />
<system.web>
<authentication mode="Forms" >
<forms loginUrl="Account/Login.aspx"
name=".ASPXFORMSAUTH" />
</authentication>
<!--<authorization>
<deny users="?" />
</authorization>-->
<compilation debug="true" targetFramework="4.5.2"/>
<httpRuntime targetFramework="4.5.2"/>
<pages>
<namespaces>
<add namespace="System.Web.Optimization"/>
<add namespace="Microsoft.AspNet.Identity"/>
</namespaces>
<controls>
<add assembly="Microsoft.AspNet.Web.Optimization.WebForms" namespace="Microsoft.AspNet.Web.Optimization.WebForms" tagPrefix="webopt"/>
</controls>
</pages>
<membership defaultProvider="SqlMembershipProvider" userIsOnlineTimeWindow="15">
<providers>
<clear/>
<add
name="SqlMembershipProvider"
type="System.Web.Security.SqlMembershipProvider"
connectionStringName="AFKMSConnectionString"
applicationName="AFKMS"
enablePasswordRetrieval="false"
enablePasswordReset="true"
requiresQuestionAndAnswer="false"
requiresUniqueEmail="true"
passwordFormat="Hashed" />
</providers>
</membership>
<profile enabled ="true" defaultProvider="SqlProvider">
<providers>
<clear />
<add name="SqlProvider"
type="System.Web.Profile.SqlProfileProvider"
connectionStringName="AFKMSConnectionString"
applicationName="AFKMS"
description="SqlProfileProvider for SampleApplication" />
</providers>
</profile>
<roleManager enabled ="true"
defaultProvider ="SqlRoleProvider" >
<providers>
<clear/>
<add name ="SqlRoleProvider"
type="System.Web.Security.SqlRoleProvider"
connectionStringName="AFKMSConnectionString"
applicationName="AFKMS"/>
</providers>
</roleManager>
My connection string works for my current functions but when I try to register a user I get the following error:
Directory lookup for the file "C:\Users\Dan\Source\Repos\AFKMS\AFKMS\App_Data\aspnet-AFKMS-140073d4-6858-4f19-9555-0edfbaadd43a.mdf" failed with the operating system error 2(The system cannot find the file specified.).
CREATE DATABASE failed. Some file names listed could not be created. Check related errors.
This comes from Accounts/Register,
Dim result = manager.Create(user, Password.Text)
Why is it trying to create a database? What does it look like I am missing?
<connectionStrings>
<add name="AFKMSConnectionString" connectionString="data source=.;Initial Catalog=your_db_name;integrated security=True" providerName="System.Data.SqlClient" />
</connectionStrings>
can you provide us with code of how you create users?
you mentioned: Dim result = manager.Create(user, Password.Text)
i think you need to use:
Membership.CreateUser(UserName, Password, Email)
I'm assuming you've created a new ASP.NET Web Application, using the Web Forms templates?
In which case you appear to be attempting to configure the newer ASP.NET Identity system with the original Membership Provider configuration settings.
As Ahmed noted, you mention the call in the register page to manager.Create(user, Password.Text) - this is using the ApplicationUserManager from ASP.NET Identity.
If you look in the App_Start folder of your project, you should find a file named IdentityConfig.vb (assuming you're using VB.NET), which has a method Create that returns the ApplicationUserManager - this in turn calls the ApplicationDbContext class that is created in the Models folder, that will be defined to use a connection called "DefaultConnection" - by default this is set to be a standalone .mdf file in the App_Data folder named after the project.
You should change this to point at your connection string, but be aware that this uses Entity Framework to create the database schema for you - it should just add it to the existing database, but you should ensure you've backed it up before you start in case it drops everything first.

ASP.NET Universal Providers and Session State

I'm developing an ASP.NET MVC 4 website and I'm using the Microsoft ASP.NET Universal Providers. I plan to deploy to Windows Azure and use SQL Database. In order to initialize memberships, profiles and roles on my local SQL Server 2008 database, I created a new user via the ASP.NET Web Site Administration Tool. How do I initialize sessions?
When my application runs, naturally I get a SqlException saying "Invalid object name dbo.Sessions." When testing on Windows Azure, this wasn't an issue; dbo.Sessions was created automatically. I'm able to run locally after generating a create table script from dbo.Sessions on Azure and applying it to my local SQL database.
web.config:
<membership hashAlgorithmType="SHA1" defaultProvider="DefaultMembershipProvider">
<providers>
<clear />
<add name="DefaultMembershipProvider" type="System.Web.Providers.DefaultMembershipProvider" connectionStringName="DefaultConnection" enablePasswordRetrieval="false" enablePasswordReset="true" passwordFormat="Hashed" requiresQuestionAndAnswer="false" requiresUniqueEmail="true" maxInvalidPasswordAttempts="5" minRequiredPasswordLength="6" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10" applicationName="/" />
</providers>
</membership>
<profile enabled="false" defaultProvider="DefaultProfileProvider">
<providers>
<clear />
<add name="DefaultProfileProvider" type="System.Web.Providers.DefaultProfileProvider" connectionStringName="DefaultConnection" applicationName="/" />
</providers>
</profile>
<roleManager enabled="false" defaultProvider="DefaultRoleProvider">
<providers>
<clear />
<add name="DefaultRoleProvider" type="System.Web.Providers.DefaultRoleProvider" connectionStringName="DefaultConnection" applicationName="/" />
</providers>
</roleManager>
<sessionState mode="Custom" customProvider="DefaultSessionProvider">
<providers>
<add name="DefaultSessionProvider" type="System.Web.Providers.DefaultSessionStateProvider, System.Web.Providers" connectionStringName="DefaultConnection" applicationName="/" />
</providers>
</sessionState>
This article goes into more detail of the differences between the old aspnet_Memembership vs the Universal Providers.
http://dotnet.dzone.com/articles/stronger-password-hashing-net
The key points from the article:
Firstly, there’s no more aspnet_regsql, you just make sure your connection string is set and the account has DBO rights (don’t worry, it doesn’t have to stay this way) then run the app up and attempt to perform any action which should cause the membership provider to hit the DB (i.e. log on – it doesn't matter that there isn't an account).
Thats it all there is to it, when it works.
When you are using Microsoft ASP.NET Universal Providers to deploy to Windows Azure & SQL Database, it seems there could be some issue with your connection string as table on SQL Database is not created.
The blog below from Soctt shows steps by step details on how to do it so please follow and see what is missing:
Introducing System.Web.Providers - ASP.NET Universal Providers for Session, Membership, Roles and User Profile on SQL Compact and SQL Azure

Session timeout using Membership of ASP.Net in prod, not in dev environment

When I login to my webform in my production environment ( IIS 7.5 + SQL Server 2008), my session expires after just a few couple of seconds (less than 1 minute).
But when I do the same in my dev environment (ASP.Net Development Server + SQL Server 2008) the session is persistant long enough... (several minutes).
I use the ASP.Net membership technology with Forms authentication mode and try to use Cookies.
It look like something on the server is overriding my parameters, but I don't have access to the production IIS configuration (I subscribed to a shared hosting)
Here are my web.config parmeters:
<system.web>
<compilation debug="true" targetFramework="4.0">
<assemblies>
<add assembly="System.Data.Entity, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
</assemblies>
</compilation>
<authentication mode="Forms">
<forms loginUrl="~/Pages/Front/Login.aspx"
protection="All"
timeout="900"
path="/"
requireSSL="false"
slidingExpiration="true"
defaultUrl="~/Pages/Front"
cookieless="UseCookies"
name="MySite" />
</authentication>
<membership defaultProvider="AspNetSqlMembershipProvider">
<providers>
<clear />
<add name="AspNetSqlMembershipProvider"
type="System.Web.Security.SqlMembershipProvider, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
connectionStringName="XXX"
enablePasswordRetrieval="false"
enablePasswordReset="true"
requiresQuestionAndAnswer="true"
applicationName="/"
requiresUniqueEmail="false"
passwordFormat="Hashed"
maxInvalidPasswordAttempts="5"
minRequiredPasswordLength="5"
minRequiredNonalphanumericCharacters="0"
passwordAttemptWindow="10"
passwordStrengthRegularExpression=""/>
</providers>
</membership>
<roleManager enabled="true"
cookieName="booble.com"
cookieProtection="All"
cookieSlidingExpiration="true"
cookieTimeout="90"
createPersistentCookie="true"
cookieRequireSSL="false">
<providers>
<clear />
<add name="AspNetSqlRoleProvider" type="System.Web.Security.SqlRoleProvider" connectionStringName="XXX" applicationName="/" />
<!--<add name="AspNetWindowsTokenRoleProvider" type="System.Web.Security.WindowsTokenRoleProvider" applicationName="/" />-->
</providers>
</roleManager>
<sessionState timeout="90" />
<customErrors defaultRedirect="Error.aspx" mode="On" redirectMode="ResponseRewrite" >
<error statusCode="404" redirect="Error404.aspx"/>
</customErrors>
<!-- needed because of my Provider-->
<pages enableViewStateMac="false" />
<siteMap enabled="true" defaultProvider="AspNetXmlSiteMapProvider">
<providers>
<clear />
<add siteMapFile="Web.sitemap" name="AspNetXmlSiteMapProvider"
type="System.Web.XmlSiteMapProvider, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
securityTrimmingEnabled="true" />
</providers>
</siteMap>
</system.web>
Thanks a LOT in advance for your answers !
The problem was coming from my shared hosting provider, I contacted them in their help forum and on of their admin "changed" something on server-side, and now it works... they didn't want to tell me what they have modified.
FYI my shared hosting provider is named OVH.com, so if you have a session timeout problem (expiring every 30 sec to 1 min), even if you have configured your web.config correctly (to be sure,I even put my sessionState mode="SQLServer") , just contact them and they will do the necessary.
I'll post here if I get an explanation, thanks for your readings
Check if your session timeout is being set through code too.
<sessionState timeout="90" />
and
cookieTimeout="90"
Should have worked fine. Development servers are very forgiving about session timeouts.
Developement server doesn't represent a proper IIS 7 environment
This provides a convenient way to test your ASP.NET application
without IIS 7 - however, we recommend that you configure
Visual Studio to test your application by using the IIS 7 environment.
The reasons for this are: The ASP.NET Development Server does not
support hosting ASP.NET applications in Integrated mode, which is the
default mode of operation used by IIS 7. This may introduce
differences in application behavior.
Refer here

ASP.Net Browser Compatibility

If I use IE to connect to my ASP.Net site and let the browser sit idle for a minute or so and then try to click on a new item, link, whatever, IE appears as though it's trying to load but never does anything.
If I connect to the site using Chrome and do the same thing Chrome pulls up the next item as expected with no delay. I've tried making changes to the web.config for sessionState and httpRuntime, to the ASP and pool settings in IIS, and I can't seem to do anything that fixes the problem in IE.
Is there another setting somewhere, perhaps in Windows to fix IE as this seems to a browser dependent issue and not related to the ASP site or IIS? I'm running out of ideas and most of the users will be using IE and not Chrome so it's not really a problem I can ignore.
Here's my web.config file if it helps:
<?xml version="1.0"?>
<!--
For more information on how to configure your ASP.NET application, please visit
http://go.microsoft.com/fwlink/?LinkId=169433
-->
<configuration>
<connectionStrings>
<add name="ApplicationServices" connectionString="data source=.\SQLEXPRESS;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|\aspnetdb.mdf;User Instance=true" providerName="System.Data.SqlClient"/>
<add name="TaskSystemConnectionString" connectionString="Data Source=REPORTSERVER;Initial Catalog=TaskSystem;Integrated Security=True" providerName="System.Data.SqlClient"/>
</connectionStrings>
<system.web>
<sessionState timeout="3600"/>
<httpRuntime executionTimeout="3600" maxRequestLength="2000000"/>
<compilation debug="true" targetFramework="4.0"/>
<authentication mode="Windows" />
<customErrors mode="Off"/>
<membership>
<providers>
<clear/>
<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="/"/>
</providers>
</membership>
<profile>
<providers>
<clear/>
<add name="AspNetSqlProfileProvider" type="System.Web.Profile.SqlProfileProvider" connectionStringName="ApplicationServices" applicationName="/"/>
</providers>
</profile>
<roleManager enabled="false">
<providers>
<clear/>
<add name="AspNetSqlRoleProvider" type="System.Web.Security.SqlRoleProvider" connectionStringName="ApplicationServices" applicationName="/"/>
<add name="AspNetWindowsTokenRoleProvider" type="System.Web.Security.WindowsTokenRoleProvider" applicationName="/"/>
</providers>
</roleManager>
<pages controlRenderingCompatibilityVersion="3.5" clientIDMode="AutoID" validateRequest="false"/>
</system.web>
<system.webServer>
<defaultDocument>
<files>
<add value="Home.aspx"/>
</files>
</defaultDocument>
<modules runAllManagedModulesForAllRequests="true"/>
Could be something to do with database permissions. Have you tried specifying a SQL login in your connections strings? Can the account that is running IIS access these databases?
Also check your IIS settings to ensure that the authentication mode=Windows.
I have had issues with Windows authentication when i'm not using IE. For example, Chrome doesn't pass through the user identity and i have to enter my credentials each time i access the intranet.
So... after continued research and fiddling I found a Microsoft article that fixed the problem. Seems those special folks over at Microsoft decided a one minute timeout was an appropriate default... http://support.microsoft.com/kb/813827. Once I added the two necessary entries into the registry for KeepAliveTimeout and ServerInfoTimeout the problem went away.

Problems with NauckIT.PostgreSQLProvider

I have a problem with AspSQL Provider for PostgreSQL (http://dev.nauck-it.de/projects/aspsqlprovider).
When I try to create Roles with the ASP.NET Web Site Administration Tool this message keeps coming up:
There is a problem with your selected data store. This can be caused by an invalid server name or credentials, or by insufficient permission. It can also be caused by the role manager feature not being enabled. Click the button below to be redirected to a page where you can choose a new data store.
The following message may help in diagnosing the problem: exePath must be specified when not running inside a stand alone exe. (D:\Documents\Programming\Projects\Portal\web.config line 40)
Here is the web.config section:
<membership defaultProvider="PgMembershipProvider">
<providers>
<clear />
<add name="PgMembershipProvider" type="NauckIT.PostgreSQLProvider.PgMembershipProvider" connectionStringName="db" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" requiresUniqueEmail="false" maxInvalidPasswordAttempts="5" minRequiredPasswordLength="6" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10" applicationName="bp" />
</providers>
</membership>
<roleManager enabled="true" defaultProvider="PgRoleProvider" cacheRolesInCookie="true" cookieName=".AspNetRoles" cookiePath="/" cookieProtection="All" cookieRequireSSL="false" cookieSlidingExpiration="true" createPersistentCookie="false" cookieTimeout="30" maxCachedResults="25">
<providers>
<clear />
<add name="PgRoleProvider" type="NauckIT.PostgreSQLProvider.PgRoleProvider" connectionStringName="db" applicationName="bp" />
</providers>
</roleManager>
<profile enabled="true" defaultProvider="PgProfileProvider">
<providers>
<clear />
<add name="PgProfileProvider" type="NauckIT.PostgreSQLProvider.PgProfileProvider" connectionStringName="db" applicationName="bp" />
</providers>
<properties>
<add name="FirstName" />
<add name="LastName" />
</properties>
</profile>
<sessionState mode="Custom" customProvider="PgSessionStateStoreProvider">
<providers>
<clear />
<add name="PgSessionStateStoreProvider" type="NauckIT.PostgreSQLProvider.PgSessionStateStoreProvider" enableExpiredSessionAutoDeletion="true" expiredSessionAutoDeletionInterval="60000" enableSessionExpireCallback="false" connectionStringName="db" applicationName="bp" />
</providers>
</sessionState>
I followed the instruction Step By Step
Thanks in advance
Seems like HttpContext.Current can be null. The PgMembershipProvider class checks this to see if its hosted or not. Based on the answer, it attempts to either OpenExeConfiguration (for stand-alone) or OpenWebConfiguration for web hosted applications.
Since HttpContext.Current can be null sometimes in Asp.Net 4.0, the wrong decision is made and the OpenExeConfiguration is called from within a webapplication (big no-no). The fix is to change PgMembershipProvider.Init to use the following check:
Configuration cfg = HostingEnvironment.IsHosted ?
WebConfigurationManager.OpenWebConfiguration(HostingEnvironment.ApplicationVirtualPath) :
ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
instead of the HttpContext.Current != null check.
this bug was fixed in the 2.0.0 Version of the Provider.
See http://dev.nauck-it.de/issues/131
You can download the latest release via NuGet: https://nuget.org/packages/NauckIT.PostgreSQLProvider/

Resources