This documentation is archived and is not being maintained.

Message Level Security

Visual Studio 2010

Applies to: Windows Communication Foundation

Published: June 2011

Author: Robert Dizon

This topic contains the following sections.

Web services on the Internet often require that a user name and password be passed in an interoperable format (this is defined in the WS-Security specification) so that they can be authenticated against a custom credential store. Typically, there are also role-based security checks to authorize access to some resources. WCF now supports a claims-based approach to security, which occurs at service boundaries. Claims, which are an example of message-level security, improve upon the older role-based and permission-based security models. In message-level security, all of the security information is encapsulated in the message. Claims can include many types of data, such as identities, role permissions, rights, and even general information about the consumer that is useful to the application. One big advantage to claims-based security is that it supports federated and single sign-on scenarios. For more information about federation services see the following articles. The first is on MSDN and second is on TechNet.

The following diagram illustrates how message-level security, such as claims, secures the channel between the consumer and the provider.

Referenced Image

The following figure illustrates the steps that occur to establish message-level security.

Referenced Image

Here are the steps.

  1. The service consumer establishes a secured message with either the service broker or the service provider that encrypts messages.

  2. The XML gateway validates the integrity of the message and decrypts the necessary information for the service broker to process the message.

  3. The service broker sends the message to the legacy providers via secure legacy channels. Messages that are not being sent to the legacy provider are sent back through the XML gateway where appropriate encryption or digital signatures are applied.

  4. The service provider validates the integrity of the message and decrypts the necessary information for processing.

For additional information on message security in WCF, see "Message Security in WCF" on MSDN at http://msdn.microsoft.com/en-us/library/ms733137.aspx

For example of how to use message security, see Windows Forms Client to Remote WCF Using Message Security on MSDN at http://msdn.microsoft.com/en-us/library/ff648163.aspx

Messaging systems are widely used to enable communication between people. In a typical organizational setting, a message is sent to a person with the assumption that the receiver is the person who is responsible for dealing with the message's contents. From business's point of view, the destination of these messages is organizational roles. A role is an abstract model in an organization, which specifies a set of duties and tasks which are associated with a set of people in the organization. Message security means various things including: confidential messages can be accessed only by authorized entities including roles and users.

The .NET Framework includes role-based security that can be used with Windows client applications, ASP.NET web applications, ASP.NET web services (ASMX), and WCF services. In role-based security, when users are authenticated, a security principal is attached to the executing thread. The principal holds the caller's identity and roles which can be either a Windows account or a custom credential. Role-based security relies on two important interfaces. One is named IPrincipal and the other is named IIdentity. Here are their signatures.


public interface IPrincipal
{
      bool IsInRole(string role);
      IIdentity Identity { get; }
}
public interface IIdentity
{
      string AuthenticationType { get; }
      bool IsAuthenticated { get; }
      string Name { get; }
}   

The implementation of the IPrincipal interface should return true from the IsInRole method if the user belongs to the specified role. The user is identified by the Identity property, which is a type that implements the IIdentity interface. The IIdentity implementation should contain the authenticated user's name and the authentication type.

To understand the role-based security, you should also understand the relevant app.config settings for WCF. Here is an example.

<system.serviceModel>
  <services>
    <service name="RoleBasedServices.SecureServiceInternal" >
      <endpoint contract="RoleBasedServices.ISecureService"  binding="wsHttpBinding" bindingConfiguration="wsHttpWindows" />
    </service>
  </services>
  <bindings>
    <wsHttpBinding>
      <binding name="wsHttpWindows">
        <security mode="Message">
          <message clientCredentialType="Windows" />
        </security>
      </binding>
    </wsHttpBinding>
  </bindings>
  <behavior name="internalServiceBehavior">
    <serviceAuthorization  principalPermissionMode="UseWindowsGroups" />
    <serviceCredentials>
      <windowsAuthentication includeWindowsGroups="true"  allowAnonymousLogons="false" />
    </serviceCredentials>
  </behavior>
</system.serviceModel>

The service configuration setting shown above is for a Windows credential that is passed in message-security mode. When a Windows credential is passed by the client, it is serialized into a security token in the message. This token is authenticated and authorized against the Windows domain with either NTLM or Kerberos configuration setup. The resulting security principal that is attached to the thread is a WindowsPrincipal object with a WindowsIdentity reference.

If the client passes a user name and password that will be authenticated against a custom credential store, you must explicitly configure the authentication and authorization modes. This is because, by default, user name credentials are authenticated against the Windows domain. To perform the configuration, use the MembershipProvider value in the userNamePasswordValidationMode enumeration. This is shown in the following code from an application configuration file (app.config).

<system.serviceModel>
  <behaviors>
    <serviceBehaviors>
      <behavior name="externalServiceBehavior">
        <serviceAuthorization principalPermissionMode="UseAspNetRoles" />
        <serviceCredentials>
          <userNameAuthentication  userNamePasswordValidationMode="MembershipProvider" />
          <serviceCertificate findValue="RPKey" x509FindType="FindBySubjectName" storeLocation="LocalMachine" storeName="My"/>
        </serviceCredentials>
      </behavior>
    </serviceBehaviors>
  </behaviors>
</system.serviceModel> 

The following code is an example of a far more complex WCF configuration. It was written for a scenario that included three SOA, enterprise-class projects. The first project uses forms authentication, and the other two projects uses Windows authentication. All three web applications run in SharePoint as the presentation layer and as the client for the WCF. All the applications use the backend enterprise resource planning (ERP) system as the authoritative source for authentication, and authorization. This configuration file is the one that was used during the development phase of the project, with one of the Windows authentication projects. It illustrates the customizing of the WSHttpBinding.

Sample WCF Configuration
<system.serviceModel>
     <bindings>
         <wsHttpBinding>
            <binding name="WSHttpBinding_IClientService" closeTimeout="00:01:00"
                 openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
                 bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard"
                 maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
                 messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true"
                 allowCookies="false">
                 <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
                     maxBytesPerRead="4096" maxNameTableCharCount="16384" />
                 <reliableSession ordered="true" inactivityTimeout="00:10:00"
                     enabled="false" />
                 <security mode="None">
                     <transport clientCredentialType="Windows" proxyCredentialType="None"
                         realm="" />
                     <message clientCredentialType="Windows" negotiateServiceCredential="true"
                         establishSecurityContext="true" />
                 </security>
             </binding>
         </wsHttpBinding>
     </bindings>
     <client>
         <endpoint address="http://devserver.local:8080/WCFApp2Services.svc" binding="wsHttpBinding"
             bindingConfiguration="WSHttpBinding_IClientService" contract="ClientService.IClientService"
             name="WSHttpBinding_IClientService" />
     </client>
</system.serviceModel>


There is a great deal of information about how to write bindings. Here are a few articles that are on MSDN.

Claims are credentials that are passed in the security headers of messages as security tokens. Each security token is mapped to a set of claims that are added to the security context for each request. A claim describes an individual right or action that is applicable to a particular resource. For example, an identity claim might describe a username, while a proof of possession claim might describe a role or a right to access a particular resource. Claims are represented at runtime as an object of type Claim, which is defined in the System.IdentityModel.Claims namespace. The Claim class includes the following properties.

  • ClaimType: A claim type can be any URI value that identifies the type of claim, such as an email address. The ClaimType static class contains a basic set of claims that are used by WCF, but the class can be customized.

  • Resource: A resource can be of any type, but it should contain the resource being referred to by the claim. For example, an e-mail possession claim would contain an e-mail address as a string.

  • Right: A right can be an URI that identifies either an identity claim, or a possession claim. The Rights static class contains the correct Uri to use.

The following code which is part of ClaimBaseServices.cs demonstrates how to create a sample claim. It programmatically creates a claim that possesses an email address. The Claim object's properties are defined as follows:

ClaimType = http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress

Resource = wcfclaim@testcode.com

Right = http://schemas.xmlsoap.org/ws/2005/05/identity/right/possessproperty

Referenced Image

public void CreateTestClaim()
{
      Claim c = new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress", "wcfclaim@testcode.com", 
                          "http://schemas.xmlsoap.org/ws/2005/05/identity/right/possessproperty");
}

public void CreateTestCompanyClaim()
{
      Claim c = Claim.CreateNameClaim("http://www.company-550eb0a.com/samples/2006/06/issuer");
      Claim[] claims = new Claim[1];
      claims[0] = c;
      ClaimSet issuer = new DefaultClaimSet(claims);
}

A claim set is a collection of claims granted by a particular issuer. For example, the claims extracted from an X.509 token are vouched for by the certificate authority. The certificate authority is therefore the issuer of the claim set. A claim set is represented at runtime by the ClaimSet type. The claim types WindowsClaimSet, UserNameClaimSet, and X509ClaimSet directly inherit from the ClaimSet base type. These are the claim sets generated for Windows, Username, and X.509 tokens. It is important to keep in mind that every security token can be mapped to a set of claims which can then be applied to message level security.

  • A WindowsClaimSet includes information about the identity of the user, plus other information about windows groups and other security identifiers for a Windows token.

Table 4. WindowsClaimSet

Right:ClaimType

Resource

http://schemas.xmlsoap.org/ws/2005/05/identity/right/possessproperty: http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name

domain\\Administrator

http://schemas.xmlsoap.org/ws/2005/05/identity/right/possessproperty: http://schemas.xmlsoap.org/ws/2005/05/identity/claims/sid

S-1-5-21-2747712036-3657831467-4081887108-513

  • A UserNameClaimSet includes a single identity and possess property both indicating the user name.

Table 5. UserNameClaimSet

Right:ClaimType

Resource

http://schemas.xmlsoap.org/ws/2005/05/identity/right/identity: http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name

domain\\Administrator

http://schemas.xmlsoap.org/ws/2005/05/identity/right/possessproperty: http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name

domain\\Administrator

  • A X.509 tokens, the X509ClaimSet describes information related to the certificate.

Table 6. X509ClaimSet

Right:ClaimType

Resource

http://schemas.xmlsoap.org/ws/2005/05/identity/right/identity: http://schemas.xmlsoap.org/ws/2005/05/identity/claims/thumbprint

cb d5 50 10 f1 65 af 3d 3b be a7 03 fb fe 87 28 89 06 e4 b6

http://schemas.xmlsoap.org/ws/2005/05/identity/right/possessproperty: http://schemas.xmlsoap.org/ws/2005/05/identity/claims/x500distinguishedname

CN=SubjectKey

http://schemas.xmlsoap.org/ws/2005/05/identity/right/possessproperty: http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name

SubjectKey

http://schemas.xmlsoap.org/ws/2005/05/identity/right/possessproperty: http://schemas.xmlsoap.org/ws/2005/05/identity/claims/rsa

RSACryptoServiceProvider instance

The issuer of the X509ClaimSet depends on the type of certificate that the object represents. For example, if the certificate is self-issued, so is the claim set. If the certificate is the root certificate, then the issuer should be a Certificate Authority (CA Root) such as Verisign, or Thawte. Here are some guidelines to follow when you are considering whether or not to use claims:

  • For Windows credentials, it is easier to work with role-based security than to use claims and be required to resolve security identifiers (SIDs) to Windows groups.

  • For user name credentials, role-based security is the obvious choice if no roles are included in the claims or roles are defined externally, such as in an Oracle System, SAP System, or Lawson ERP.

  • For certificate credentials, there is no role-based security unless you map certificates to Windows accounts. In this case, you might find claims to be useful for custom authorization. For example, you might have a database that associates certificates with custom roles or claims.

To effectively implement a claims-based model you must consider what types of claims make sense to your application. One way to do this is to start from the functionality that is in the application's presentation layer. Often, it is helpful to use a wireframe view of the application, with screens and sub-screens. Working from the top to the bottom of the wireframe, organize the functionality into CRUD (Create, Read, Update, and Delete) operations that can be associated with specific claims.

The following figures illustrate a wireframe of a sample application. There are two UI elements that can be associated with claims.

Referenced Image

Referenced Image

There are two places in the application that require claims to be mapped to resources. The first CRUD mapping maps a Create claim type in the site (that is, a user privilege or right to create a new object) to the customer's resource, limiting it to UI-1, which is a Web page of the sample wireframe.

The first create claim type is defined as:

http://schemas.xmlsoap.org/ws/2005/05/identity/right/possessproperty: http://schemas.550eb0a.com/samples/2006/06/identity/claims/create

The resource is defined as: http://schemas.550eb0a.com/samples/2006/06/identity/resources/customers

The second read claim type is defined as:

http://schemas.xmlsoap.org/ws/2005/05/identity/right/possessproperty: http://schemas.550eb0a.com/samples/2006/06/identity/claims/read

The resource is defined as: http://schemas.550eb0a.com/samples/2006/06/identity/resources/customers

Retaining the natural grouping of operations, as they appear in the presentation layer, is a recommended practice.

Every source file in the Message-Level Security section is included in a WCF Service Library project solution. The source code naming conventions are similar to the names of the article sections.

The following figure illustrates the project organization.

Referenced Image

To compile the project, you must have the following references.

  • Role-based security requires IRoleBaseServices.cs and RoleBaseServices.cs.

  • Claims-based security requires IClaimBaseService.cs and ClaimBaseServices.cs.

  • WCF security services require ISecurityServices.cs and SecurityServices.cs which are bonus codes for accessing SharePoint rights on user, Active Directory interface for getting practically any information on target user running inside WCF, and other general purpose utilities.

The code can be downloaded in these areas: http://code.msdn.microsoft.com/WCF-Content-based-Routing-71c4a2cc, http://code.msdn.microsoft.com/WCF-Content-based-Routing-b8cb198c, and http://code.msdn.microsoft.com/WCF-Content-based-Routing-c59c49ec

When you must create secure web services, think about the following points.

  • Secure existing web services with current technologies. Use SSL to secure point-to-point communications.

  • Identify additional security requirements that are introduced with new web service functionality.

  • Stay current with the development of WS-Security standards. This will help you to know when standards are being replaced, or are evolving.

  • Identify the security integration points between business partners. Examine their plans to secure their web services.

See the Web Services Security Specification Index page on MSDN for links to the WS-Security standards. It is located at http://msdn.microsoft.com/en-us/library/ms951273.aspx

The Open OASIS WS-Security specification is located at: http://www.oasis-open.org/committees/tc_home.php?wg_abbrev=wss

The Microsoft Security Overview is located at: http://msdn.microsoft.com/en-us/library/ms735093.aspx

The WCF Security Guidance is located at: http://wcfsecurity.codeplex.com/

The Web Services Protocols Binding is located at: http://msdn.microsoft.com/en-us/library/ms730294.aspx

Previous article: Transport Level Security

Continue on to the next article: Advanced WCF Configuration

Show: