I know that there are thousands of reports of people having trouble getting Integrated Windows Authentication to work with IIS, but they all seem to lead to web pages that don't apply or solutions that I've already tried. I've deployed dozens of sites like this before, so either there's something bizarre going on with the server/configuration, or I've been looking at this too long and not seeing the obvious.
Simply put, everything works perfectly on my local machine, but falls apart on the production server, which as far as I can tell has the exact same configuration.
On the local machine:
- The machine is running Windows 7 Ultimate, Service Pack 1, IIS 7.5.
- The site has been tested successfully, using both IIS and the VS Web Development Server.
- The IIS site config has all authentication methods disabled except Windows Authentication.
- The local machine is not on any domain.
- The Providers set up are Negotiate and NTLM (not Negotiate:Kerberos).
- Extended Protection is Off.
- All browsers tested (IE, Firefox, Chrome) show the challenge prompt and allow me to log in to the localhost domain with my (local) Windows account.
- All browsers tested also work using an opaque local IP address - so the browsers themselves don't seem to care whether the site appears "local" or "remote".
- I've added a display line to the web page which shows the currently-logged-in user and it shows exactly what I would expect (whichever local user I logged in with).
On the remote machine:
- The server is running Windows Server 2008 R2, IIS 7.5.
- Loading the web page results in an immediate 401.2 error: You are not authorized to view this page due to invalid authentication headers. No challenge prompt ever appears.
- The IIS site config has all authentication methods disabled except Windows Authentication.
- The remote machine is not on any domain.
- The Providers set up are Negotiate and NTLM (not Negotiate:Kerberos).
- Extended Protection is Off.
- On the remote machine (remote desktop session), the same error appears in Internet Explorer regardless of whether the domain is localhost or the external IP address.
- If I try to view the remote web site from my local machine, the error is still 401, but a slightly different 401. No subcode, with the text: Access is denied due to invalid credentials.
- The Windows Authentication IIS role feature is installed.
- The WindowsAuthentication Module is added (at the Server level).
- The exact same error occurs if I turn off Windows Authentication and enable Basic Authentication.
- The site does load if I turn off Windows Authentication and enable Anonymous (obviously).
- I've already followed all of the troubleshooting steps on Microsoft Support: Troubleshooting HTTP 401 errors in IIS
- I've already tried the workaround shown on another Microsoft support page (supposedly to force NTLM as the only method).
Last but not least, I tried turning on FREB for 401.2 errors and the results don't seem to tell me anything useful, all I see is the following warning:
MODULE_SET_RESPONSE_ERROR_STATUS
ModuleName IIS Web Core
Notification 2
HttpStatus 401
HttpReason Unauthorized
HttpSubStatus 2
ErrorCode 2147942405
ConfigExceptionInfo
Notification AUTHENTICATE_REQUEST
ErrorCode Access is denied. (0x80070005)
...this seems to just be telling me what I already know (that it's simply rejecting the request instead of negotiating the credentials).
The trace does indicate that the WindowsAuthentication module is correctly loaded because there is a NOTIFY_MODULE_START
line with ModuleName
= WindowsAuthentication
(and various other ASP.NET follow-up events - [un]fortunately, no interesting errors or warnings here).
Can anyone tell me what I might be missing here?
Quick Update:
I'm a little uncomfortable sending a whole Wireshark dump as it would reveal IPs, URLs and other stuff, but I did a side-by-side comparison of the HTTP responses from localhost and the remote server in Fiddler, and it seems fairly self-evident what the problem is:
Localhost:
HTTP/1.1 401 Unauthorized Cache-Control: private Content-Type: text/html; charset=utf-8 Server: Microsoft-IIS/7.5 WWW-Authenticate: Negotiate WWW-Authenticate: NTLM X-Powered-By: ASP.NET Date: Sat, 17 Dec 2011 23:42:34 GMT Content-Length: 6399 Proxy-Support: Session-Based-Authentication
Remote:
HTTP/1.1 401 Unauthorized Content-Type: text/html Server: Microsoft-IIS/7.5 X-Powered-By: ASP.NET Date: Sat, 17 Dec 2011 23:43:13 GMT Content-Length: 1293
Aside from a few seemingly-inconsequential differences like cache-control, the main difference is that the remote server is not sending the WWW-Authenticate headers back to the client.
So, I guess that narrows the question down to: Why is IIS not sending WWW-Authenticate headers when Windows Authentication appears to be installed, loaded, and exclusively enabled?