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?
You said the backend service is not claims aware. Can you elaborate on this? Do you mean that the compiled code is not claims aware but you have the ability modify the web.config file? If so then you can try to configure the backend service to use the WIF pipeline for authN by wedging in the WSFederationAuthenticationModule, SessionAuthenticationModule and a custom ClaimsAuthorizationManager if you need to also do authZ. You can then use WIF's ActAs or OnBehalfOf features when your ASP.NET application calls the backend service.
Sorry for digging up this old thread, but for your code to work make sure the Managed Pipeline Mode of the Application Pool running your application is set to Classic.