Hi all,
Our web site is using FormsAuthentication for the login, but authenticates against ActiveDirectory. After a successful authentication, we replace HttpContext.Current.User with the authenticated WindowsIdentity instance. This code resides within global.asax under Application_AuthenticateRequest event handler. After a successful windows authentication, we "cache" the WindowsIdentity object in a Dictionary in order not to perform unnecessary logins per request. This works great in IIS6 or IIS7 Classic app pool but not for IIS7 Integrated app pool.
Under Integrated app pool what happens is that the cached WindowsIdentity object throws an ObjectDisposedException in the following postbacks.
The process is as follows: Initially, the windows authentication is successful and we assign the WindowsIdentity to the HttpContext.Current.User successfully. However the following postback throws an ObjectDisposedException when we attempt to use the cached WindowsIdentity again, with a "Safe handle has been closed" exception message. Examining the object in a Watch window shows that the IsClosed property of the Token is now true (as opposed to the initial state after performing calling LogonUserA).
Here's the code from global.asax
void Application_AuthenticateRequest(object sender, EventArgs e)
{
if (HttpContext.Current.User != null
&& HttpContext.Current.User.Identity is FormsIdentity
&& HttpContext.Current.User.Identity.IsAuthenticated)
{
FormsIdentity formsIdentity = (FormsIdentity)HttpContext.Current.User.Identity;
FormsAuthenticationTicket ticket = formsIdentity.Ticket;
string username = ticket.UserData;
System.Security.Principal.WindowsIdentity userIdentity = identityDictionary[username]; // identityDictionary caches WindowsIndentity instances created in a custom membership provides which validates the users.
if (userIdentity != null)
{
var principal = new System.Security.Principal.WindowsPrincipal(userIdentity);
HttpContext.Current.User = principal; // <- ObjectDisposedException, "Safe handle has been closed"
}
}
}
I have a several questions:
1. Why under Classic app pool this works but not in Integrated app pool.
2. Is this "pattern" correct? Assuming that it is bad practice to perform login using LogonUserevery request in order to avoid this exception..., how should the WindowsIdentity be cached without the token being closed?
Thanks.