When your IIS 7.5 server returns HTTP 401 status codes but still delivers content, you're dealing with a particularly gnarly authentication issue. Here's what we observed:
HTTP/1.1 401 Unauthorized
Content-Type: text/html; charset=utf-8
Server: Microsoft-IIS/7.5
X-AspNetMvc-Version: 2.0
X-AspNet-Version: 4.0.30319
{full HTML content here}
First, verify these IIS settings:
<system.webServer>
<security>
<authentication>
<anonymousAuthentication enabled="true" />
<windowsAuthentication enabled="false" />
</authentication>
</security>
</system.webServer>
Check the application pool identity matches your content permissions:
# PowerShell verification
Import-Module WebAdministration
Get-ItemProperty 'IIS:\AppPools\YourAppPool' | Select-Object processModel
When Process Monitor shows FAST IO DISALLOWED
and PATH NOT FOUND
:
- This indicates IIS can't properly access the physical files
- Check both NTFS permissions and IIS application pool identity
The critical trace shows the 401 occurs during ManagedPipelineHandler execution. Try adding this to web.config:
<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
<remove name="FormsAuthentication" />
<remove name="UrlAuthorization" />
</modules>
</system.webServer>
For domain environments, add this registry setting on the server:
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa]
"DisableLoopbackCheck"=dword:00000001
Use this to test authentication requirements:
curl -v http://yourserver/app --negotiate -u :
- Verify application pool matches content permissions
- Check for double-hop authentication issues
- Disable kernel-mode caching temporarily
- Test with Failed Request Tracing enabled
When working with IIS 7.5 on Windows Server 2008 R2, encountering a 401 Unauthorized error that only manifests for remote clients (while working perfectly on localhost) suggests one of these scenarios:
1. Authentication inheritance conflicts
2. Double-hop authentication limitations
3. URL Authorization misconfiguration
4. Kernel-mode vs User-mode authentication differences
The fact that static content works while MVC routes fail points to handler-specific issues. These critical checkpoints need verification:
- Anonymous Authentication credentials (IUSR vs Application Pool Identity)
- Handler Mappings inheritance status
- HTTP Response Headers configuration
Your discovery that enabling Detailed Errors makes the application work reveals important clues:
<system.webServer>
<httpErrors errorMode="Detailed" />
</system.webServer>
This behavior suggests IIS is choking on custom error handling. The 401 might be getting generated during the error-handling phase rather than the initial request.
For .NET 4.0 MVC applications, verify these handler mappings in applicationHost.config
:
<handlers>
<add name="ExtensionlessUrlHandler-Integrated-4.0"
path="*."
verb="GET,HEAD,POST,DEBUG"
type="System.Web.Handlers.TransferRequestHandler"
preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
When dealing with Windows authentication across network hops:
// Web.config settings for explicit NTLM declaration
<system.web>
<authentication mode="Windows" />
<identity impersonate="false" />
</system.web>
The FR trace shows the ManagedPipelineHandler is generating the 401. This often indicates:
- Missing handler registration
- Incorrect .NET Framework version binding
- Application pool identity permissions
After troubleshooting dozens of similar cases, these solutions have consistently worked:
1. Reset IIS handlers:
%windir%\system32\inetsrv\appcmd set config /section:handlers /reset
2. Re-register ASP.NET:
aspnet_regiis.exe -iru
3. Explicitly deny the 401 status in web.config:
<httpErrors>
<remove statusCode="401" />
<error statusCode="401"
path="ErrorPages/401.htm"
responseMode="ExecuteURL" />
</httpErrors>
For Server 2008 R2 specifically, disable kernel-mode authentication for the problematic application:
appcmd set config "YourSite/YourApp" -section:system.webServer/security/authentication/anonymousAuthentication /kernelMode:false