Geeks With Blogs

News

Disclaimer


Posts in the blog are provided "AS IS" with no warranties implied or expressed. The opinions expressed here are mine alone, and may not represent those of any organization or group that I am part of.
Manesh Karunakaran

When we started WCFing in my current project, the first challenge that we had was to get the WCF Services to impersonate the callers, I had burned a lot of mid night oil trying to figure out the right configuration that would make this happen. Till that time I had not gone through the WCF Security Guidance on CodePlex. The Guidance turned out to be quite helpful and very comprehensive. If you have not gone though that yet, I strongly recommend going to CodePlex and reading it right away.

For those who do not have that much time and do not want to go too much into the theoretical side of side of it, I have put together a small how to on setting up WCF Services to Impersonate Client credentials. Please follow these simple steps and you will be good to go.

WCF Side 

1. Configure your service to use Windows Authentication and Message Security.

<wsHttpBinding>
  <binding name="WSHttpBinding_IService”>
    <security mode="Message">
      <transport clientCredentialType="Windows" 
                 proxyCredentialType="None" realm="" />
      <message clientCredentialType="Windows" 
               negotiateServiceCredential="true" 
               algorithmSuite="Default" 
               establishSecurityContext="true" />
    </security>
  </binding>
</wsHttpBinding>

2. Configure the SPN Identity for the WCF Service Endpoint

Configure the service principle name (SPN) identity under which the WCF service will run, this identity is usually the lower-privilege Network Service account. Use of this account will reduce the attack surface when your application is not impersonating.

  1. Right-click the web.config file and then and select the Edit WCF Configuration option.
  2. If you do not see the Edit WCF Configuration option, click the Tools menu and select WCF Service Configuration Editor. Close the WCF Service Configuration Editor tool that appears. The option should now appear on the web.config context menu.
  3. Expand the Services node, expand the Service node, and then expand the Endpoints node.
  4. Ensure that there is one endpoint that is configured to use wsHttpBinding.
  5. Select the Identity tab and delete the Dns attribute value, which by default is set to “localhost”.
  6. Set the ServicePrincipalName attribute to your machine name. This value depends on the identity which is used for running the WCF service. By default, the WCF service runs under the Network Service identity and is identified by the machine account in the network, hence you can use your machine name.

Now the configuration should look like this.

<service behaviorConfiguration="ServiceBehavior" name="ServiceSI">
  <endpoint address="" binding="wsHttpBinding" contract="IService">          
    <identity>
      <servicePrincipalName value="DEV-MANESHK" />
      <dns value="" />
    </identity>
  </endpoint>
  <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>

3. Set up impersonation for all operations

Perform the following steps to impersonate all operations:

  1. Right-click the Web.config file and then select the Edit WCF Configuration option.
  2. Expand the Advanced node and then expand the Service Behaviors node.
  3. Select the ServiceBehavior service behavior, and then click the Add button.
  4. In the Adding Behavior Extension Element Sections dialog box, choose serviceAuthorization and then click Add.
  5. Select the serviceAuthorization node and then set the ImpersonateCallerForAllOperations attribute to True.
  6. In the configuration editor dialog box, on the File menu, click Save.
  7. In Visual Studio, verify your configuration settings in Web.config. The configuration should look as follows:

<behavior name="ServiceBehavior">
  <serviceMetadata httpGetEnabled="true" />
  <serviceDebug includeExceptionDetailInFaults="false" />
  <serviceAuthorization impersonateCallerForAllOperations="true" />
</behavior>

4. Implement Impersonation in the WCF Service

Perform the following steps to declaratively impersonate specific operations:

  1. Open the Service Implementation (SI) cs file, and add a using statement for the System.Security.Principal namespace.
  2. Set the impersonation required on the operation implementation of the specific operations as follows:

[OperationBehavior(Impersonation = ImpersonationOption.Required)]
public ServiceOutPut CreateService(ServiceInput serviceInput)
{
      //Code
}

Note: When impersonating for all operations, the Impersonation property of the OperationBehaviorAttribute applied to each method must also be set to either Allowed or Required.

5. Impersonating the Original Caller Programmatically.

Perform the following step to impersonate the original caller programmatically:

  1. Use the Impersonate() call to impersonate the original caller, and then use GetCurrent() to revert back to the previous state. Now the stub should look like this

[OperationBehavior(Impersonation = ImpersonationOption.Required)]
public ServiceOutPut CreateService(ServiceInput serviceInput)
{
    if ((ServiceSecurityContext.Current.WindowsIdentity.ImpersonationLevel == TokenImpersonationLevel.Impersonation)
        || (ServiceSecurityContext.Current.WindowsIdentity.ImpersonationLevel == TokenImpersonationLevel.Delegation))
    {
        using (ServiceSecurityContext.Current.WindowsIdentity.Impersonate())
        {

            //Your code goes in here

        }
    }
}

Client Side

1. Create the Client Configuration file from the WCF Config

Perform the following steps for creating a client configuration file from the newly created wcf configuration file.

  1. Open Visual Studio 2008 and navigate to the Tools menu and select WCF Service Configuration Editor.
  2. Once the WCF Configuration Editor opens up, select File > New Config to start a new configuration file.
  3. Click on Client, and click on the Create New Client link
  4. From the next screen select the WCF Configuration created earlier, by clicking on the Browse button.
  5. Select wsHttpBinding Endpoint from the next screen.
  6. In the next screen provide a name for your client configuration, go Next, view summary and click on Finish.
  7. Now click on the newly created wsHttp end point and provide the address of your hosted WCF
  8. Expand the Advanced node, open Endpoint Behaviors and click on New Endpoint Behavior Configuration.
  9. Give a name to the configuration, something more meaningful than ‘NewBehavior0’
  10. Click on Add and from the window that pops up, select clientCredentials
  11. Once the entry gets cretated, double click on clientCredentials to open detailed configuration
  12. Now modify the value for AllowedImpersonationLevel to “Impersonation”.
  13. Now expand Client node and open Endpoints
  14. Select the wsHttpEndPoint and select the newly added endpoint configuration for BehaviorConfiguration.
  15. Save the configuration file and let out a sigh of relief.. you are done!

 

Side Note on my Second Blog Post

I have taken the good advice that Lee Brandt and Matt Christian gave me and have installed LiveWriter on my machine, and have got that to talk to GWB servers. The import blog feature works like a charm. Now I can preview the post before actually publishing it, and make it real cool. This post was written using LiveWriter.

Posted on Thursday, April 23, 2009 4:10 PM | Back to top


Comments on this post: Setting up WCF to Impersonate Client credentials

# re: Setting up WCF to Impersonate Client credentials
Requesting Gravatar...
Hi Manesh, I followed all the instructions you delineate above - and now it's apparent I am impersonating as the client. Hurrah!!!

By the way, I had to remove the code lines in the wcf:
if ... Impersonation/Delegation
because it was always Identification so it couldn't reach my code.

Thank you a million for posting this!

Have a great day!
Left by Giovanni on Nov 12, 2009 2:56 PM

# re: Setting up WCF to Impersonate Client credentials
Requesting Gravatar...
@Giovanni:
If you are always getting Identification, that means your client configuration is not correct. You need to set the AllowedImpersonationLevel attribute on the client side configuration. (You can do this from code as well - if you need to change between Impersonation/Delegation at runtime for some reason)
Left by Manesh on Nov 27, 2009 11:33 PM

# re: Setting up WCF to Impersonate Client credentials
Requesting Gravatar...
From what I see, the need to call:

ServiceSecurityContext.Current.WindowsIdentity.Impersonate();

from within the service if the impersonation level is TokenImpersonationLevel.Delegation is not necessary. Impersonation appears to be in effect by the time the method is reached.

Can someone confirm this for me please?

Thank you!
Left by Rich Bergmann on Dec 10, 2009 8:32 AM

# re: Setting up WCF to Impersonate Client credentials
Requesting Gravatar...
@Rich Bergman
If you have the set up the client configuration properly, then at the server side you wll get the WindowsIdentity object with the client credentials. But the Service would still be running under the appPool identity. If you want to impersonate the cliet user then you need to call the Impersonate() method on the WindowsIdentity object. I recommend you read the WCF Security Guidence on CodePlex at the following link http://wcfsecurity.codeplex.com/
Left by Manesh on Dec 11, 2009 7:53 PM

# re: Setting up WCF to Impersonate Client credentials
Requesting Gravatar...
Nice tutorial but when I tried to do this using silverlight as the client I was unsuccessfull, would you happen to know a work around for when the client is a silverlight application.
Any help would be appreciated
Left by Filipe on Feb 23, 2010 8:37 AM

# re: Setting up WCF to Impersonate Client credentials
Requesting Gravatar...
Was the wcf service hosted on IIS?
Left by Roo on Apr 30, 2010 2:21 AM

# re: Setting up WCF to Impersonate Client credentials
Requesting Gravatar...
Does this work locally as well as on the server? How do you debug your service locally after you set all this up?
Left by Chuck on Jul 28, 2010 8:30 PM

# re: Setting up WCF to Impersonate Client credentials
Requesting Gravatar...
Hi is this also applicable to scenarios where in i want to make my wcf service open an excel file via Interop, read some data and then return the observable collection?
Left by dennis on May 05, 2011 3:03 PM

# re: Setting up WCF to Impersonate Client credentials
Requesting Gravatar...
looks good. I will try out the code
Left by Zed power on Aug 11, 2011 7:49 PM

# re: Setting up WCF to Impersonate Client credentials
Requesting Gravatar...
Hi Manesh,

Thanks for your concise explaination. I tried to follow your steps and I'm sure it works because if I write WindowsIdentity.GetCurrent.Name to event log I can see the caller windows account identity. But I'm stuck when I need the service to connect to an SQL Server using trusted connection. It always gets an error saying "Login failed for user 'NT AUTHORITY\ANONYMOUS LOGON'". It looks like the credential is not propagated. Could you help me on this please?

Thanks
Left by Tony on Aug 15, 2011 10:06 AM

# re: Setting up WCF to Impersonate Client credentials
Requesting Gravatar...
very useful text - thank you!!!
Left by MOPO3OB on Aug 29, 2011 8:15 PM

Your comment:
 (will show your gravatar)
 


Copyright © Manesh Karunakaran | Powered by: GeeksWithBlogs.net | Join free