I have an MVC 4 website where a user can log in and I save a cookie with session information, so they don’t need to log in again.
public void SetCookie(HttpCookie cookie) { HttpContext.Current.Response.Cookies.Set(cookie); }
This works on desktop devices, but when I run it on iOS, it does not work 100% of the time. If you leave at least 1 page in your mobile phone’s browser (Chrome or Safari) and then return to my site, my session cookie will be found and I won’t need to log in. But if I close ALL the windows of this browser, then the next time I return to my site, the session cookie will not be found. I set 1 year duration / expiration on my cookie so that it does not expire.
The only thing I have found so far is a bug in .NET 4.0 and fixed in .NET 4.5. I believe that I am already running .NET 4.5 by looking at my * .csproj and the TargetFrameworkVersion element:
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> <PropertyGroup> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> <ProductVersion> </ProductVersion> <SchemaVersion>2.0</SchemaVersion> <ProjectGuid>{xxxxxxxxxxxxxxxxxx}</ProjectGuid> <ProjectTypeGuids>{xxxxxxxx};{xxxxxxxxxxxxx};{xxxxxxxxxxxxxxxx}</ProjectTypeGuids> <OutputType>Library</OutputType> <AppDesignerFolder>Properties</AppDesignerFolder> <RootNamespace>MyApp</RootNamespace> <AssemblyName>MyApp</AssemblyName> <TargetFrameworkVersion>v4.5</TargetFrameworkVersion> <MvcBuildViews>false</MvcBuildViews> <UseIISExpress>true</UseIISExpress> <IISExpressSSLPort /> <IISExpressAnonymousAuthentication /> <IISExpressWindowsAuthentication /> <IISExpressUseClassicPipelineMode /> </PropertyGroup>
Is this a bug with .NET (or MVC), or is it my coding? Do I need to upgrade to MVC 5 (instead of the original recommendation for upgrading to .NET 4.5)?
This really bothered me, since most of the traffic to my site in the coming months will be from mobile users, and I will probably lose some of them if they log at any time (I know that I hate having to connect to a mobile device ...)
Edit:
Btw is another page on the same topic: ASP.Net Form Authentication Using iPhone UIWebView
And I also tried to implement this, and it didn't work either:
http://www.bloggersworld.com/index.php/asp-net-forms-authentication-iphone-cookies/
And the above includes Scott Hanselman proposing a fix:
http://www.hanselman.com/blog/FormsAuthenticationOnASPNETSitesWithTheGoogleChromeBrowserOnIOS.aspx
Here is my cookie creation code if it helps:
private void CreateAndSetAuthenticationCookie(int loginId, string username) { HttpCookie cookie = CreateAuthenticationCookie(loginId, username); _cookieService.SetCookie(cookie); } private HttpCookie CreateAuthenticationCookie(int loginId, string username) { string userData = string.Format("loginId:{0},username:{1}", loginId, username); var ticket = new FormsAuthenticationTicket(loginId, username, DateTime.Now, DateTime.Now.AddYears(1), false, userData, FormsAuthentication.FormsCookiePath); string encryptedTicket = FormsAuthentication.Encrypt(ticket); return new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket); }
One thing I pointed out in my comments, I have a "PersistentCookie" set to false. Not sure if it matters, I will do more research.
Update:
First of all, PersistentCookie is now true, and this has not changed the behavior.
One of the commentators below suggested that I run Fiddler when accessing the website from the iPhone. After going through very short and easy steps to get this setting, this is what I learned.
The first request I tried indicated (I believe) what the actual problem is. When I reviewed this first request, iOS Safari sends a DNT header. Having no idea what it was, I looked at it and the “Do Not Track” heading.
Then I went and checked the Safari settings to disable this. Guess what, it's already off. Why the hell is Safari (iOS) sending a DNT header when (Settings → Safari → Do Not Track) is not set? In addition, Block Cookies, which is located directly below it, is set to Never.
After I was disappointed with this, I went to check Chrome on iOS to make sure that this still does not work. IT IS WORKING! From what I can say, I would close all the tabs, try again, close all the tabs, and then kill the browser and it still works. Hurrah!
Now I need to find out why iOS Safari sends a DNT header ...