Chapter 12: Intranet - Windows Forms to Remote WCF Using Transport Security (Original Caller, TCP)

patterns & practices Developer Center

Applies To

  • Microsoft® Windows Communication Foundation (WCF) 3.5

Scenario

In this scenario, your users have Microsoft Windows® accounts and use a Windows Forms client to connect over an intranet to your WCF service. The business logic called by the WCF service is backed by a Microsoft SQL Server® data store. The following figure illustrates the basic model for this application scenario.

Ff649806.CH12-Fig1(en-us,PandP.10).png

Figure 1
Windows Forms to Remote WCF Using Transport Security (Original Caller, TCP) – Model

Key Characteristics

This scenario applies to you if:

  • Your users have Windows Forms clients.
  • Your user accounts are in a Microsoft Active Directory® directory service within a domain.
  • Your user roles are Windows groups.
  • Your application transmits sensitive data over the network that needs to be protected.

Solution

Ff649806.CH12-Fig2(en-us,PandP.10).png

Figure 2
Windows Forms to Remote WCF Using Transport Security (Original Caller, TCP) – Solution

Solution Summary Table

In this solution, you will:

  • Use domain credentials to authenticate clients against an Active Directory user store.
  • Use a service account to call the SQL Server from WCF.
  • Use transport security to protect sensitive data between the Windows Forms client and the WCF service.
  • Use netTcpBinding to support the TCP transport for improved performance.
  • Host WCF in a Windows service because Internet Information Services (IIS) does not support the Transmission Control Protocol (TCP) transport.

Thick Client

Checks/ more information

Example

WCF proxy

The application has a proxy reference to the WCF service.

The application has access to the WCF metadata to create a service reference.

        
WCFTestService.MyServiceClient proxy = new WCFTestService.MyServiceClient();

      

The proxy invokes services with the security context of the logon user.

The proxy will automatically invoke WCF operations using the security context of the current user.

        
proxy.GetData("data");
proxy.Close();

      

Application Server

Checks / more information

Windows service—configuration

The Windows service is configured to run under a custom domain service account.


Use a domain account if possible.

The WCF service is hosted in a Windows service.

Since IIS does not support netTcpBinding, host in a Windows service instead.

Checks / more information

Example

WCF service—configuration

Configure the WCF service to use netTcpbinding. The base address is provided in the configuration section.

netTcpBinding uses the TCP protocol and provides full support for SOAP security, transactions, and reliability. Because the client and WCF service are both located in an intranet, this is a good choice from a performance perspective.

        
<endpoint 
   address=""     
   binding="netTcpBinding" 
   bindingConfiguration=""
   name="TcpBinding"    
   contract=
   "WCFServicecHost.IMyService"/>

<baseAddresses> <add baseAddress= "net.tcp://WCFApp01.npscode.com/MyService" />

</baseAddresses>

A metadata exchange (mex) endpoint is created for publishing the metadata.

This is required so that the client can add reference to the WCF service using the SvcUtil utility.

        
<endpoint 
    address="Mex" 
    binding="mexTcpBinding" 
    bindingConfiguration=""
    name="MexEndpoint"  
    contract="IMetadataExchange"
/>

      

Service metadata is configured in the service behavior.

The service metadata entry is required for the Windows service host to start. HTTP and HTTPS GET requests are disabled.

        
<serviceMetadata />

      

WCF service—authentication

netTcpBinding is configured to use Windows authentication and transport security.

By default, netTcpBinding is configured to use Windows authentication and transport security.

        
<endpoint 
  address=""   
  binding="netTcpBinding"
  bindingConfiguration="" />

      

WCF service—authorization

The Role Manager feature is enabled and WindowsTokenRoleProvider is configured for roles authorization.

Roles authorization can be performed declaratively or imperatively in the operation contract.

        
<serviceAuthorization    
  principalPermissionMode             
    ="UseAspNetRoles"
  roleProviderName
="AspNetWindowsTokenRoleProvider" />

      

Perform role checks declaratively using Windows Identity Token, for checking Active Directory group membership.

Declarative role checks on operations are the preferred mechanism.

        
[PrincipalPermission(SecurityAction.Demand, Role = "npscode\\accounting")]

public string GetData(string message) { return "hello"; }

Perform role checks imperatively using Windows Identity Token, for checking Active Directory group membership.

If you need finer-grained authorization control, you can use imperative role checks in the code itself. Use a call to Roles.IsUserInRole to perform the check.

        
public string GetData(string myValue)
{
if(Roles.IsUserInRole(@"npscode\Accounting"))
  {
   //Do something for Accounting role              
  }
else
  {
   //Do something for non-accounting role or throw an error
   } 
 }

      

WCF service—SQL

The connection string for the database is configured to use Windows authentication.

The database connection string includes Integrated Security=SSPI or Trusted Connection=Yes.

        
SqlConnection sqlcon = new SqlConnection("Server=10.3.19.11;Database=Northwind;IntegratedSecurity=SSPI");

      

The database connection is opened using the WCF process identity’s security context.

The service does not impersonate the original caller to benefit from connection pooling.

 

Database Server

Checks / more information

Example

Configuration

A SQL Server login is created for the WCF’s service account (process identity).

This grants access to the SQL Server.

        
exec sp_grantlogin 'Custom Service Account'

      

The login is granted access to the target database.

This grants access to the specified database.

        
use targetDatabase 
go 
exec sp_grantdbaccess 'Custom Service Account' 
go 

      

A database role is created in the target database.

This allows access control and authorization to the database.

        
use targetDatabase 
go 
exec sp_addrole 'DB Role Name' 
go 

      

The login is added to the database role.

Grant minimum permissions. For example, grant execute permissions to selected stored procedures, and provide no direct table access.

        
use targetDatabase
go
exec sp_addrolemember 'DB Role Name', 'Custom Service Account'
go

      

Authentication

SQL Server is configured to use Windows authentication.

Communication Security

What

Check

Application server to database

You can use IPSec or SSL between the application server and the database server to protect sensitive data on the wire.

Analysis

Thick Client

WCF Proxy

  • Because WCF requires the original user’s credentials for authentication and authorization, the original user’s security context makes all calls through the WCF proxy and into the WCF service.

Application Server

Authentication

  • In order to authenticate the original users when the thick client makes calls on the WCF service, WCF is configured to use Windows authentication.

Authorization

  • For coarse grained access control, authorization checks are performed declaratively in the WCF service at the operation level.
  • For fine-grained access control, authorization checks are performed programmatically within the operations.
  • The Role Manager is a good choice for this scenario because it allows your service code to look up users’ roles without writing and maintaining custom code.

Data Access

  • To reduce the risk of stolen database credentials, the database connection string is configured to use Windows authentication. This eliminates the need to store credentials in files and pass credentials over the network to the database server.
  • The WCF service accesses the database using the WCF process identity. As a result, all calls use the single process account and the designated database connection pooling.

Configuration

  • This scenario is optimized around transmission performance at the expense of interoperability with clients that expect a legacy Web service and the ability to host the service in IIS. For this reason, the best binding choice is netTcpBinding. By default, netTcpBinding supports Windows authentication with transport security.
  • Because netTcpBinding is not supported by IIS 6.0, the WCF service is hosted in a Windows service.
  • In order to reduce attack surface and minimize the impact of a compromise, the Windows service is running under the security context of the service account, using a least-privileged account.
  • In order to make it possible for the client to generate a proxy based on the service definition, we have exposed a mex endpoint.

Database Server

  • SQL Server database user roles are preferred over SQL Server application roles to avoid the password management and connection pooling issues associated with the use of SQL Server application roles. Applications activate SQL Server application roles by calling a built-in stored procedure with a role name and a password. Therefore, the password must be stored securely. Database connection pooling must also be disabled when you use SQL Server application roles, which severely impacts application scalability.
  • Creating a new user-defined database role, and adding the database user to the role, lets you give specific minimum permissions to the role. Therefore, if the database account changes, you do not have to change the permissions on all database objects.

Communication Security

  • Transport security protects sensitive data between the thick client and the WCF service.
  • You can use IPSec or Secure Sockets Layer (SSL) encryption between the WCF service and the database server to protect sensitive data on the wire.

Example

Application Server

Code

The service performs imperative authorization checks calling Roles.IsUserInRole.

The service calls SQL Server using Windows authentication.

using System.Data.SqlClient;
using System.Web.Security;

public string GetData(string myValue)
{
  if(Roles.IsUserInRole(@"npscode\Accounting"))
  {
    SqlConnection sqlcon = new  SqlConnection("Server=10.3.19.11;Database=Northwind;IntegratedSecurity=SSPI");
    sqlcon.Open();
    //do the business operation
    return "Authorization succeeded ";
  }
  else return "authorization failure";
}

Configuration

  • The service has a binding endpoint that uses netTcpBinding with no binding configuration and Windows authentication (default settings).
  • The service has a mex endpoint to publish metadata.
  • The service has a service behavior configuration to expose the role provider to the WCF service.
  • The service has a base address configured to reduce the size of the binding addresses in the configuration file.
  • The service configuration file has an entry for the AspNetWindowsTokenRoleProvider under system.web to define which role provider is being used.
  • The service behavior is configured with the serviceAuthorization element to allow WindowsTokenRoleProvider as the authorization provider.
  • The service behavior is configured with the serviceMetadata element to allow metadata exposure.
<system.web>
    <roleManager enabled="true"
             defaultProvider="AspNetWindowsTokenRoleProvider" />
</system.web>

<system.serviceModel>
  <behaviors>
     <serviceBehaviors>
        <behavior name="BehaviorConfiguration">
           <serviceAuthorization principalPermissionMode="UseAspNetRoles"
                        roleProviderName="AspNetWindowsTokenRoleProvider" />
                    <serviceMetadata />
        </behavior>
      </serviceBehaviors>
  </behaviors>

  <bindings />

  <services>
    <service behaviorConfiguration="BehaviorConfiguration" 
             name="WCFServicecHost.MyService">
       <endpoint address="Mex" 
                 binding="mexTcpBinding" 
                 bindingConfiguration=""
                 name="MexEndpoint" 
                 contract="IMetadataExchange" />
       <endpoint address="" 
                 binding="netTcpBinding" 
                 bindingConfiguration=""
                 name="TcpBinding" 
                 contract="WCFServicecHost.IMyService" />
       <host>
          <baseAddresses>
            <add baseAddress="net.tcp://perfpres02.npscode.com/MyService" />
          </baseAddresses>
       </host>
    </service>
  </services>

</system.serviceModel>

Database Server

Configuration

  • A SQL Server login is created for the WCF service account.
  • The WCF login name is given access to the application database.
  • The role is created in the application database.
  • The WCF login name is added to the role.
-- Create a SQL Server login  that matches the WCF machine name
EXEC SP_GRANTLOGIN 'npscode\perfpres02$'

-- Grant the login access to the application database
use testdb 
go 
exec sp_grantdbaccess 'npscode\perfpres02$' 

-- Create the new database role
use testdb
go
exec sp_addrole 'myrole2','db_owner' 

-- Add the new login to the role
use testdb
go
exec sp_addrolemember 'myrole2','npscode\perfpres02$' 

Additional Resources