Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Impersonating ASP.NET claims identity to windows identity

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?

like image 671
Jaap Avatar asked Nov 14 '22 10:11

Jaap


1 Answers

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.

like image 132
Raymond Saltrelli Avatar answered Dec 19 '22 02:12

Raymond Saltrelli