We are seeing some Safari browsers failing to cross-authenticate our website after we upgrade to .NET 4.0 from .NET 3.5.
After much investigation, it turns out to be a problem with ASP.NET identifying the Safari browsers properly. ASP.NET identifies some Safari (possibly other WebKit-based browsers) as Mozilla Version 0.0. browsers that do not support cookies, frames, JavaScript, etc. .NET 3.5 does not have any problems identifying these browsers.
We have simplified testing down to a simple HTTP handler (running on a vanilla 4.0 website) that only returns the browser capabilities of the requestor.
Here are a few User-Agents that fail to be identified (they are identified as Mozilla 0.0):
Mozilla/5.0+(Macintosh;+U;+Intel+Mac+OS+X+10_5_8;+en-us)+AppleWebKit/533.19.4+(KHTML,+like+Gecko)+Version/5.0.3+Safari/533.19.4
Mozilla/5.0+(Macintosh;+U;+Intel+Mac+OS+X+10_6_2;+en-us)+AppleWebKit/531.9+(KHTML,+like+Gecko)
Mozilla/5.0+(Macintosh;+U;+Intel+Mac+OS+X+10_6_7;+en-us)+AppleWebKit/533.20.25+(KHTML,+like+Gecko)+Version/5.0.4+Safari/533.20.27
Mozilla/5.0+(Macintosh;+U;+Intel+Mac+OS+X+10_6_6;+en-us)+AppleWebKit/533.18.1+(KHTML,+like+Gecko)
The handler code looks like this:
<%@ WebHandler Language="C#" Class="PowershellTemporaryHandler" %>
using System;
using System.Web;
using System.Web.Security;
public class PowershellTemporaryHandler : IHttpHandler
{
public bool IsReusable
{
get { return true; }
}
public void ProcessRequest(HttpContext context)
{
HttpBrowserCapabilities hbc = context.Request.Browser;
context.Response.Write("Type=" + hbc.Type + "<br>");
context.Response.Write("Name=" + hbc.Browser + "<br>");
context.Response.Write("Version=" + hbc.Version + "<br>");
context.Response.Write("Major Version=" + hbc.MajorVersion + "<br>");
context.Response.Write("Minor Version=" + hbc.MinorVersion + "<br>");
context.Response.Write("Platform=" + hbc.Platform + "<br>");
context.Response.Write("Is Beta=" + hbc.Beta + "<br>");
context.Response.Write("Is Crawler=" + hbc.Crawler + "<br>");
context.Response.Write("Is AOL=" + hbc.AOL + "<br>");
context.Response.Write("Is Win16=" + hbc.Win16 + "<br>");
context.Response.Write("Is Win32=" + hbc.Win32 + "<br>");
context.Response.Write("Supports Tables=" + hbc.Tables + "<br>");
context.Response.Write("Supports cookies=" + hbc.Cookies + "<br>");
context.Response.Write("Supports VBScript=" + hbc.VBScript + "<br>");
context.Response.Write("Supports Frames=" + hbc.Frames + "<br>");
context.Response.Write("Supports JavaScript=" + hbc.EcmaScriptVersion.ToString() + "<br>");
context.Response.Write("Supports Java Applets=" + hbc.JavaApplets + "<br>");
context.Response.Write("Supports ActiveX Controls=" + hbc.ActiveXControls + "<br>");
context.Response.Write("User Agent=" + context.Request.UserAgent + "<br>");
}
}
We are bewildered as to the lack of mention on the Internet about this problem. It seems that we need to add Browser defintions either to the framework/config/browsers folder or else to the App_Browsers folder at the website level, but it seems bizarre that we would need to tweak Browser definitions for a .NET 4.0 website to run properly.
Does anyone have any experience with this issue?
I have been running into what seems to be a similar issue. It seems that ideed some Safari user agents are not properly recognized and instead reported as Mozilla 0.0, BUT some investigation showed me that this failure is not exactly reproducible. If I use my Firefox's UserAgent-Switcher to send the exact same user agent that previously failed to be recognized and take a look at the browser capabilities, it is correctly reported as a Safari. Going through the server log files (after adding some debug information) also seems to confirm this behavior. The very same client with the very same (Safari) user agent is sometimes recognized correctly and occasionally reported as Mozilla 0.0 - most of the time it is incorrectly recognized a couple of times in a row before it gets it right again... It only seems to affect Safari user agents - if anybody is interested, I have a rather long list, the most recent one being:
- |Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_2_1 like Mac OS X; de-de) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8C148 Safari/6533.18.5|
Does anybody have more information on this issue?
EDIT 2011-08-24
It seems that I have found the root cause of the problem. The UserAgent -> BrowserCaps resolving mechanism uses a cache to temporarily store mappings. Unfortunately it uses (by default) the first 64 characters of the UserAgent string as cache key and THAT is just BS... Occasionally a user agent pops up that looks like a Safari, but really isn't and that one is not resolved properly (Mozilla 0.0), but the mapping is still stored in the cache, which means that all UserAgent strings with the same 64 character prefix are now incorrectly mapped as well until that cache entry expires (sliding window with 1 minute). The key length used for caching can fortunately be configured with
<browserCaps userAgentCacheKeyLength="..." />
in the config section. I've upped the key length to 256 and since that the problem has disappeared. Now I'll try to figure out which UserAgent string was responsible for the cache poisoning in the firs place - and I'll update this post if I find anything.
Solution
I put the <browserCaps userAgentCacheKeyLength='256'>
element under <system.web>
and everything appears to work, as follows:
<configuration>
<system.web>
<browserCaps userAgentCacheKeyLength="256" />
</system.web>
</configuration>
Detailed explanation
The 'Browser capabilities user agent cache key length' resolving mechanism uses a cache to temporarily store mappings.
By default it uses the first 64 characters of the UserAgent string as cache key, however when a user agent pops up that looks like it belongs to Safari, but really isn't does not resolve properly i.e. 'Mozilla 0.0'
The mapping is stored in the cache, which means that all UserAgent strings with the same 64 character prefix are now incorrectly mapped until the cache entry expires i.e. usually 1 minute.
The key length used for caching is configured using the following:
Increase the key length to 256 to resolve the problem.
...I had problems finding the correct place in my web.config file to insert the above.
When I inserted the <browserCaps userAgentCacheKeyLength="..." />
element directly under <configuration>
in my web.config file, my web-application immediately crashed.
Fortunately, this happened in the test environment and not in production environment.
After searching online, I found an old MSDN / ASP .NET reference page (http://msdn.microsoft.com/en-us/library/sk9az15a%28v=vs.71%29.aspx) that suggested that the <broswerCaps>
element is a child of <system.web>
.
I tried all answers from this thread, but for the User Agent from the IPhone 4S:
Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3 like Mac OS X; de-de) AppleWebKit/533.17.9 (KHTML, like Gecko) Mobile/8F190
It still went wrong. Eventually I used the ClientTarget property with the value "uplevel" to force ASP.NET to always enable new browser features. I've put this in a base class that all pages inherit from.
See: http://msdn.microsoft.com/en-us/library/system.web.ui.page.clienttarget.aspx
I highly recommend that you consider leveraging the following:
http://aspnet.codeplex.com/releases/view/41420