Chapter 11: Intranet - Web to Remote WCF Using Transport Security (Trusted Subsystem, 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 Web client to connect over an intranet to an ASP.NET application on an Internet Information Services (IIS) server. The ASP.NET application makes calls to the WCF service over the Transmission Control Protocol (TCP). The business logic called by the WCF service is backed by a Microsoft SQL Server® data store. The ASP.NET application, the WCF service, and the SQL Server data store are all part of a trusted subsystem. The basic model for this application scenario is shown in the following figure.

Ff650350.CH11-Fig1(en-us,PandP.10).png

Figure 1
Web to Remote WCF Using Transport Security (Trusted Subsystem, TCP) – Model

Key Characteristics

This scenario applies to you if:

  • Your users have browsers supporting Windows integrated authentication.
  • Your user accounts are in a Microsoft Active Directory® directory service within a domain.
  • Your user roles are Windows groups.
  • Your users access the Web client from within the domain.
  • The business logic behind your WCF service does not require fine-grained authorization.
  • Your ASP.NET application and WCF service transmit sensitive data over the network that needs to be protected.
  • A high-performance connection between the ASP.NET application and the WCF service is more important than the ability to host the WCF service in IIS.
  • A high -performance connection between the ASP.NET application and the WCF service is more important than providing interoperability support for non-WCF clients.

Solution

Ff650350.CH11-Fig2(en-us,PandP.10).png

Figure 2
Web to Remote WCF Using Transport Security (Trusted Subsystem, 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 WCF from the ASP.NET application. The WCF service uses Windows authentication.
  • Use a service account to call the SQL Server from WCF. The SQL Server uses Windows authentication.
  • Use Secure Sockets Layer (SSL) encryption to protect sensitive data between the Web client and IIS.
  • Use transport security to protect sensitive data between the ASP.NET application and the WCF service.
  • Optionally, use IPSec to protect sensitive data between the WCF service and SQL Server.
  • Use netTcpBinding to support the TCP transport for improved performance.
  • Host WCF in a Windows service because IIS 6.0 does not support the TCP transport.

Web Server

Checks / more information

Example

IIS—Configuration

A dedicated application pool is used and configured to run under a custom service account.

Use a domain account if possible.

 

The Web application is configured to run under the service account.

Assign the Web application to the custom application pool.

 

A service principal name (SPN) is created if the service account used in the ASP.NET application pool is a custom domain account.

Create an SPN for both the DNS and NETBIOS machine names.

        
setspn -a HTTP//WebServer.domain.com customDomainAccount
setspn -a HTTP//WebServer customDomainAccount

      

IIS—authentication

The IIS virtual directory is configured to use Windows integrated authentication.

Users will be authenticated with Windows authentication.

Anonymous access is disabled.

Checks / more information

Example

ASP.NET—authentication

ASP.NET is configured for Windows integrated authentication.

The Web application will authenticate the users.

        
<authentication mode = "Windows" >

      

ASP.NET—authorization

If you have roles in your application, use URL authorization.

Use the <location> attribute to configure authorization settings for specific folders. The authorized users have access to specific folders and pages.

        
<authorization>
  <allow roles="domainName\RoleName" />
  <deny users="*" />
</authorization>

      

Role Manager is enabled and role checks are performed using a Role Manager API.

Original users are authorized using the Windows groups before calling into the WCF service.

        
<roleManager enabled="true"
             defaultProvider=  
           "AspNetWindowsTokenRoleProvider"/>

      

Checks / more information

Example

WCF proxy—configuration

ASP.NET has a proxy reference to the WCF service.

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

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

      

The proxy invokes services with the security context of the ASP.NET process identity.

The proxy will automatically invoke WCF operations using the security context of the service account.

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

      

The root certification authority (CA) of the certificate is installed in the Trusted Root Certification Authorities store of the user machine, either in Local Machine or Local User.

You need to install the root CA because transport security performs trust chain validation. If the certificate comes from a known issuer, such as VeriSign, this is unnecessary.

 

WCF proxy—caller identity

For auditing purposes, the identity of the caller can be passed in custom message headers.

Use transport security to protect against spoofing attacks.

        
using ( OperationContextScope scope = new OperationContextScope(proxy.InnerChannel))
{
string identity = ((WindowsIdentity)HttpContext.Current.User.Identity).Name;

MessageHeader<string> headerIdentity = new MessageHeader<string>(identity);

MessageHeader untypedMessageHeader = headerIdentity.GetUntypedHeader("identity", "ns"); OperationContext.Current.OutgoingMessageHeaders.Add(untypedMessageHeader);

TextBox1.Text = proxy.GetData("data"); }

Application Server

Checks / more information

Example

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 the Windows service.

Because IIS does not support netTcpBinding, host in the Windows service.

 

WCF service—configuration

Configure the WCF service to use netTcpBinding.

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

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

      

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

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

        
<services>
<service behaviorConfiguration="BehaviorConfiguration" name="WCFServicecHost.MyService">
<endpoint address="Mex" binding="mexTcpBinding" bindingConfiguration=""
name="MexEndpoint" contract="IMetadataExchange" />
</service>

      

Service metadata is configured in the service behavior.

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

        
<behaviors>
    <serviceBehaviors>
    <behavior name="BehaviorConfiguration">
       <serviceMetadata />
    </behavior>
    </serviceBehaviors>
</behaviors>

      

WCF service—authentication

netTcpBinding is configured to use Windows authentication and transport security.

netTcpBinding supports Windows authentication and transport security by default.

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

      

WCF service—caller identity

The service retrieves the identity of the caller from OperationContext for auditing purposes.

Use the identity to improve logging and auditing.

        
string identity = OperationContext.Current.IncomingMessageHeaders.GetHeader<string>("identity", "ns");

      

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, so SQL Server benefits from connection pooling.

 

Database Server

Checks / more information

Example

Configuration

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

This grants access to the SQL Server.

        
exec sp_grantlogin 'Custom Service Account'

      

The login is mapped to a database user for the Web application.

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

Browser to Web server

SSL is used between the browser and Web server to protect sensitive data on the wire.

Install the certificate in the Web site. Configure the virtual directory of the Web application to use SSL.

Application server to database

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

Analysis

Web Server

Authentication

  • To prevent unauthenticated and unauthorized users from accessing pages, IIS disables anonymous access.
  • Windows integrated authentication is a good choice for this scenario because all users have Windows accounts. One benefit of Windows integrated authentication is that it prevents the user’s password from ever being sent over the network. Additionally, the logon is transparent for the user because Windows uses the current user’s logon session.

Authorization

  • URL authorization performs role checks against the original caller and restricts access to pages or folders based on role permissions.
  • All authorization checks are performed in the Web application before calls are made to the WCF service. The WCF service trusts the Web application to perform this authorization and does not need to make fine-grained authorization decisions of its own.
  • The Role Manager is a good choice for this scenario because it allows your service code to look up users’ roles without the need to write and maintain custom code.

WCF Proxy

  • Because you are taking care of all authentication and authorization in the ASP.NET application, all calls through the WCF proxy and into the WCF service use the ASP.NET process identity’s security context. You do not need to flow the original caller into the WCF service.
  • If you need to produce audit logs showing what service operations were called by each user, you can pass the identity of the original caller in a custom header.

Configuration

  • In order to reduce attack surface and minimize the impact of a compromise, the ASP.NET application on the Web server runs under the security context of a service account, using a least-privileged account.

Application Server

Authentication

  • In order to authenticate the ASP.NET service when it makes calls into the WCF service, WCF is configured to use Windows authentication.

Authorization

  • Because the WCF service trusts the ASP.NET application to authorize the user, the WCF service performs no authorization.

Data Access

  • To reduce the risk of stolen database credentials, the database connection string is configured to use Windows authentication. This choice eliminates the need to store credentials in files and pass the 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 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 a service account, using a least-privileged account.
  • A mex endpoint is exposed so that the client can use SvcUtil to generate a proxy based on the service definition.

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. Moreover, using SQL Server application roles forces you to disable database connection pooling, which can severely impact 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. In this way, if the database account changes, you do not have to change the permissions on all database objects.

Communication Security

  • SSL is used between the browser and Web server to protect sensitive data on the wire.
  • Transport security is used to protect sensitive data between the Web server and application server.
  • IPSec or SSL can be used between the application server and database server to protect sensitive data on the wire.

Example

Domain Controller

Configuration

Create an SPN based on the following rules:

  1. If the ASP.NET application runs in an application pool with a custom domain identity, create an SPN and map the custom domain identity with the HTTP service class and both the DNS and NETBIOS machine names:

    setspn -a HTTP//WebServer.domain.com customDomainAccount
    setspn -a HTTP//WebServer customDomainAccount
    
  2. If the service runs under a custom domain identity:

    setspn -a ServiceNameofWcfService//WebServer.domain.com customDomainAccount
    setspn -a ServiceNameofWcfService//WebServer customDomainAccount
    
  3. If the service runs under the network service account:

    setspn -a ServiceNameofWcfService//WebServer.domain.com computerName
    setspn -a ServiceNameofWcfService//WebServer computerName
    

Note

You should specify the service name as it is displayed in the MMC services console.

Web Server

Code

  • Role authorization occurs before WCF service invocation.
  • ASP.NET calls the WCF service if it is authorized.
  • The original caller’s identity is retrieved from the HttpContext.
  • A message header containing the caller identity is created and passed to the operation context for auditing purposes.
using System.Security.Principal;
using System.ServiceModel;
using System.ServiceModel.Channels;
…
protected void Button1_Click(object sender, EventArgs e)
{
  if (Roles.IsUserInRole(@"npscode\Accounting"))
  {
    WCFTestclient.MyServiceClient proxy 
        = new WCFTestclient.MyServiceClient();
    using ( OperationContextScope scope 
        = new OperationContextScope(proxy.InnerChannel))
    {
      string identity 
        = ((WindowsIdentity)HttpContext.Current.User.Identity).Name;
      MessageHeader<string> headerIdentity 
        = new MessageHeader<string>(identity);
      MessageHeader untypedMessageHeader 
        = headerIdentity.GetUntypedHeader("identity", "ns");

 OperationContext.Current.OutgoingMessageHeaders.Add(untypedMessageHeader);
                proxy.GetData("data");          
     }
     proxy.Close();

   } // endif
}

Configuration

  • Windows authentication is enabled.
  • URL authorization role check is enabled.
  • Role Manager is enabled.
<system.web>
  <assemblies>

    <add assembly="System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
    <add assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
    <add assembly="System.Data.DataSetExtensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
    <add assembly="System.Xml.Linq, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>

  </assemblies>

  <authentication mode="Windows" />

  <authorization>
    <allow roles="npscode\BusinessDivision" />
    <deny users="*" /> 
  </authorization>

  <roleManager enabled="true"
               defaultProvider= "AspNetWindowsTokenRoleProvider"/>
     <pages>
        <controls>
          <add tagPrefix="asp" 
               namespace="System.Web.UI" 
               assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>

          <add tagPrefix="asp" 
               namespace="System.Web.UI.WebControls" 
               assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
        </controls>
     </pages>

     <httpHandlers>
        <remove verb="*" path="*.asmx"/>

        <add verb="*" 
             path="*.asmx" 
             validate="false"       
             type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>

        <add verb="*" 
             path="*_AppService.axd" 
             validate="false" 
             type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>

        <add verb="GET,HEAD" 
             path="ScriptResource.axd" 
             type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" validate="false"/>

     </httpHandlers>

      <httpModules>
        <add name="ScriptModule" 
             type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
      </httpModules>

</system.web>

Application Server

Code

  • The service retrieves the identity of the caller from the operation context if it is required for auditing purposes.
  • The service calls SQL Server using the security context of the WCF service.
using System.Data.SqlClient;

public string GetData(string myValue)
{
   SqlConnection sqlcon 
      = new SqlConnection("Server=SqlServer;Database=testdb;Integrated Security=SSPI");

   sqlcon.Open();

//do the business operation

   string identity = OperationContext.Current.IncomingMessageHeaders.GetHeader<string>("identity", "ns");

   return “some data” ;
}

Configuration

  • The service has a binding endpoint that uses netTcpbinding with the default settings.
  • The service has a service behavior configuration to publish metadata.
  • The service has a base address configured.
  • The service behavior is configured with the serviceMedata element to allow metadata exposure.
<system.serviceModel>
      <behaviors>
          <serviceBehaviors>
              <behavior name="BehaviorConfiguration">
                  <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 database.
  • The role is created in the 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\aspnethost' 

Additional Resources