IIS 7.5: How to configure custom Authentication Error page with Windows Authentication. 401 header problems

I have a php website running under IIS 7.5. The site is secured by Windows authentication and that works fine:

Windows Authentication is on

When users go to the site, they are asked for username/password and get through if authenticated. If users click Cancel or mistype password 3 times, they are shown 401 error page:

Ugly 401 page

Now I would like to show custom page explaining how to log-in. So I go to Error pages, select status code 401.2 and point it to the page I would like to display:

Error pages settings

Then make sure the custom errors are turned on for everybody. And kaa-boom! Authentication does not work any more, users are not presented with the password prompt. As documentation says, Windows Authentication works by sending 401 reply first, then browser asks user to provider credentials and then they work out what to do next.

What happens here: on first request for the page IIS tries to send 401-header, but notices that web.config says "on 401 redirect to this page". And instead of authentication, it just gives the redirect page.

I've tried replacing 401, 401.1, 401.2 - made no difference.

What am I doing wrong and how to give custom page on user authentication error?

p.s. Here is the web.config:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <httpErrors errorMode="Custom">
            <remove statusCode="500" subStatusCode="-1" />
            <remove statusCode="404" subStatusCode="-1" />
            <remove statusCode="401" subStatusCode="-1" />
            <error statusCode="401" subStatusCode="2" prefixLanguageFilePath="" path="/not_restricted/401.htm" responseMode="ExecuteURL" />
            <error statusCode="404" prefixLanguageFilePath="" path="/not_restricted/404.htm" responseMode="ExecuteURL" />
        </httpErrors>
        <httpProtocol>
            <customHeaders>
                <remove name="X-Powered-By" />
            </customHeaders>
        </httpProtocol>
    </system.webServer>
    <system.web>
        <identity impersonate="false" />
        <customErrors defaultRedirect="http://www.myserver.com/not_restricted/500.htm" mode="Off">
        </customErrors>
    </system.web>
</configuration>

Solution 1:

Try this:

change:

<error statusCode="401" subStatusCode="2" prefixLanguageFilePath="" path="/not_restricted/401.htm" responseMode="ExecuteURL" />

to

<error statusCode="401" subStatusCode="2" prefixLanguageFilePath="" path="not_restricted\401.htm" responseMode="File" />

With the response mode 'File' IIS just loads the content of that file and displays it, it still sends the 401 status back to the client.

I used to use 'ExecuteURL' but have learned that File mode works much better. You just have to make sure that any linked resources in your error pages still work.

Solution 2:

I ran into this same issue of users not being prompted with credentials after adding custom httperrors and was able to fix it with a subStatusCode of 0. Hope this helps someone.

<error statusCode="401" subStatusCode="0" path="..." responseMode="ExecuteURL">

Solution 3:

So I was having a hard time with the exact same problem of Basic Auth not prompting the browser. Neither forcing a custom error of 401.0 (i.e. explicitly setting subcode to 0) or setting the registry key creation resolved it for me.

Turned out it was our use of custom error pages to begin with. Turning them off, everything worked fine, back on... specifically the 401 (0) and 401.2 errors prevented the prompt.

Setting the custom error type to 'File' from 'ExecuteURL' did resolve it, but if the user canceled the prompt or entered a bad password, they got a generic "You do not have permission to view this directory or page".

After a lot of getting hints from various posts, but never an exact 'how-to' or 'why'... I was using a relative path for the custom error file which was in a subdirectory of the site. Changing the path to an absolute one caused the above generic error to be replaced with "cannot display this page" if canceled or bad password. A little more digging and I found a post talking about a config attribute "allowAbsolutePathsWhenDelegated" which is set to false by default. It also states that if you just put the customer error file in your site root and then in the custom error location just the file name (i.e. relative path to the root of the site) it would work... sure enough it does, however, I didn't want to put custom errors in the root of my site. So I used the ConfigurationEditor to set the above attribute to true, set the absolute path to the custom error files and everything started to work fine. Prompt remained, custom error displays when triggered.

What I would like is, to be able to use the File attribute with a nested relative path, but so far I've not found out why I can't or how to do this. The other question is, if by using an absolute path, if I'm potentially creating a security hole (i.e. why would this be disabled by default?)

Anyway, hope this helps someone.