Chapter 14 - Internet – Web to Remote WCF Using Transport Security (Trusted Subsystem, TCP)

- J.D. Meier, Carlos Farre, Jason Taylor, Prashant Bansode, Steve Gregersen, Madhu Sundararajan, Rob Boucher

Applies To

  • Microsoft® Windows Communication Foundation (WCF) 3.5

Scenario

In this scenario, your users do not have Windows accounts and use a Web client to connect over the Internet to an ASP.NET application on an IIS server. The business logic called by the WCF service is backed by a SQL Server data store. The basic model for this application scenario is shown in the following figure.



ch14scenario.jpg

Key Characteristics

This scenario applies to you if:
  • Your users have Web clients.
  • Your user accounts are stored in SQL.
  • Your user roles are stored in SQL.
  • The business logic behind your WCF service does not require fine-grained authorization.
  • Your application transmits 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.

Solution



ch14solution.jpg

Solution Summary Table

In this solution you will:
  • Use username and password to authenticate users against the SQL Server Membership Provider.
  • Use a service account to call WCF from the ASP.NET application.
  • Use a service account to call the SQL Server from WCF.
  • Use SSL 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.
  • Use netTcpBinding to support the TCP transport for improved performance.
  • Host WCF in a Windows Service since IIS does not support the TCP transport.

Note: Due to a limitation with tables on this site, the code in the tables below may be run together when in the same cell. If this is a problem for you, please comment the workitem at
http://www.codeplex.com/CodePlex/WorkItem/View.aspx?WorkItemId=17004

Web Server

Checks Example
IIS - Configuration
A dedicated application pool is created 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.
IIS - Authentication
The IIS virtual directory is configured to use Anonymous access. Users will be allowed to access pages and if required will be redirected to forms authentication page.


Checks Example
ASP.NET - Configuration
ASP.NET database is created for the SQL Membership Provider and SQL Role Provider. Aspnetregsql.exe creates the SQL database to store the user and role information. aspnetregsql -S .\SQLExpress -E -A r m
Connection string is configured to point to the user and role store in SQL Server. The database connection string includes Integrated Security=SSPI or Trusted Connection=Yes for Windows Authentication. <add name="MyLocalSQLServer" connectionString="Initial Catalog=aspnetdb;data source=localhost;Integrated Security=SSPI;" />
Web application process identity is given access permissions on the ASPNET database. Your Web application process identity requires access to the Aspnetdb database. If you host the Web application in Internet Information Services (IIS) 6.0 on Microsoft Windows Server® 2003, the NT AUTHORITY\Network Service account is used by default to run the Web application. -- Create a SQL Server login for the Web application process identity spgrantlogin 'Customdomainserviceaccount -- Grant the login access to the membership database USE aspnetdb GO spgrantdbaccess 'Customdomainserviceaccount', 'Custom Service' -- Add user to database role USE aspnetdb GO spaddrolemember 'aspnetMembershipFullAccess', 'Custom Service' spaddrolemember 'aspnetRolesFullAccess', 'Custom Service'
ASP.NET - Authentication
ASP.NET is configured for Forms authentication. The Web application will authenticate the users. <authentication mode = "Forms" >
ASP.NET application is configured to deny access to all unauthenticated users. Only authenticated users will be able to access the application. <authorization> <deny users="?"/> <allow users="*"/> </authorization>
SqlMembershipProvider is configured to use with Membership feature for forms authentication. The membership feature helps protect credentials, can enforce strong passwords, and provides consistent APIs for user validation and secure user management. The membership feature also automatically creates the authentication ticket for you. <membership defaultProvider="MySqlMembershipProvider"> <providers> <clear/> <add name="MySqlMembershipProvider" connectionStringName="MyLocalSQLServer" applicationName="MyAppName" type="System.Web.Security.SqlMembershipProvider"/> </providers> </membership>
ASP.NET - Authorization
Role Manager feature is enabled and SqlRoleProvider is configured for roles authorization. Role Manager feature allows you to look up users' roles without writing and maintaining code. Additionally, the role providers offer a consistent way for you to check the role membership of your users, regardless of the underlying data store. <roleManager enabled="true" defaultProvider="MySqlRoleProvider" > <providers> <clear/> <add name="MySqlRoleProvider" connectionStringName="MyLocalSQLServer" applicationName="MyAppName" type="System.Web.Security.SqlRoleProvider" /> </providers> </roleManager>
Role-checks are performed using role manager APIs. if (User.IsInRole("Role")) { //business operation }


Checks Example
WCF Proxy
ASP.NET has a proxy reference to the WCF service. The application has access to the WCF metadata to create a service reference. WCFTestService.ServiceClient myService = new WCFTestService.ServiceClient();
Proxy invokes services with the security context of service account . The proxy will automatically invoke WCF operations using the security context of the service account. myService.GetData(123);
WCF Proxy - Caller Identity
For auditing purposes, the identity of the caller can be passed in custom message headers during Proxy call. Additionally custom headers can be defined in message contracts or service contracts. Use transport security to protect against spoofing attacks. if (User.IsInRole("accounting")) { WCFTestService.MyServiceClient proxy = new WCFTestService.MyServiceClient(); using (OperationContextScope scope = new OperationContextScope(proxy.InnerChannel)) { string identity = 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();

Application Server

Checks Example
Windows Service -Configuration
Windows Service is configured to run under a custom domain service account. Use a domain account if possible.
WCF service is hosted in a Windows Service. Since IIS does not support netTcpBinding, host it in Windows Service.



Checks Example
WCF Service - Configuration
Configure the WCF service to use netTcpBinding. NetTcpBinding uses the TCP protocol and provides full support for SOAP security, transactions, and reliability. As client and WCF service both are in the Intranet, this is a good choice from a performance perspective. <endpoint address="" binding="netTcpBinding" bindingConfiguration="" name="TcpBinding" contract="WCFServicecHost.IMyService" />
A mex endpoint is created for publishing the metadata. This is required so that client can add reference to the WCF Service using SvcUtil utility. <endpoint address="Mex" binding="mexTcpBinding" bindingConfiguration="" name="MexEndpoint" contract="IMetadataExchange" />
Service Metadata is configured in service behavior. The service metadata entry is required for the Windows Service host to start. Both HTTP and HTTPS get 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 - Caller Identity
Service retrieves the identity of the caller from the 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 database is configured to use Windows Authentication. The database connection string includes Integrated Security=SSPI or Trusted Connection=Yes. The database connection string includes Integrated Security=SSPI or Trusted Connection=Yes
Database connection is opened using the WCF process identity’s security context. Service does not impersonate the original caller to benefit for connection pooling.


Database Server

Check 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 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 DB. 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 More Info
Browser to Web Server SSL is used between browser and Web Server to protect sensitive data on the wire. Install certificate in the Website. Configure the virtual directory of the Web application to use SSL.
App Server to Database Server You can use IPSec or SSL between the App Server and Database Server to protect sensitive data on the wire.

Analysis

Web Server

Authentication

  • To allow unauthenticated and unauthorized users to access pages and redirect to the login page, anonymous access in IIS is enabled.
  • Forms authentication is a good choice for this scenario because users come from the Internet and have accounts in SQL.
  • The membership feature is a good choice to use with forms authentication, as it allows user authentication without writing and maintaining custom code.

Authorization

  • URL authorization performs role checks against the original caller and restricts access to pages based on role permissions.
  • All authorization checks occur in the Web application before it makes calls 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 Roles Manager is a good choice for this scenario because it allows the application to look up users' roles without writing and maintaining 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.
  • If you need to produce audit logs showing what service operations each user called, 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 the Service account using a least privileged account.

Application Server

Authentication

  • WCF is configured to use Windows Authentication in order to authenticate the ASP.NET service when it makes calls on the WCF Service.

Authorization

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

SQL

  • To reduce the risk of database credentials theft, the database connection string is configured to use Windows Authentication. This choice avoids storing credentials in files and passing 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 IIS 6.0 does not support netTcpBinding, 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.
  • A metadata exchange (mex) endpoint is exposed to make it possible for the client to generate a proxy based on the service definition.

Database Server

  • SQL Server database user roles are preferred to SQL Server application roles to avoid the associated password management and connection pooling issues associated with the use of SQL application roles. Applications activate SQL application roles by calling a built-in stored procedure with a role name and a password. Therefore, you must store the password securely. You must also disable database connection pooling when you use SQL 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. In this way, if the database account changes you don't have to change the permissions on all database objects.

Communication Security

  • SSL protects sensitive data on the wire between the browser and Web server.
  • Transport Security protects sensitive data between the Web Server and App Server.
  • You can use IPSec or SSL between the App Server and Database Server to protect sensitive data on the wire.

Example

Web Server

Code

  • Form is created to perform Forms authentication.
  • Role-authorization occurs before WCF service invocation.
  • ASP.NET calls WCF service if it is authorized.
  • Identity of the original caller is retrieved from the User ticket context.
  • Message Header containing the caller identity is created and passed to the operation context for auditing purposes.

Form to do forms authentication
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Login.aspx.cs" Inherits="Login" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Untitled Page</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
    
    </div>
    <asp:Login ID="Login1"  runat="server">
    </asp:Login>
    <asp:CreateUserWizard ID="CreateUserWizard1" runat="server">
        <WizardSteps>
            <asp:CreateUserWizardStep runat="server" />
            <asp:CompleteWizardStep runat="server" />
        </WizardSteps>
    </asp:CreateUserWizard>
    </form>
</body>
</html>



//Proxy call invocation
using System.ServiceModel;
using System.ServiceModel.Channels;
…
protected void Button1_Click(object sender, EventArgs e)
 {
  if (User.IsInRole("accounting"))
  {
    WCFTestService.MyServiceClient proxy 
         = new WCFTestService.MyServiceClient();
    using (OperationContextScope scope 
         = new OperationContextScope(proxy.InnerChannel))
    {
     string identity = 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

 } //end function

Configuration

  • Windows and anonymous authentication are enabled.
  • Connection string to the SqlMembershipProvider and to the SqlRoleProvider are configured.
  • SQLmembershipProvider is enabled.
  • Only authenticated users are allowed to browse the site.
  • Role Manager is enabled.
<configuration>
   …
<connectionStrings>
   <add name="MyLocalSQLServer" connectionString="Initial 
        Catalog=aspnetdb;data source=10.3.19.60;Integrated Security=SSPI;"/>
</connectionStrings>

<system.web>
  <membership defaultProvider="MySqlMembershipProvider">
     <providers>
	  <clear/>
	  <add name="MySqlMembershipProvider" 
             connectionStringName="MyLocalSQLServer" 
             applicationName="MyAppName" 
             type="System.Web.Security.SqlMembershipProvider"/>
	</providers>
  </membership>

  <roleManager enabled="true" defaultProvider="MySqlRoleProvider">
	<providers>
        <clear/>
	  <add name="MySqlRoleProvider" 
             connectionStringName="MyLocalSQLServer" 
             applicationName="MyAppName" 
             type="System.Web.Security.SqlRoleProvider"/>
	</providers>
  </roleManager>

  <authentication mode="Forms"/>
  <authorization>
    <deny users="?"/>
    <allow users="*"/>
  </authorization>

  <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" validate="false" type=
"System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />

  </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 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 element serviceMedata 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



Last edited Jul 2, 2008 at 7:17 PM by rboucher, version 11

Comments

No comments yet.