AsiaTech: Microsoft APGC Internet Developer Support Team

We focus on various troubleshooting plan and solution on IIS web platform and distributed applications

A solution to limit specified client certificates to consume WCF service

A solution to limit specified client certificates to consume WCF service

Rate This
  • Comments 3

Background:

 

Suppose there is a WCF service which will be consumed by other parties.  The client credential type of this WCF service is configured as certificate. In other word, the WCF consumer must present its client certificate to WCF service for authentication & authorization. This is a typical kind of business –to-business architecture.

By default, WCF provides below options to validate if the incoming client certificate is valid:

 

·         None

·         PeerTrust

·         ChainTrust

·         PeerOrChainTrust

·         Custom

More details about this topic, you can refer to below MSDN:

X509CertificateValidationMode Enumeration

http://msdn.microsoft.com/en-us/library/system.servicemodel.security.x509certificatevalidationmode(v=vs.90)

 

Suppose there are multiple incoming client certificates, let’s say: WCFClient#1, WCFClient#2. Both client certificates can be validated successfully according to above X509 certificate validation policy.  Then the problem comes up:

How can we limit only WCFClient#1 can consume the WCF service, and disallow WCFClient#2 to consume the WCF service although WCFClient#2 can be validated successfully?

 

Or we have multiple WCF services deployed in the same box and will be consumed by multiple other parties who will present their corresponding client certificates, just as below diagram shows:

 

Then how can we control WCF#1 WCF service can only be consumed by WCFClient#1, and WCF#2 WCF service can be only consumed by WCFClient#2 as well?

 

Recently I handled several cases that customer were just trying to find a solution to implement above design.

 

Here I’d like to share a solution to implement this kind of design.

 

NOTE: One thing I need to mention is: this is one possible solution, but not the only one. So I just share the steps for my specific solution.

Solution:

The rough idea of this solution is to map the incoming client certificate as a windows account. Then we authorize the access to WCF service based on windows account.

To implement above design, we need to configure IIS and WCF perspective at the same time, and a little coding as well.

NOTE: Here I’d like to use IIS7.5 of Windows Server 2008 R2 as the web server. So all configuration about IIS listed below is about IIS7.5.

1) IIS perspective:

      a) For SSL Setting, we need to configure it as below:

                          “Require SSL + Client Certificates Require”

 

 b)  For Authentication setting, we need to enable “Anonymous” authentication and disable all other options.

c)  We need to enable iisClientCertificateMappingAuthentication just as below screenshot shows:

 

So we need to map the incoming client certificate as a windows account. Let’s say the mapped windows account is “mydomain\wcfclientaccount”.

 

For more details about how to configure client certificate mappings, you can refer to below article:

Configuring Many-to-One Client Certificate Mappings for Internet Information Services (IIS) 7.0 and 7.5

http://support.microsoft.com/kb/2026113

 

2. WCF Service Perspective:

  a) Configure your binding to use Transport Security mode with Certificate client credential type .  So the configuration will be just like below:

         “
   <basicHttpBinding>
        <binding name="NewBinding0">
          <security mode="Transport">
            <transport clientCredentialType="Certificate" />
          </security>
       </binding>
     </basicHttpBinding>

   

 

 b) Apply the same binding configuration to the metadata endpoint. The configuration will just be like below:

     <service behaviorConfiguration="securebehaviour" name="HelloWorldDemo.Service1">
…… 
       <endpoint address="mex" binding="basicHttpBinding" bindingConfiguration="NewBinding0"    name="mexEndpoint"  contract="IMetadataExchange" />
      </service>

 

For more information about this topic, you can refer to below MSDN:


How to: Use Certificate Authentication and Transport Security in WCF Calling from Windows Forms
http://msdn.microsoft.com/en-us/library/ff650785.aspx

  c)  Configure the service behavior as below:

i)                    Enable service authorization.

ii)                  Enable “mapClientCertificateToWindowsAccount”

So the configuration will just look as below highlighted.


  <serviceBehaviors>
        <behavior name="securebehaviour">
          <serviceMetadata httpGetEnabled="false" httpsGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="false" />
          <serviceCredentials>
            <clientCertificate>
              <authentication certificateValidationMode="PeerOrChainTrust" mapClientCertificateToWindowsAccount="true" />
            </clientCertificate>
          </serviceCredentials>
          <serviceAuthorization principalPermissionMode="UseWindowsGroups" />
        </behavior>
      </serviceBehaviors>

More details about mapClientCertificateToWindowsAccount property, you can refer to below MSDN article:

X509ClientCertificateAuthentication.MapClientCertificateToWindowsAccount Property

http://msdn.microsoft.com/en-us/library/system.servicemodel.security.x509clientcertificateauthentication.mapclientcertificatetowindowsaccount.aspx

d) Apply PrincipalPermission attribute to that specific method that you want to limit access to, for example:


       [PrincipalPermission(SecurityAction.Demand, Name = @"mydomain\wcfclientaccount")]
        public string HelloWorld()
        {
            return "Hello World. You have authenticated with account: " + System.ServiceModel.ServiceSecurityContext.Current.PrimaryIdentity.Name.ToString();
        }

If you have concern about this kind of hardcoded way, you can also implement it programmatically. The sample code will be like below:

    static class PermissionHelper
    {

        public static void CheckPermission()
        {
            string allowedAccount = System.Configuration.ConfigurationManager.AppSettings["AllowedWindowsAccount"].ToString(); 
// We get the allowed windows account who is authorized to call this WCF method from configuration file

            PrincipalPermission ppAdmin = new PrincipalPermission(null, allowedAccount);
            ppAdmin.Demand();

       }
    }

 

    public class Service1 : IService1
    {                
        public string helloworld()
        {
            PermissionHelper.CheckPermission();
//Execute your real logic then
            return "Hello World. You have authenticated with account: " + System.ServiceModel.ServiceSecurityContext.Current.PrimaryIdentity.Name.ToString();
        }
    }

For more details, you can refer to below article:

PrincipalPermissionMode Enumeration

http://msdn.microsoft.com/en-us/library/system.servicemodel.description.principalpermissionmode.aspx

 

3. WCF Client Perspective.

  WCF client must present its client certificate by specifying the client certificate using Endpoint behavior just like below:


<endpointBehaviors>
                <
behavior name="NewBehavior0">
                    <
clientCredentials>
                        <
clientCertificate findValue=" AllowedClientCertificate " storeLocation="LocalMachine"     x509FindType="FindBySubjectName" />
                    </
clientCredentials>
                </
behavior>
</
endpointBehaviors>

Best regards

Winston He from AGPC DSI Team

 

Leave a Comment
  • Please add 4 and 8 and type the answer here:
  • Post
  • This post is very interesting and it also helpful for us. liking stuff like this blog as well as this has now given me Some inspiration To succeed, ever so Appreciate it.

    http://johnnymbombenza.com/

  • Hi,

    Hi,

    I need to consume a web service method inside the secured ssl certificate. We've  already installed root, intermediate and personel certifiactes inside the related folders. But we always receive the error message "Could not establish secure channel for SSL/TLS with authority". Why do we see that error? How can we know which the certificate installation or client application causing the error?

    Thank you

  • I'm having the same scenario you described at the top and I tried to implement this solution, both the service and client are on the same machine. I receive the following error:

    "The HTTP request was forbidden with client authentication scheme 'Anonymous'."

    Do I miss something? If there is a better way to contact you please tell me.

    Thanks in advance.

Page 1 of 1 (3 items)