I have an ASP.NET application
which uses claims bases authentication against ADFS. I also map it to a WindowsClaimsIdentity
by using the Claims to Windows Identity Service. That works fine.
But now I need to impersonate the current request/thread so I can access a service which is not claims aware. How should I do that?
Should I acquired a WindowsImpersonationContext
in the Application_PostAuthenticate
event and save that in the HttpContext.Items
and then in the Application_EndRequest
call the Undo method?
Or are there other preferred ways to do this?
Update: As I didn't get any hints on what the preferred way to impersonate I tried my own suggestion. I created this code in the global.asax.cs:
private static readonly string WICKey = typeof(System.Security.Principal.WindowsImpersonationContext).AssemblyQualifiedName;
protected void Application_PostAuthenticateRequest()
{
var wid = User.Identity as System.Security.Principal.WindowsIdentity;
if (wid != null)
{
HttpContext.Current.Trace.Write("PostAuthenticateRequest PreImpersonate: " + System.Security.Principal.WindowsIdentity.GetCurrent().Name);
HttpContext.Current.Items[WICKey] = wid.Impersonate();
HttpContext.Current.Trace.Write("PostAuthenticateRequest PostImpersonate: " + System.Security.Principal.WindowsIdentity.GetCurrent().Name);
}
}
protected void Application_EndRequest()
{
var wic = HttpContext.Current.Items[WICKey] as System.Security.Principal.WindowsImpersonationContext;
if (wic != null)
{
HttpContext.Current.Trace.Write("EndRequest PreUndoImpersonate: " + System.Security.Principal.WindowsIdentity.GetCurrent().Name);
wic.Undo();
HttpContext.Current.Trace.Write("EndRequest PostUndoImpersonate: " + System.Security.Principal.WindowsIdentity.GetCurrent().Name);
}
}
When I look to the trace log I see this
PostAuthenticateRequest PreImpersonate: NT AUTHORITY\NETWORK SERVICE
PostAuthenticateRequest PostImpersonate: MyDomain\CorrectUser
Home: NT AUTHORITY\NETWORK SERVICE
EndRequest PreUndoImpersonate: NT AUTHORITY\NETWORK SERVICE
EndRequest PostUndoImpersonate: NT AUTHORITY\NETWORK SERVICE
So in the second line you can see the thread is impersonated correctly. But in the next lines you see that the impersonation is lost. (the third line originates from a controller).
When I use the following code to impersonate locally it works fine:
var wid = User.Identity as System.Security.Principal.WindowsIdentity;
if (wid != null)
{
using (var ctx = wid.Impersonate())
{
//Do something
}
}
But I want to impersonate the whole request lifetime. How should I do that?