How to: Decrypt a SOAP Message Encrypted Using a User Name and Password

The following procedures detail how to configure WSE to decrypt SOAP messages encrypted using a user name and password and how to use policy or code to require that the SOAP <Body> element be encrypted.

To decrypt SOAP messages encrypted using a user name and password

  • In the Web.config file for the Web service, include an <add> Element for <soapExtensionTypes> (WSE for Microsoft .NET) element in the <soapExtensionTypes> section.

    When the SOAP message recipient is a Web service client, this configuration entry is not required. Instead, the base class of the proxy class must be changed to derive from the WebServicesClientProtocol class.

    The following code example shows the configuration entry that must be placed in the Web.config file for WSE to run with a Web service. The type attribute of the <add> Element for <soapExtensionTypes> (WSE for Microsoft .NET) element must be on one line, even though the following sample shows it split across multiple lines for readability.

    <configuration>
       <system.web>
          <webServices>
             <soapExtensionTypes>
                <add type="Microsoft.Web.Services2.WebServicesExtension, 
                Microsoft.Web.Services2,Version=2.0.0.0, Culture=neutral, 
                PublicKeyToken=31bf3856ad364e35" 
                priority="1" group="0"/>
             </soapExtensionTypes>
          </webServices>
       </system.web>
    </configuration>
    

To use policy to require that incoming SOAP messages are encrypted by a user name and password

  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. 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. The value of the Id attribute must be unique to the policy file.
    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 http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#UsernameToken.
      The <TokenType> Element element specifies the type of security token that must be used to encrypt the message.

    The following code example specifies that a UsernameToken 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>http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#UsernameToken</wssp:TokenType>      </wssp:TokenType>
    
  3. Optionally, specify requirements for the token by adding <Claims> Element, <SubjectName> Element, and <UsePassword> Element elements.

    1. Add a <Claims> Element child element to the <SecurityToken> Element element.
    2. Add a <SubjectName> Element child element to the <Claims> Element element.
      The value of the <SubjectName> Element element specifies the user name portion of a UsernameToken. The MatchType attribute of the <SubjectName> Element element specifies how to compare the value of the <SubjectName> Element element with the user name portion of a UsernameToken. The following table lists the valid values for the MatchType attribute.
  1. 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>
    
  2. 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 that 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>
    

To use code to require that the <Body> element of incoming SOAP messages is encrypted using a user name and password

  1. Add a Web service method that processes the UsernameToken.

    1. In Solution Explorer, right-click Service1.asmx, and then select View Code.

    2. Add the following using or Imports directives to Service1.asmx.cs.

      Imports Microsoft.Web.Services2
      Imports Microsoft.Web.Services2.Security
      Imports Microsoft.Web.Services2.Security.Tokens
      Imports System.Security.Cryptography
      
      using Microsoft.Web.Services2;
      using Microsoft.Web.Services2.Security;
      using Microsoft.Web.Services2.Security.Tokens;
      using System.Security.Cryptography;
      
    3. In the class representing the Web service, add code to verify that the <Body> element of the SOAP request was encrypted using a UsernameToken security token.
      The following code example is a Web service method named sayHello that verifies the request was made using SOAP and calls the method named IsMessageEncrypted defined in the next step.

      <WebMethod()>  _
      Public Function sayHello() As String
          Dim requestContext As SoapContext = _
              RequestSoapContext.Current
      
          ' Verify that a SOAP request was received.  
          If requestContext Is Nothing Then
              Throw New ApplicationException( "Either a non-SOAP " + _
                  "request was received or WSE is not properly " + _
                  "installed for the Web application hosting the " + _
                  "Web service.")
          End If
      
          ' Verify that the SOAP body is encrypted.
          If Not IsMessageEncrypted(requestContext) Then
              Throw New ApplicationException("The body of the request" + _
                  " is not encrypted.")
          End If
          Return "Hello"
      End Function
      
      [WebMethod()]
      public string sayHello() 
      {
          SoapContext requestContext = RequestSoapContext.Current;
      
          // Verify that a SOAP request was received.  
          if (requestContext == null)
          {
              throw new ApplicationException( "Either a non-SOAP " +
                  "request was received or WSE is not properly " +
                  "installed for the Web application hosting the " +
                  "Web service.");
          }
          // Verify that the SOAP body is encrypted.
          if (!IsMessageEncrypted(requestContext))
          {
              throw new ApplicationException(
                  "The body of the request is not encrypted.");
          }
          return "Hello";
      }
      
  2. Define a method to verify that a UsernameToken security token encrypted the <Body> element of the SOAP message.

    1. In Solution Explorer, right-click Service1.asmx, and then click View Code.

    2. In the Service1 class, add the code shown in the following code example.
      The following code example verifies that an incoming SOAP message contains a <Body> element that is encrypted using a UsernameToken.

      Private Function IsMessageEncrypted(ByVal context As SoapContext) As Boolean
          Dim element As ISecurityElement
          For Each element In context.Security.Elements
              If (TypeOf (element) Is EncryptedData) Then
                  ' The SoapContext contains a EncryptedData element. 
                  Dim encrypt As EncryptedData = element
                  If TypeOf encrypt.SecurityToken Is UsernameToken Then
                      ' The SOAP body is encrypted using a UsernameToken.
                      Return True
                  End If
              End If
          Next
          Return False
      End Function 
      
      private bool IsMessageEncrypted(SoapContext context)
      {
          foreach (ISecurityElement element in context.Security.Elements)
          {
              if (element is EncryptedData)
              {
                  // The given context contains an EncryptedData element.
                  EncryptedData encrypt = element as EncryptedData;
      
                     // The SOAP message is encrypted.
                      if (encrypt.SecurityToken is UsernameToken)
                          // The SOAP body is encrypted by a UsernameToken.
                          return true;
              }
          }
          return false;
      }
      

Example

The following code example is a policy file specifying that all SOAP messages sent to the http://www.cohowinery.com/SaleWidgets.asmx endpoint have the <Body> element encrypted by a user name and password. Furthermore, the UsernameToken must be for the user name someone and the password must be sent hashed.

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="" />
        <fault policy="" />
      </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: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>http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#UsernameToken</wssp:TokenType>
            <wssp:Claims>
              <wssp:SubjectName MatchType="wssp:Exact">
                someone</wssp:SubjectName> 
              <wssp:UsePassword Type="wssp:PasswordDigest"
                wsp:Usage="wsp:Required" />
            </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 defines a Web service method that verifies that requests are made using SOAP and that the <Body> element is encrypted using a UsernameToken security token

Imports System
Imports System.Web.Services
Imports Microsoft.Web.Services2
Imports Microsoft.Web.Services2.Security
Imports Microsoft.Web.Services2.Security.Tokens

<WebService([Namespace] := "https://www.contoso.com")>  _
Public Class StockService
    Inherits System.Web.Services.WebService

    <WebMethod()> _
    Public Function sayHello() As String
         Dim requestContext As SoapContext = _
         RequestSoapContext.Current

         ' Verify that a SOAP request was received.  
         If requestContext Is Nothing Then
             Throw New ApplicationException("Either a non-SOAP " + _
                 "request was received or WSE is not properly " + _
                 "installed for the Web application hosting the " + _
                 "Web service.")
         End If
         If Not IsMessageEncrypted(requestContext) Then
             Throw New ApplicationException("The body of the request" + _
                " was not encrypted.")
         End If
         Return "Hello"
     End Function

    Private Function IsMessageEncrypted(ByVal context As SoapContext) _
        As Boolean
        Dim element As ISecurityElement
        For Each element In context.Security.Elements
            If (TypeOf (element) Is EncryptedData) Then
                ' The SoapContext contains a EncryptedData element. 
                Dim encrypt As EncryptedData = element
                If TypeOf encrypt.SecurityToken Is UsernameToken Then
                    ' The SOAP body is encrypted using a UsernameToken.
                    Return True
                End If
            End If
        Next
        Return False
    End Function 
End Class
using System;
using System.Web.Services;
using Microsoft.Web.Services2;
using Microsoft.Web.Services2.Security;
using Microsoft.Web.Services2.Security.Tokens;

public class HelloService : System.Web.Services.WebService
{
    [WebMethod]
    public string sayHello() 
    {
        SoapContext requestContext = RequestSoapContext.Current;

        // Verify that a SOAP request was received.  
        if (requestContext == null)
        {
            throw new ApplicationException( "Either a non-SOAP " +
                "request was received or WSE is not properly " +
                "installed for the Web application hosting the " +
                "Web service.");
        }
        // Verify that the SOAP body was encrypted.
        if (!IsMessageEncrypted(requestContext))
        {
            throw new ApplicationException(
                "The body of the request was not encrypted.");
        }
        return "Hello";
    }

    private bool IsMessageEncrypted(SoapContext context)
    {
        foreach (ISecurityElement element in context.Security.Elements)
        {
            if (element is EncryptedData)
            {
                // The given context contains an EncryptedData element.
                EncryptedData encrypt = element as EncryptedData;
    
                   // The SOAP message is encrypted.
                    if (encrypt.SecurityToken is UsernameToken)
                        // The SOAP body is encrypted by a UsernameToken.
                        return true;
            }
        }
        return false;
    }
}

See Also

Tasks

How to: Encrypt a SOAP Message by Using a User Name and Password
How to: Specify the Parts of a SOAP Message That Are Signed or Encrypted
How to: Encrypt a SOAP Message

Reference

UsernameToken