Impersonating ASP.NET claims identity to windows identity
Asked Answered
P

2

6

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?

Proparoxytone answered 2/2, 2012 at 21:32 Comment(0)
J
1

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.

Jemappes answered 2/2, 2012 at 22:0 Comment(3)
The backend service is using Windows Authentication and I can't change anything in it's configuration. Beside that, it would only move the problem, because that backend service is accessing SQL-Server with Windows authentication impersonated. So then I whould have to solve my problem there.Proparoxytone
What about something like this? Your ASP.NET app can impersonate the WindowsPrincipal for certain blocks of code where it calls the backend service.Jemappes
I want to impersonate in the PostAuthenticateRequest event so that the whole request can run in that impersonated context. After impersonating call in PostAuthenticationRequest WindowsIdentity.GetCurrent().Name returns indeed the expected user name. But in my controller and after that in the EndRequest it has again the NetworkService account. And not done an impersonatingcontext.Undo()!Proparoxytone
A
-1

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.

Accusative answered 17/8, 2017 at 11:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.