How to: Digitally Sign a Custom SOAP Header

This procedure details the steps to digitally sign a custom SOAP header in a custom policy assertion. For complete details about signing a SOAP message, see How to: Digitally Sign a SOAP Message. For more details about creating a custom policy assertion, see How to: Create a Custom Policy Assertion that Secures SOAP Messages.

To digitally sign a custom SOAP header

  1. Create a custom policy assertion.

    For more details about creating custom policy assertions, see How to: Create a Custom Policy Assertion that Secures SOAP Messages.

  2. In the output SOAP filter for the client or the Web service that signs SOAP messages, override the SecureMessage method.

    The following code example overrides the SecureMessage method for the client output SOAP filter.

    public override void SecureMessage(SoapEnvelope envelope, Security security)
    {
    
  3. Obtain the security token with which you want to sign the SOAP message.

    The following code example creates a new instance of a UsernameToken security token.

    Dim token As New UsernameToken(Environment.UserName, "passwordEquivalent", PasswordOption.SendPlainText)
    
    UsernameToken token =
        new UsernameToken(Environment.UserName, "passwordEquivalent", PasswordOption.SendPlainText);
    
  4. Add a security token to the WS-Security SOAP header.

    The following code example adds the UsernameToken security token to the WS-Security SOAP header.

    security.Tokens.Add(token)
    
    security.Tokens.Add(token);
    
  5. Create a new instance of the MessageSignature class, passing in the security token.

    Dim sig As New MessageSignature(token)
    
    MessageSignature sig = new MessageSignature(token);
    
  6. Get the custom SOAP header that you want to sign using the SoapEnvelope that was passed into the SecureMessage method.

    The following code example gets the OrderTimeHeader custom SOAP header from the SoapEnvelope.

    ' Find the OrderTimeHeader custom SOAP header.
    Dim header As New XmlQualifiedName("OrderTimeHeader")
    Dim index As Integer
    For index = 0 To envelope.Header.ChildNodes.Count - 1
    
        Dim child As XmlElement = envelope.Header.ChildNodes(index)
    
        If (child Is Nothing And child.LocalName = header.Name AndAlso child.NamespaceURI = header.Namespace) Then
    
    // Find the OrderTimeHeader custom SOAP header.
    XmlQualifiedName header = new XmlQualifiedName("OrderTimeHeader");
    for (int index = 0; index < envelope.Header.ChildNodes.Count; index++)
    {
        XmlElement child = envelope.Header.ChildNodes[index] as XmlElement;
    
        if (child != null && child.LocalName == header.Name && child.NamespaceURI == header.Namespace)
        {
    
  7. Create a new instance of the SignatureReference class, passing in the value of the Id field with a #Id prefix.

    ' Create a signature reference for the custom SOAP header.
    Dim soapRef As _
      New SignatureReference("#Id:" + child.Attributes("Id").Value)
    soapRef.AddTransform(New Microsoft.Web.Services3.Security.Xml.XmlDsigExcC14NTransform())
    
    // Create a signature reference for the custom SOAP header.
    SignatureReference soapRef =
      new SignatureReference("#Id:" + child.Attributes["Id"].Value);
    soapRef.AddTransform(new Microsoft.Web.Services3.Security.Xml.XmlDsigExcC14NTransform());
    
  8. Add the instance of the SignatureReference class to the MessageSignature, using the AddReference method.

    ' Add the signature reference to the digital signature.
    sig.AddReference(soapRef)
    
    // Add the signature reference to the digital signature.
    sig.AddReference(soapRef);
    
  9. Add the MessageSignature to the WS-Security SOAP header to the SOAP message.

    ' Add the digital signature to the SOAP message.
    security.Elements.Add(sig)
    
    // Add the digital signature to the SOAP message.
    security.Elements.Add(sig);
    

Example

The following code example creates a new UsernameToken security token, and then signs the OrderTimeHeader custom soap header by using the token.

public override void SecureMessage(SoapEnvelope envelope, Security security)
{
    UsernameToken token =
        new UsernameToken(Environment.UserName, "passwordEquivalent", PasswordOption.SendPlainText);

    security.Tokens.Add(token);

    MessageSignature sig = new MessageSignature(token);

    // Find the OrderTimeHeader custom SOAP header.
    XmlQualifiedName header = new XmlQualifiedName("OrderTimeHeader");
    for (int index = 0; index < envelope.Header.ChildNodes.Count; index++)
    {
        XmlElement child = envelope.Header.ChildNodes[index] as XmlElement;

        if (child != null && child.LocalName == header.Name && child.NamespaceURI == header.Namespace)
        {
            // Create a signature reference for the custom SOAP header.
            SignatureReference soapRef =
              new SignatureReference("#Id:" + child.Attributes["Id"].Value);
            soapRef.AddTransform(new Microsoft.Web.Services3.Security.Xml.XmlDsigExcC14NTransform());
            // Add the signature reference to the digital signature.
            sig.AddReference(soapRef);
        }
    }
    // Add the digital signature to the SOAP message.
    security.Elements.Add(sig);
}

See Also

Tasks

How to: Digitally Sign a SOAP Message
How to: Create a Custom Policy Assertion that Secures SOAP Messages
How to: Determine Which Parts of a SOAP Message Were Signed or Encrypted

Other Resources

Signing Custom SOAP Headers