I have an ASP.NET app that requires users to sign in with their domain accounts using Basic Authentication. The user can make a selection, then press a button.
At some point after pressing the button is this code: WindowsIdentity.Impersonate(userIdentity.Token)
. userIdentity is of type WindowsIdentity, and it was previously set to (WindowsIdentity)User.Identity.
userIdentity is stored as a session variable, and I think that's because, after the button is pressed, the page containing this code is called via AJAX.
When I hit this code, it works about 2/3 of the time, but 1/3 of the time, I get this exception: Invalid token for impersonation - it cannot be duplicated. I think the biggest head scratcher for me is why does it work sometimes but not other times? On some sessions, it works several times before failing. On others, it fails right away.
Here's the stack trace:
at System.Security.Principal.WindowsIdentity.CreateFromToken(IntPtr userToken)
at System.Security.Principal.WindowsIdentity..ctor(IntPtr userToken, String authType, Int32 isAuthenticated)
at System.Security.Principal.WindowsIdentity.Impersonate(IntPtr userToken)
at Resource_Booker.BLL.ReservationAgent.SubmitReservationRequest(Reservation reservation, Patron patron) in C:\dev\RoomRes\Resource Booker\BLL\ReservationAgent.cs:line 101
at Resource_Booker.Reserve.reserve_Click(Object sender, EventArgs e) in C:\dev\RoomRes\Resource Booker\Reserve.aspx.cs:line 474
at System.EventHandler.Invoke(Object sender, EventArgs e)
at System.Web.UI.WebControls.Button.RaisePostBackEvent(String eventArgument)
at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
Here's a confounding factor: I cannot reproduce this problem on my local Windows 7 x64 workstation--albeit my authentication is passed implicitly here since I am using localhost--or on a Windows 2003 32-bit IIS 6.0 environment. It only happens on a pretty vanilla Windows 2008 R2 environment. All these environments are domain members.
Basically what you are seeing is not a security problem as the logon session is cached by IIS for the lifetime of the TCP connection, but HTTP will occasionally cut the TCP connection requiring re-authentication. This will happen seamlessly and invisibly (handled by the browser) but it will invalidate the token, as the logon session will be destroyed when the TCP connection ends.
I.e. for the benefit of @usr, it only works sometimes because the logon session is the same so the token is the same, so the token stored in the session works because it happens to be the same actual token as User.Identity. It's not a way of avoiding the security check it is an implementation detail of the security check.
You shouldn't be storing the identity in the session - it is unnecessary since it is an authenticated connection.
Just use (WindowsIdentity)User.Identity
every single time and your problem should go away.