Share via


How to: Digitally Sign a SOAP Message

WSE allows you to digitally sign your SOAP messages by writing code or allowing an administrator to set the digital signature requirements using policy.

The procedures in this topic outline just the steps to sign the SOAP message and do not include the steps it takes to obtain a specific security token or send the SOAP message. For step-by-step procedures for the specific type of security token you are using, see Supported Security Tokens.

To use policy to sign a SOAP message

  1. Define a policy assertion and digital signature requirements by adding <Policy> Element (WSE for Microsoft .NET) (1) and <Integrity> 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 an <Integrity> Element child element to the <Policy> Element (WSE for Microsoft .NET) (1) element.
      The <Integrity> Element element defines digital signature requirements. The Usage attribute value of "Required" specifies that a signature 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 digital signature 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:Integrity wsp:Usage="wsp:Required" 
    
  2. Specify the token type by adding <TokenInfo> Element, <SecurityToken> Element, and <TokenType> Element elements.

    1. Add a <TokenInfo> Element child element to the <Integrity> 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 the URI for the specific security token.
      The <TokenType> Element element specifies the type of security token that must be used to create the digital signature.

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

    <wssp:Integrity wsp:Usage="wsp:Required"
      xmlns:wssp="https://schemas.xmlsoap.org/ws/2002/12/secext">
      <wssp:TokenInfo>    <wssp:SecurityToken>      <wssp:TokenType>https://schemas.xmlsoap.org/ws/2003/12/kerberos/Kerberosv5ST</wssp:TokenType>
    
  3. 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 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>
    
  4. Specify the XML elements to be signed by adding a <MessageParts> Element for <Integrity> Element element to the <Integrity> Element element.

    1. Add a <MessageParts> Element for <Integrity> Element child element to the <Integrity> 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 signed by listing them, separated by spaces, as the value of the <MessageParts> Element for <Integrity> Element element.

    The following code example specifies that the <Body> element and the To, Action, MessageID, and From headers are signed.

    <wssp:MessageParts Dialect="https://schemas.xmlsoap.org/2002/12/wsse#part">
      wsp:Body() wsp:Header(wsa:To) wsp:Header(wsa:Action)
      wsp:Header(wsa:MessageID) wsp:Header(wsa:From)
    </wssp:MessageParts>
    
  5. Optionally, add the security token that meets the policy requirements to the PolicyEnforcementSecurityTokenCache of the application where you are sending the SOAP message.

    This step is optional because WSE looks in the following caches in the specified order to find a security token that matches the policy:

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

    WSE uses the first security token that it finds that matches the policy.

    The following code example adds a security token to the PolicyEnforcementSecurityTokenCache.

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

To write code to sign a SOAP message

  1. Obtain the security token that you want to sign the SOAP message with.

    The following code example calls a GetSecurityToken method to get an X509SecurityToken.

    Dim signatureToken As X509SecurityToken = GetSecurityToken()
    
    X509SecurityToken signatureToken = GetSecurityToken();
    
  2. Get the SoapContext for the SOAP message

    The following code example gets the SoapContext for a SOAP request, where Service1 is the name of the proxy class to the Web service.

    Dim svc As New Service1()
    Dim requestContext As SoapContext = svc.RequestSoapContext
    
    Service1 svc = new Service1();
    SoapContext requestContext = svc.RequestSoapContext;
    
  3. Add the security token to the WS-Security SOAP header.

    requestContext.Security.Tokens.Add(signatureToken)
    
    requestContext.Security.Tokens.Add(signatureToken);
    
  4. Create a new instance of the MessageSignature class using the security token just added to the WS-Security SOAP header.

    Dim sig As New MessageSignature(signatureToken)
    
    MessageSignature sig = new MessageSignature(signatureToken);
    
  5. Add the digital signature to the WS-Security SOAP header.

    The following code example adds the digital signature to the SoapContext for a SOAP request.

    RequestContext.Security.Elements.Add(sig)
    
    requestContext.Security.Elements.Add(sig);
    

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 have the <Body> element and the To, Action, MessageID, and From headers signed by 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" >
      <wssp:Integrity wsp:Usage="wsp:Required"
        xmlns:wssp="https://schemas.xmlsoap.org/ws/2002/12/secext">
        <wssp:TokenInfo>
          <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:TokenInfo>
        <wssp:MessageParts Dialect="https://schemas.xmlsoap.org/2002/12/wsse#part">
          wsp:Body() wsp:Header(wsa:To) wsp:Header(wsa:Action)
          wsp:Header(wsa:MessageID) wsp:Header(wsa:From)
        </wssp:MessageParts>
      </wssp:Integrity>
    </wsp:Policy>
  </policies>
</policyDocument>

The following code example creates a new KerberosToken security token, and then signs 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)

    ' Specify the security token to sign the message with.
    requestContext.Security.Elements.Add(new MessageSignature(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;
    
    // Add the security token.                
    requestContext.Security.Tokens.Add(kerbToken);
    // Specify the security token to sign the message with.
    requestContext.Security.Elements.Add(new
      MessageSignature(kerbToken));

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

See Also

Reference

<Integrity> Element
MessageSignature Class

Concepts

Digitally Signing a SOAP Message