How to: Encrypt a SOAP Message By Using a Kerberos Ticket

The following procedures detail how to use policy or code to encrypt a SOAP message by using a Kerberos service ticket. The procedure can be used with both the KerberosToken and KerberosToken2 security tokens. To use the procedure for KerberosToken2 security tokens, do the following:

For more details about the difference between the KerberosToken and KerberosToken2 security tokens, see Differences between KerberosToken and KerberosToken2.

To use policy to encrypt a SOAP message by using a Kerberos Ticket

  1. Define a policy assertion and encryption requirements by adding <Policy> Element (WSE for Microsoft .NET) (1) and <Confidentiality> Element elements.

    1. Add a <Policy> Element (WSE for Microsoft .NET) (1) element to the policy file for the application. Add the <Policy> Element (WSE for Microsoft .NET) (1) element as a child element of the <policies> Element element.
      The <Policy> Element (WSE for Microsoft .NET) (1) element defines criteria that a SOAP message must meet. The criteria are specified as child elements of the <Policy> Element (WSE for Microsoft .NET) (1) element. The Id attribute value provides a name that is used by the <request> Element (WSE for Microsoft .NET), <response> Element (WSE for Microsoft .NET), and <fault> Element elements to refer to the policy assertion when applying the policy to an endpoint.
    2. Add a <Confidentiality> Element child element to the <Policy> Element (WSE for Microsoft .NET) (1) element.
      The <Confidentiality> Element element defines encryption requirements. The Usage attribute value of "Required" specifies that encryption is required, and additional requirements are specified in child elements.

    The following code example defines a policy assertion named policy-c0a22319-6b89-49ff-9b82-bdbac5f04618 and specifies that there are encryption requirements.

                  <wsp:Policy wsu:Id="policy-c0a22319-6b89-49ff-9b82-bdbac5f04618"
      xmlns:wsp="https://schemas.xmlsoap.org/ws/2002/12/policy"
      xmlns:wsa="https://schemas.xmlsoap.org/ws/2004/03/addressing">
      <wssp:Confidentiality wsp:Usage="wsp:Required"     xmlns:wssp="https://schemas.xmlsoap.org/ws/2002/12/secext">
    
  2. Specify the token type by adding <KeyInfo> Element (WSE for Microsoft .NET) (1), <SecurityToken> Element, and <TokenType> Element elements.

    1. Add a <KeyInfo> Element (WSE for Microsoft .NET) (1) child element to the <Confidentiality> Element element.
    2. Add a <SecurityToken> Element child element to the <TokenInfo> Element element.
    3. Add a <TokenType> Element child element to the <SecurityToken> Element element and set its value to https://schemas.xmlsoap.org/ws/2003/12/kerberos/Kerberosv5ST.
      The <TokenType> Element element specifies the type of security token that must be used to encrypt the SOAP message.

    The following code example specifies that a KerberosToken security token must be used to encrypt the SOAP message.

                  <wssp:Confidentiality wsp:Usage="wsp:Required"
                    xmlns:wssp="https://schemas.xmlsoap.org/ws/2002/12/secext">
                    <wssp:KeyInfo>
                      <wssp:SecurityToken>
                        <wssp:TokenType>https://schemas.xmlsoap.org/ws/2003/12/kerberos/Kerberosv5ST</wssp:TokenType>
    
    
  3. Optionally, specify requirements about the token by adding <Claims> Element, <ServiceName> Element, and <TokenIssuer> Element (WSE for Microsoft .NET) (1) elements

    1. Add a <Claims> Element child element to the <SecurityToken> Element element.

    2. Add a <ServiceName> Element child element to the <Claims> Element element.
      The <ServiceName> Element element specifies the service principal name. The service principal name is in the following format: host/<hostname>@<domain>, where hostname is the name of the computer receiving the SOAP message and domain is the fully qualified domain name of the Kerberos realm in which the host computer resides.

      Note

      Kerberos tickets are obtained using the current user's credentials. Therefore, when a <ServiceName> Element element is specified, WSE attempts to obtain a Kerberos service ticket from the Key Distribution Center (KDC) for communication between the current user and the computer specified in the <ServiceName> Element element.

    3. Add a <TokenIssuer> Element (WSE for Microsoft .NET) (1) child element to the <SecurityToken> Element element
      The <TokenIssuer> Element (WSE for Microsoft .NET) (1) element specifies the domain, also known as the Kerberos realm, which issued the Kerberos ticket. WSE does not support Kerberos delegation, so this must be the same realm the recipient is a member of.

      Note

      The value of the <TokenIssuer> Element (WSE for Microsoft .NET) (1) must be in uppercase.

      The following code example specifies that a Kerberos service ticket must be used to encrypt SOAP messages. Furthermore, the Kerberos service ticket must be obtained from a KDC in the COHOWINERY realm for the computer named computer1.

                        <wssp:Confidentiality wsp:Usage="wsp:Required"
                          xmlns:wssp="https://schemas.xmlsoap.org/ws/2002/12/secext">
        <wssp:KeyInfo>
          <SecurityToken xmlns="https://schemas.xmlsoap.org/ws/2002/12/secext">
            <wssp:TokenType>https://schemas.xmlsoap.org/ws/2003/12/kerberos/Kerberosv5ST</wssp:TokenType>
              <wssp:TokenIssuer>COHOWINERY</wssp:TokenIssuer>        <wssp:Claims>          <wssp:ServiceName>host/computer1@cohowinery.com</wssp:ServiceName>        </wssp:Claims>
            </SecurityToken>
          </wssp:KeyInfo>
      
  4. Map the policy assertion to an endpoint by adding an <endpoint> Element element. Optionally, designate the policy as the default for all SOAP messages by adding the <defaultOperation> Element element.

    1. Add an <endpoint> Element element to the <mappings> Element element, and set the uri attribute value to the URI of the application.
      The <endpoint> Element element maps a policy assertion to an endpoint. The uri attribute value specifies the URI of the service to which the policy is mapped.
    2. Add a <defaultOperation> Element child element to the <endpoint> Element element.
      The <defaultOperation> Element element specifies the default policy for all operations at the URI specified in the uri attribute.
    3. Add <request> Element (WSE for Microsoft .NET), <response> Element (WSE for Microsoft .NET), and <fault> Element child elements to the <defaultOperation> Element element. The value of the policy attribute must match the value of the Id attribute of the <Policy> Element (WSE for Microsoft .NET) (1) element that defines the policy assertion.

    The following code example sets the default policy for all SOAP messages sent to the http://www.cohowinery.com/SaleWidgets.asmx endpoint to the policy-c0a22319-6b89-49ff-9b82-bdbac5f04618 policy assertion.

    <mappings xmlns:wse="https://schemas.microsoft.com/wse/2003/06/Policy">
      <endpoint uri="http://www.cohowinery.com/SaleWidgets.asmx">
        <defaultOperation>
          <request policy="#policy-c0a22319-6b89-49ff-9b82-bdbac5f04618" />
          <response policy="#policy-c0a22319-6b89-49ff-9b82-bdbac5f04618" />
          <fault policy="#policy-c0a22319-6b89-49ff-9b82-bdbac5f04618" />
        </defaultOperation>
      </endpoint>
    </mappings>
    
  5. Specify the XML elements to be encrypted by adding a <MessageParts> Element for <Confidentiality> Element element to the <Confidentiality> Element element.

    1. Add a <MessageParts> Element for <Confidentiality> Element child element to the <Confidentiality> Element element in the policy file for the application, and set the Dialect attribute value to "https://schemas.xmlsoap.org/2002/12/wsse#part".
    2. Specify the parts of the message to be encrypted by listing them, separated by spaces, as the value of the <MessageParts> element.
      When using policy, WSE only supports specifying the <Body> element must be encrypted.

    The following code example specifies that the <Body> element must be encrypted.

    <wssp:MessageParts Dialect="https://schemas.xmlsoap.org/2002/12/wsse#part">
      wsp:Body()
    </wssp:MessageParts>
    
  6. Optionally, add a KerberosToken security token that meets the policy requirements to the PolicyEnforcementSecurityTokenCache to the code where you are sending the SOAP message.

    This step is optional, as WSE will look through the following caches in the specified order to find a KerberosToken security token that matches the Policy and if it does not succeed it will attempt to request a Kerberos ticket from a KDC in the current domain or the one specified in the <TokenIssuer> Element (WSE for Microsoft .NET) (1) element:

    1. The Tokens collection of the SoapContext associated with the SOAP message.
    2. The PolicyEnforcementSecurityTokenCache token cache.

    WSE uses the first KerberosToken security token that it finds that matches the Policy.

    The following code example adds a KerberosToken to the PolicyEnforcementSecurityTokenCache.

    PolicyEnforcementSecurityTokenCache.GlobalCache.Add( token )
    
    PolicyEnforcementSecurityTokenCache.GlobalCache.Add( token );
    

To use code to encrypt a SOAP message by using a Kerberos ticket

  1. Open the Web service client project in Visual Studio .NET 2003.

  2. Add references to the Microsoft.Web.Services2,System.Web.Services, and System.Security assemblies.

    1. On the Project menu, click Add Reference.
    2. Click the .NET tab, select Microsoft.Web.Services2.dll, and then click Select.
    3. On the .NET tab, select System.Web.Services.dll, and then click Select.
    4. On the .NET tab, select System.Security.dll, and then click Select.
    5. Click OK.
  3. Add a Web reference to the Web service that is to receive the SOAP message encrypted with the shared secret.

    1. On the Project menu, click Add Web Reference.
    2. In the Add Web Reference dialog box, type the URL for the Web service in the Address box, and then click the arrow icon.
    3. Verify that the items in the Available references box are the items you want to reference in your project, and then click Add Reference.
  4. Edit the proxy class to derive from the WebServicesClientProtocol.

    1. In Solution Explorer, right-click the Reference.cs file for the Web reference just added, and then click View Code.

      Note

      If the Reference.cs file containing the proxy class is not visible, click the show all files icon on the Solution Explorer toolbar, and then expand the Reference.map node.

    2. Change the base class of the proxy class to the Microsoft.Web.Services2.WebServicesClientProtocol class.
      This modifies the proxy class to emit WS-Addressing and WS-Security SOAP headers when communicating with the Web service. The following code example modifies a proxy class named Service1 to derive from Microsoft.Web.Services2.WebServicesClientProtocol.

      Public Class Service1
         Inherits Microsoft.Web.Services2.WebServicesClientProtocol
      
      public class Service1 : Microsoft.Web.Services2.WebServicesClientProtocol {
      

      Note

      If you select Update Web Reference in Visual Studio .NET 2003, the proxy class is regenerated, the base class is reset to the SoapHttpClientProtocol class, and you must change the class that the proxy class derives from again.

  5. Add Imports or using directives to the top of the file that communicates with the Web service.

    1. In Solution Explorer, right-click the file containing the client code, and then click View Code.

    2. At the top of the file, add the directives as shown in the following code example.

      Imports Microsoft.Web.Services2
      Imports Microsoft.Web.Services2.Security
      Imports Microsoft.Web.Services2.Security.Tokens
      Imports Microsoft.Web.Services2.Security.Kerberos
      
      using Microsoft.Web.Services2;
      using Microsoft.Web.Services2.Security;
      using Microsoft.Web.Services2.Security.Tokens;
      using Microsoft.Web.Services2.Security.Kerberos;
      
  6. Add code to create a KerberosToken security token.

    The hostname variable is the name of the computer hosting the target Web service, and the dnsDomainName variable is the Kerberos realm that the host is a member of. The Kerberos realm is needed only when the SOAP message sender resides in a different domain or realm then the target Web service.

    Dim kerbToken As New KerberosToken("host/" + hostname + _
      "@" + dnsDomainName)
    
    KerberosToken kerbToken = new KerberosToken( "host/" + hostname + "@" + dnsDomainName);
    
  7. Specify that the SOAP request must be encrypted by the Kerberos ticket.

    For information about encrypting portions of the SOAP message other than the defaults, see How to: Specify the Parts of a SOAP Message That Are Signed or Encrypted.

    1. Get the SoapContext value for the SOAP request that is being made to the Web service. Service1 is the SoapContext name of the proxy class to the Web service in the following code example.

      Dim svc As New Service1()
      Dim requestContext As SoapContext = svc.RequestSoapContext
      
      Service1 svc = new Service1();
      SoapContext requestContext = svc.RequestSoapContext;
      
    2. Create a new instance of the EncryptedData class by using the KerberosToken security token.

      Dim enc As New EncryptedData(kerbToken)
      
      EncryptedData enc = new EncryptedData(kerbToken);
      
    3. Add the encrypted data to the WS-Security SOAP header.

      RequestContext.Security.Elements.Add(enc)
      
      RequestContext.Security.Elements.Add(enc);
      
    4. Specify the time-to-live (TTL) for the SOAP message to diminish the chance of someone intercepting the message and replaying it.
      The following code example sets the TTL to 1 minute.

      requestContext.Security.Timestamp.TtlInSeconds = 60
      
      requestContext.Security.Timestamp.TtlInSeconds = 60;
      
    5. Call the Web service.

      svc.sayHello()
      
      svc.sayHello();
      

Example

The following code example is a policy file specifying that all SOAP messages sent to the http://www.cohowinery.com/SaleWidgets.asmx endpoint must encrypt the <Body> element by using a Kerberos service ticket issued from the COHOWINERY realm for communication between the current user and the computer named computer1@cohowinery.com.

Note

This code example is designed to demonstrate WSE features and is not intended for production use.

<?xml version="1.0" encoding="utf-8"?>
<policyDocument xmlns="https://schemas.microsoft.com/wse/2003/06/Policy">
  <mappings xmlns:wse="https://schemas.microsoft.com/wse/2003/06/Policy">
    <endpoint uri="http://www.cohowinery.com/SaleWidgets.asmx">
      <defaultOperation>
        <request policy="#policy-c0a22319-6b89-49ff-9b82-bdbac5f04618" />
        <response policy="#policy-c0a22319-6b89-49ff-9b82-bdbac5f04618" />
        <fault policy="#policy-c0a22319-6b89-49ff-9b82-bdbac5f04618" />
      </defaultOperation>
    </endpoint>
  </mappings>
  <policies xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
    <wsp:Policy wsu:Id="policy-c0a22319-6b89-49ff-9b82-bdbac5f04618"
      xmlns:wsp="https://schemas.xmlsoap.org/ws/2002/12/policy"
      xmlns:wsa="https://schemas.xmlsoap.org/ws/2004/03/addressing" >
      <SecurityToken xmlns="https://schemas.xmlsoap.org/ws/2002/12/secext">
        <wssp:TokenType>https://schemas.xmlsoap.org/ws/2003/12/kerberos/Kerberosv5ST</wssp:TokenType>
        <wssp:TokenIssuer>COHOWINERY</wssp:TokenIssuer>
        <wssp:Claims>
          <wssp:ServiceName>host/computer1@cohowinery.com</wssp:ServiceName>
        </wssp:Claims>
      </SecurityToken>
      <wssp:Confidentiality wsp:Usage="wsp:Required"
        xmlns:wssp="https://schemas.xmlsoap.org/ws/2002/12/secext">
        <wssp:KeyInfo>
          <SecurityToken xmlns="https://schemas.xmlsoap.org/ws/2002/12/secext">
            <wssp:TokenType>https://schemas.xmlsoap.org/ws/2003/12/kerberos/Kerberosv5ST</wssp:TokenType>
            <wssp:TokenIssuer>COHOWINERY</wssp:TokenIssuer>
            <wssp:Claims>
              <wssp:ServiceName>host/computer1@cohowinery.com</wssp:ServiceName>
            </wssp:Claims>
          </SecurityToken>
        </wssp:KeyInfo>
        <wssp:MessageParts Dialect="https://schemas.xmlsoap.org/2002/12/wsse#part">
            wsp:Body()
        </wssp:MessageParts>
      </wssp:Confidentiality >
    </wsp:Policy>
  </policies>
</policyDocument>

The following code example creates a KerberosToken security token, and then encrypts a SOAP request by using the token.

Try
    Dim kerbToken As New KerberosToken( "host/" + hostname + _
      "@" + domainName)
    Dim svc As New Proxy.Service1() 
    Dim requestContext As SoapContext = svc.RequestSoapContext
   
    ' Set the TTL to one minute.
    requestContext.Security.Timestamp.TtlInSeconds = 60
   
    ' Add the security token. 
    requestContext.Security.Tokens.Add(kerbToken)
    ' Encrypt the SOAP request by using the Kerberos ticket.
    requestContext.Security.Elements.Add(new EncryptedData(kerbToken))

    MessageBox.Show( svc.sayHello() )
Catch ex As Exception
    MessageBox.Show( ex.ToString() )
End Try 
try 
{
    KerberosToken kerbToken = new KerberosToken("host/" + hostname +
      "@" + domainName);

    Proxy.Service1 svc = new Proxy.Service1();
        SoapContext requestContext = svc.RequestSoapContext;

    // Set the TTL to one minute.
    requestContext.Security.Timestamp.TtlInSeconds = 60;
    
    // Encrypt the SOAP request by using the Kerberos ticket.
    requestContext.Security.Elements.Add(new
      EncryptedData(kerbToken));

    MessageBox.Show( svc.sayHello() );
}
catch (Exception ex) 
{
    MessageBox.Show( ex.ToString() );
}

See Also

Tasks

How to: Decrypt a SOAP Message Encrypted Using a Kerberos Ticket

Reference

KerberosToken

Other Resources

Kerberos Ticket