I created an ASP.NET MVC application that uses integrated Windows Authentication. The following authorization logic was implemented:
Try to get account credentials from active directory through NTLM.
Display the Windows authentication dialog, so a user can provide another credentials:
Then I have added custom error pages for the application, using VictorySaber's solution:
protected void Application_EndRequest()
{
int status = Response.StatusCode;
string actionName;
if (status >= 400 && status < 500)
{
switch (status)
{
case 401:
actionName = "Unauthorized";
break;
// Handle another client errors
default:
actionName = "BadRequest";
break;
}
}
else if (status >= 500 && status < 600)
{
switch (status)
{
case 501:
actionName = "NotImplemented";
break;
// Handle another server errors
default:
actionName = "InternalServerError";
break;
}
}
if (!String.IsNullOrEmpty(actionName))
{
Response.Clear();
var rd = new RouteData();
rd.Values["controller"] = "Errors";
rd.Values["action"] = actionName;
IController c = new ErrorsController();
c.Execute(new RequestContext(new HttpContextWrapper(Context), rd));
}
}
As result my friendly error pages are rendered. But the Windows authentication dialog does not appear. If the 401 HTTP status code occurs it immediately displays 401 error message. The trick with the <httpErrors>
section of web.config file gives same result.
Also, I found proposal to catch the 401.2 HTTP status code that should occur when the dialog is cancelled. But in my case the code never occurs.
How to use user friendly error pages instead of default messages but don't change authentication dialog logic?
I need to implement the following requirements:
By default the server leaves the response untouched only if the SetStatus
flag is set. So, it is necessary to clearly specifiy what IIS must to do with an existing response when the HTTP status code is an error.
One way is to configure the <httpErrors>
element of <system.webServer>
section in the Web.config file. Just set existingResponse
attribute value to PassThrough
, so that the server leaves the response untouched if an existing response exists.
<system.webServer>
<!-- configuration settings -->
<httpErrors errorMode="Custom" existingResponse="PassThrough" />
</system.webServer>
The configuration prevent error page rendering if the sever prompts for a Windows user account credentials. The response will be replaced with the error page after the dialog cancellation.
The same result could be achieved by disabling of IIS custom errors through TrySkipIisCustomErrors
property of HttpResponse
. So the
addition the following line to code from the question solves the problem:
Context.Response.TrySkipIisCustomErrors = true;
Note. The second way does not work on my production server for some reason. I think, it requires additional server settings.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With