views:

627

answers:

4

I have a Windows Service that is self hosting a Wcf service, this Wcf service has a tcpBinding with default settings. The Windows service is running as LocalSystem.

The Wcf Service is referenced (default settings) by a Web application that is running in IIS 7.5 integrated pipeline within it's own application pool with its own identity.

Both are running on the same machine.

All is working fine, except that when in the Wcf Service when I check the identity of the current thread with:

Thread.CurrentPrincipal.Identity.Name

It returns the user of the Application Pool of the Web Application.. this is not what I expect. It looks like some sort of impersonation is going on in the Wcf service.

Is this standard behavior? I can't find any documentation on this. And does it mean that when I try to access a database in the Wcf service i'm introducing a identity hop?

Edit, the config on service side:

        Type serviceType = typeof(WcfService);
        host = new ServiceHost(serviceType);

        Binding tcpBinding = new NetTcpBinding( );

        Uri tcpBaseAddress = new Uri("net.tcp://localhost:8001/Test");
        host.AddServiceEndpoint(typeof (WcfService), tcpBinding, tcpBaseAddress);

        host.Open();

On the client side:

            NetTcpBinding tcpBinding = new NetTcpBinding(SecurityMode.Transport);
        windowsService = new WindowsService.WcfServiceClient(tcpBinding, new EndpointAddress("net.tcp://localhost:8001/Test"));
A: 

More information is needed, but I'm guessing that it's somewhere in the configuration for the binding on either the server side or the client side that impersonation is enabled. When adding service references, svcutil.exe is VERY aggressive in setting EVERY possible binding property in configuration.

If you could provide more information for the configuration on the server and client side, it would be appreciated.

casperOne
+2  A: 

I'm reading from Learning WCF by Michele Bustamante. I have used WCF for an application that I've refactored and we're interested in using WCF in new applications for the flexibility it offers. One of the downsides of WCF is that it can be tricky to use the .net attributes or .config files to get the settings just right. I have spent days tracking down issues with the WCF settings. I've even created automated tests that will check that my service runs the way it's supposed to.

In response to your question, Michele says very specifically in Chapter Seven that NetTcpBinding is secure by default, meaning that callers must provide Windows credentials for authentication. I believe that would explain why the thread appears to be running as the identity of the web service. This is to protect your service from being called by an unauthorized user.

I believe that the following quotation from pp. 419-420 will answer your question concisely. "If you are familiar with traditional .NET role-based security, you know that there is a security principal attached to each executing thread. That security principal holds the caller's identity, which may be tied to a Windows account or a custom database credential, and its roles."

That seems to state plainly that yes, this is standard behavior.

I believe that you can change the behavior through attributes and .config files. I recommend you get a good book on the subject. I spun my wheels in the sand a long time trying to get bits and pieces of information about WCF from the web.

Rice Flour Cookies
A: 

To clearify:

I was checking the wrong property here. Because code would be executed under the WindowsIdentity.GetCurrent() identity.

By default this is NOT the same as the caller (which is in Thread.CurrentPrincipal.Identity). If you want this behaviour you can control this with:

host.Authorization.ImpersonateCallerForAllOperations = true;

and

[OperationBehavior(Impersonation = ImpersonationOption.Required)]
Flores
A: 

We actually have integrated security set at the website, and then any calls from the website to the WCF service we wrap in:

        using (((WindowsIdentity)HttpContext.Current.User.Identity).Impersonate())
        {

That makes sure the credentials of the logged in user are passed through, rather than the IIS app pool credentials.

Works like magic!

Jonathan