Share via


How to: Create a Custom Policy Assertion That Supports Secure Conversations

To establish a secure conversation, either set the EstablishSecurityContext attribute to true for a turnkey security assertion or use a custom policy assertion that supports secure conversations. A custom policy assertion that supports secure conversations has filters that derive from the secure conversation filter classes, such as the SecureConversationServiceReceiveSecurityFilter class. This topic details how to create a custom policy assertion that supports secure conversations. For more information on the turnkey security assertions, see Turnkey Security Assertions.

To create a custom policy assertion that supports secure conversations

  1. Open the project containing the Web service or Web service client using Visual Studio 2005.

  2. Add a new class to the project.

    1. In Solution Explorer, right-click the project name, and then click Add New Item….
    2. Select Class and provide a name for the class.
    3. Click Add to close the dialog box and add the class to the project.
  3. Add references to the Microsoft.Web.Services3, System.Web.Services, System.Security, and System.Xml assemblies.

    1. In Solution Explorer, right-click the project name, and then click Add Reference.
    2. Click the .NET tab, press and hold the CTRL key, and click Microsoft.Web.Services3.dll, System.Web.Services.dll, System.Security.dll, and System.Xml.dll.
    3. Click OK to close the dialog box.
  4. Add the Imports statements or using directives that are shown in the following code example to the top of the file for the new class.

    Imports System
    Imports System.Collections.Generic
    Imports System.Text
    Imports System.Security.Cryptography.X509Certificates
    Imports System.Xml
    
    Imports Microsoft.Web.Services3
    Imports Microsoft.Web.Services3.Design
    Imports Microsoft.Web.Services3.Security
    Imports Microsoft.Web.Services3.Security.Tokens
    
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Security.Cryptography.X509Certificates;
    using System.Xml; 
    
    using Microsoft.Web.Services3;
    using Microsoft.Web.Services3.Design;
    using Microsoft.Web.Services3.Security;
    using Microsoft.Web.Services3.Security.Tokens;
    
  5. Create a custom input filter for the Web service.

    1. Add a class that derives from the SecureConversationServiceReceiveSecurityFilter class.
      The following code example defines a class that derives from the SecureConversationServiceReceiveSecurityFilter class.

      Class CustomSecurityServerInputFilter
          Inherits SecureConversationServiceReceiveSecurityFilter
      
      class CustomSecurityServerInputFilter : SecureConversationServiceReceiveSecurityFilter
      {
      
    2. Specify the security requirements for incoming SOAP requests to the Web service that are not secured using a secure conversation by overriding the ValidateMessageSecurity method.
      When the EstablishSecurityContext property is set to true, a secure conversation is established between the client and the Web service. Security for security token requests are validated using the ValidateMessageSecurity method (takes 3 parameters). Other SOAP requests are validated using the ValidateMessageSecurity method (2 parameters), which cannot be overridden.
      When a secure conversation is not established, the ValidateMessageSecurity method (3 parameters) validates SOAP requests received by the Web service.
      The following code example specifies that SOAP messages that are sent to the Web service that are not part of a secure conversation must be signed and encrypted. The security tokens that are used to sign and encrypt the SOAP message are saved in the OperationState property, which can be accessed later by a Web service's custom output filter if a SOAP response is returned to the client.

      Public Overrides Sub ValidateMessageSecurity(ByVal envelope As SoapEnvelope, ByVal security As Security, ByVal response As MessageProtectionRequirements)
          Dim clientToken As SecurityToken = Nothing
          Dim serverToken As SecurityToken = Nothing
      
          ' Ensure incoming SOAP messages are signed and encrypted.
          Dim elem As ISecurityElement
          For Each elem In security.Elements
              If TypeOf elem Is MessageSignature Then
                  Dim sig As MessageSignature = CType(elem, MessageSignature)
                  clientToken = sig.SigningToken
              End If
      
              If TypeOf elem Is EncryptedData Then
                  Dim enc As EncryptedData = CType(elem, EncryptedData)
                  serverToken = enc.SecurityToken
              End If
          Next elem
      
          If clientToken Is Nothing OrElse serverToken Is Nothing Then
              Throw New Exception("Incoming message did not meet security requirements")
          End If
          Dim state As New RequestState(clientToken, serverToken)
      
          envelope.Context.OperationState.Set(state)
      
      End Sub 'ValidateMessageSecurity
      
      public override void ValidateMessageSecurity(SoapEnvelope envelope, Security security, MessageProtectionRequirements response)
      {
          SecurityToken clientToken = null;
          SecurityToken serverToken = null;
      
          // Ensure incoming SOAP messages are signed and encrypted.
          foreach (ISecurityElement elem in security.Elements)
          {
              if (elem is MessageSignature)
              {
                  MessageSignature sig = (MessageSignature)elem;
                  clientToken = sig.SigningToken;
              }
      
              if (elem is EncryptedData)
              {
                  EncryptedData enc = (EncryptedData)elem;
                  serverToken = enc.SecurityToken;
              }
          }
      
          if (clientToken == null || serverToken == null)
              throw new Exception("Incoming message did not meet security requirements");
      
          RequestState state = new RequestState(clientToken, serverToken);
      
          envelope.Context.OperationState.Set(state);
      }
      
  6. Create a custom output filter for the Web service.

    1. Add a class that derives from the SecureConversationServiceSendSecurityFilter class.
      The following example defines a class that derives from the SecureConversationServiceSendSecurityFilter class.

      Class CustomSecurityServerOutputFilter
          Inherits SecureConversationServiceSendSecurityFilter
      
      class CustomSecurityServerOutputFilter : SecureConversationServiceSendSecurityFilter
      {
      
    2. Secure SOAP responses that are sent from the Web service by overriding the SecureMessage method.
      When the EstablishSecurityContext property is set to true, a secure conversation is established between the client and the Web service. Security for security token responses are secured using the SecureMessage method (takes 3 parameters). Other SOAP responses are secured using the SecureMessage method (2 parameters), which cannot be overridden.
      When a secure conversation is not established, the SecureMessage method (3 parameters) validates SOAP responses sent by the Web service.
      The following code example signs and encrypts SOAP responses using the security tokens that encrypted and signed the SOAP request, respectively. The security tokens are retrieved from the OperationState property that was set by the Web service's custom input filter.

      Public Overrides Sub SecureMessage(ByVal envelope As SoapEnvelope, ByVal security As Security, ByVal request As MessageProtectionRequirements)
          Dim state As RequestState = envelope.Context.OperationState.Get(Of RequestState)()
          ' Sign the message with the Web service's security token.
          security.Tokens.Add(state.ServerToken)
          security.Elements.Add(New MessageSignature(state.ServerToken))
      
          ' Encrypt the message with the client's security token.
          security.Elements.Add(New EncryptedData(state.ClientToken))
      
      End Sub 'SecureMessage
      
      public override void SecureMessage(SoapEnvelope envelope, Security security, MessageProtectionRequirements request)
      {
          RequestState state = envelope.Context.OperationState.Get<RequestState>();
      
          // Sign the message with the Web service's security token.
          security.Tokens.Add(state.ServerToken);
          security.Elements.Add(new MessageSignature(state.ServerToken));
      
          // Encrypt the message with the client's security token.
          security.Elements.Add(new EncryptedData(state.ClientToken));
      }
      
  7. Create a custom input filter for the client.

    1. Add a class that derives from the SecureConversationClientReceiveSecurityFilter class.
      The following code example defines a class that derives from the SecureConversationClientReceiveSecurityFilter class.

      Class CustomSecurityClientInputFilter
          Inherits SecureConversationClientReceiveSecurityFilter
      
      class CustomSecurityClientInputFilter : SecureConversationClientReceiveSecurityFilter
      {
      
    2. Enforce the security requirements for SOAP responses that are received by the client by overriding the ValidateMessageSecurity method.
      When the EstablishSecurityContext property is set to true, a secure conversation is established between the client and the Web service. Security for security token responses are validated using the ValidateMessageSecurity method (takes 3 parameters). Other SOAP responses are secured using the ValidateMessageSecurity method (2 parameters), which cannot be overridden.
      When a secure conversation is not established, the ValidateMessageSecurity method (3 parameters) validates SOAP responses that are received by the client.
      The following code example ensures that SOAP responses are signed using the security token that is used to encrypt the SOAP request and that is encrypted by the security token that signed the SOAP request. The security tokens are retrieved from the OperationState property that was set by the client's custom output filter.

      Public Overrides Sub ValidateMessageSecurity(ByVal envelope As SoapEnvelope, ByVal security As Security, ByVal request As MessageProtectionRequirements)
          Dim state As RequestState
          Dim signed As Boolean = False
          Dim encrypted As Boolean = False
      
          ' Get the request state out of the operation state.
          state = envelope.Context.OperationState.Get(Of RequestState)()
      
          ' Make sure the message was signed with the server's security token.
          Dim elem As ISecurityElement
          For Each elem In security.Elements
              If TypeOf elem Is MessageSignature Then
                  Dim sig As MessageSignature = CType(elem, MessageSignature)
      
                  If sig.SigningToken.Equals(state.ServerToken) Then
                      signed = True
                  End If
              End If
              If TypeOf elem Is EncryptedData Then
                  Dim enc As EncryptedData = CType(elem, EncryptedData)
      
                  If enc.SecurityToken.Equals(state.ClientToken) Then
                      encrypted = True
                  End If
              End If
          Next elem
          If Not signed OrElse Not encrypted Then
              Throw New Exception("Response message does not meet security requirements")
          End If
      
      End Sub 'ValidateMessageSecurity
      
      public override void ValidateMessageSecurity(SoapEnvelope envelope, Security security, MessageProtectionRequirements request)
      {
          RequestState state;
          bool signed = false;
          bool encrypted = false;
      
          // Get the request state out of the operation state.
          state = envelope.Context.OperationState.Get<RequestState>();
      
          // Make sure the message was signed with the server's security token.
          foreach (ISecurityElement elem in security.Elements)
          {
              if (elem is MessageSignature)
              {
                  MessageSignature sig = (MessageSignature)elem;
      
                  if (sig.SigningToken.Equals(state.ServerToken))
                      signed = true;
              }
      
              if (elem is EncryptedData)
              {
                  EncryptedData enc = (EncryptedData)elem;
      
                  if (enc.SecurityToken.Equals(state.ClientToken))
                      encrypted = true;
              }
          }
      
          if (!signed || !encrypted)
              throw new Exception("Response message does not meet security requirements");
      }
      
    3. Override the GetUnattachedTokensCore method.
      The GetUnattachedTokensCore method retrieves security tokens that a Web service did not include in SOAP responses that are not secured using a secure conversation.
      The following code example returns the security tokens that were used to protect the SOAP request.

      Public Overrides Function GetUnattachedTokensCore(ByVal context As SoapContext) As IEnumerable(Of SecurityToken)
          Return New SecurityToken() {Me.serviceX509Token, Me.clientX509Token}
      End Function
      
      public override IEnumerable<SecurityToken> GetUnattachedTokensCore(SoapContext context)
      {
      
          return new SecurityToken[] {this.serviceX509Token, this.clientX509Token };
      }
      
  8. Create a custom output filter for the client.

    1. Add a class that derives from the SecureConversationClientSendSecurityFilter class.
      The following code example defines a class that derives from the SecureConversationClientSendSecurityFilter class.

      Class CustomSecurityClientOutputFilter
          Inherits SecureConversationClientSendSecurityFilter
      
      class CustomSecurityClientOutputFilter : SecureConversationClientSendSecurityFilter
      {
      
    2. Secure SOAP responses that are sent from the client by overriding the SecureMessage method.
      When the EstablishSecurityContext property is set to true, a secure conversation is established between the client and the Web service. Security for security token requests are secured using the SecureMessage method (takes 3 parameters). Other SOAP requests are secured using the SecureMessage method (2 parameters), which cannot be overridden.
      When a secure conversation is not established, the SecureMessage method (3 parameters) secures SOAP responses sent by the Web service.
      The following code example signs and encrypts SOAP responses using the security tokens that are created in the custom filter's constructor. The security tokens that are used to sign and encrypt the SOAP message are saved in the OperationState property, which can be accessed later by a client's custom output filter to verify security requirements on SOAP responses that are returned by the Web service.

      Public Overrides Sub SecureMessage(ByVal envelope As SoapEnvelope, ByVal security As Security, ByVal request As MessageProtectionRequirements)
          If envelope Is Nothing Then
              Throw New ArgumentNullException("envelope")
          End If
          If security Is Nothing Then
              Throw New ArgumentNullException("security")
          End If
          If request Is Nothing Then
              Throw New ArgumentNullException("request")
          End If
          ' Sign the SOAP message with the client's security token.
          security.Tokens.Add(clientToken)
      
          security.Elements.Add(New MessageSignature(clientToken))
      
          ' Encrypt the SOAP message with the client's security token.
          security.Elements.Add(New EncryptedData(serverToken))
      
          ' Encrypt the client's security token with the server's security token.
          security.Elements.Add(New EncryptedData(serverToken, "#" + clientToken.Id))
      
          ' Store the client and server security tokens in the request state.
          Dim state As New RequestState(clientToken, serverToken)
      
          ' Store the request state in the proxy's operation state. 
          ' This makes these tokens accessible when SOAP responses are 
          ' verified to have sufficient security requirements.
          envelope.Context.OperationState.Set(state)
      
      End Sub 'SecureMessage
      
      public override void SecureMessage(SoapEnvelope envelope, Security security, MessageProtectionRequirements request)
      {
          if (envelope == null)
              throw new ArgumentNullException("envelope");
          if (security == null)
              throw new ArgumentNullException("security");
          if (request == null)
              throw new ArgumentNullException("request");
      
          // Sign the SOAP message with the client's security token.
          security.Tokens.Add(clientToken);
      
          security.Elements.Add(new MessageSignature(clientToken));
      
          // Encrypt the SOAP message with the client's security token.
          security.Elements.Add(new EncryptedData(serverToken));
      
          // Encrypt the client's security token with the server's security token.
          security.Elements.Add(new EncryptedData(serverToken, "#" + clientToken.Id));
      
          // Store the client and server security tokens in the request state.
          RequestState state = new RequestState(clientToken, serverToken);
      
          // Store the request state in the proxy's operation state. 
          // This makes these tokens accessible when SOAP responses are 
          // verified to have sufficient security requirements.
          envelope.Context.OperationState.Set(state);
      }
      
  9. Create a class that represents the custom policy assertion.

    1. Create a class that derives from the SecurityPolicyAssertion class.
      The following code example defines a class that derives from the SecurityPolicyAssertion class.

      Public Class CustomSecurityAssertion
          Inherits SecurityPolicyAssertion
      
      public class CustomSecurityAssertion : SecurityPolicyAssertion
      {
      
    2. Specify the Web service's custom input filter by overriding the CreateServiceInputFilter method.
      When a custom policy assertion does not enforce security on SOAP requests that are sent to the Web service, set the return value of the CreateServiceInputFilter method to a null reference (Nothing in Visual Basic).
      The following code example adds a custom input filter for the Web service.

      Public Overrides Function CreateServiceInputFilter(ByVal context As FilterCreationContext) As SoapFilter
          Return New CustomSecurityServerInputFilter(Me)
      
      End Function 'CreateServiceInputFilter
      
      public override SoapFilter CreateServiceInputFilter(FilterCreationContext context)
      {
          return new CustomSecurityServerInputFilter(this);
      }
      
    3. Specify the Web service's custom output filter by overriding the CreateServiceOutputFilter method.
      When a custom policy assertion does not enforce security on SOAP responses that are sent by the Web service, set the return value of the CreateServiceOutputFilter method to a null reference (Nothing in Visual Basic).
      The following code example adds a custom output filter for the Web service.

      Public Overrides Function CreateServiceOutputFilter(ByVal context As FilterCreationContext) As SoapFilter
          Return New CustomSecurityServerOutputFilter(Me)
      
      End Function 'CreateServiceOutputFilter
      
      public override SoapFilter CreateServiceOutputFilter(FilterCreationContext context)
      {
          return new CustomSecurityServerOutputFilter(this);
      }
      
    4. Specify the client's custom input filter by overriding the CreateClientInputFilter method.
      When a custom policy assertion does not enforce security on SOAP responses that are received by the client, set the return value of the CreateClientInputFilter method to a null reference (Nothing in Visual Basic)
      The following code example adds a custom input filter for the client.

      Public Overrides Function CreateClientInputFilter(ByVal context As FilterCreationContext) As SoapFilter
          Return New CustomSecurityClientInputFilter(Me)
      
      End Function 'CreateClientInputFilter
      
      public override SoapFilter CreateClientInputFilter(FilterCreationContext context)
      {
          return new CustomSecurityClientInputFilter(this);
      }
      
    5. Specify the client's custom output filter by overriding the CreateClientOutputFilter method.
      When a custom policy assertion does not enforce security on SOAP requests that are sent by the client, set the return value of the CreateClientOutputFilter method to a null reference (Nothing in Visual Basic).
      The following code example adds a custom output filter for the client.

      Public Overrides Function CreateClientOutputFilter(ByVal context As FilterCreationContext) As SoapFilter
          Return New CustomSecurityClientOutputFilter(Me)
      
      End Function 'CreateClientOutputFilter
      
      public override SoapFilter CreateClientOutputFilter(FilterCreationContext context)
      {
          return new CustomSecurityClientOutputFilter(this);
      }
      
    6. Add code to parse the custom XML elements and attributes that can be placed in a policy file for this custom policy assertion by overriding the ReadXml method.
      Like the turnkey security assertions, custom policy assertions can optionally provide an XML element that is used to specify the custom policy assertion's options in a policy file. The XML element can contain child elements and attributes that specify the options for the custom policy assertion.
      A System.Xml.XmlReader is passed into the ReadXml method with the reader positioned on the XML element for the custom policy assertion. The name of the XML element is specified when the custom policy assertion is registered in the policy file using an <extension> Element. Use the System.Xml.XmlReader to retrieve the custom policy assertion's options that are set in the policy file.
      In the ReadXml method call the ReadAttributes method to have the SecurityPolicyAssertion class parse the XML attributes natively supported by that class, including the EstablishSecurityContext attribute.
      Typically, it is best to provide support for reading an XML element from a policy file for the custom policy assertion, so that policy for the application can be configured at deployment time to match the application's environment.
      The following code example verifies that the current element is named CustomSecurityAssertion and then reads it. To see an example policy file with the custom policy assertion, see How to: Secure an Application Using a Custom Policy Assertion.

      Public Overrides Sub ReadXml(ByVal reader As System.Xml.XmlReader, ByVal extensions As IDictionary(Of String, Type))
          If (True) Then
              Dim isEmpty As Boolean = reader.IsEmptyElement
              MyBase.ReadAttributes(reader)
              reader.ReadStartElement("CustomSecurityAssertion")
              If Not isEmpty Then
                  If reader.MoveToContent() = XmlNodeType.Element AndAlso reader.Name = "clientToken" Then
                      reader.ReadStartElement()
                      reader.MoveToContent()
                      ' Get the registed security token provider for X.509 certificate security credentials. 
                      Dim type As Type = extensions(reader.Name)
                      Dim instance As Object = Activator.CreateInstance(type)
      
                      If instance Is Nothing Then
                          Throw New InvalidOperationException(String.Format(System.Globalization.CultureInfo.CurrentCulture, "Unable to instantiate policy extension of type {0}.", type.AssemblyQualifiedName))
                      End If
      
                      Dim clientProvider As TokenProvider(Of X509SecurityToken) = CType(instance, TokenProvider(Of X509SecurityToken))
      
                      ' Read the child elements that provide the details about the client's X.509 certificate. 
                      clientProvider.ReadXml(reader, extensions)
                      Me.ClientX509TokenProvider = clientProvider
                      reader.ReadEndElement()
                  End If
                  If reader.MoveToContent() = XmlNodeType.Element AndAlso reader.Name = "serviceToken" Then
                      reader.ReadStartElement()
                      reader.MoveToContent()
      
                      ' Get the registed security token provider for X.509 certificate security credentials. 
                      Dim type As Type = extensions(reader.Name)
                      Dim instance As Object = Activator.CreateInstance(type)
      
                      If instance Is Nothing Then
                          Throw New InvalidOperationException(String.Format(System.Globalization.CultureInfo.CurrentCulture, "Unable to instantiate policy extension of type {0}.", type.AssemblyQualifiedName))
                      End If
      
                      Dim serviceProvider As TokenProvider(Of X509SecurityToken) = CType(instance, TokenProvider(Of X509SecurityToken))
      
                      ' Read the child elements that provide the details about the Web service's X.509 certificate.
                      serviceProvider.ReadXml(reader, extensions)
                      Me.ServiceX509TokenProvider = serviceProvider
                      reader.ReadEndElement()
                  End If
                  MyBase.ReadElements(reader, extensions)
                  reader.ReadEndElement()
              End If
          End If
      End Sub
      
      public override void ReadXml(System.Xml.XmlReader reader, IDictionary<string, Type> extensions)
      {
          bool isEmpty = reader.IsEmptyElement;
          base.ReadAttributes(reader);
            reader.ReadStartElement("CustomSecurityAssertion");
          if (!isEmpty)
          {
              if (reader.MoveToContent() == XmlNodeType.Element && reader.Name == "clientToken")
              {
                  reader.ReadStartElement();
                  reader.MoveToContent();
                  // Get the registed security token provider for X.509 certificate security credentials. 
                  Type type = extensions[reader.Name];
                  object instance = Activator.CreateInstance(type);
      
                  if (instance == null)
                      throw new InvalidOperationException(String.Format(System.Globalization.CultureInfo.CurrentCulture, "Unable to instantiate policy extension of type {0}.", type.AssemblyQualifiedName));
      
                  TokenProvider<X509SecurityToken> clientProvider = instance as TokenProvider<X509SecurityToken>;
      
                  // Read the child elements that provide the details about the client's X.509 certificate. 
                  clientProvider.ReadXml(reader, extensions);
                  this.ClientX509TokenProvider = clientProvider;
                  reader.ReadEndElement();
              }
              if (reader.MoveToContent() == XmlNodeType.Element && reader.Name == "serviceToken")
              {
                  reader.ReadStartElement();
                  reader.MoveToContent();
      
                  // Get the registed security token provider for X.509 certificate security credentials. 
                  Type type = extensions[reader.Name];
                  object instance = Activator.CreateInstance(type);
      
                  if (instance == null)
                      throw new InvalidOperationException(String.Format(System.Globalization.CultureInfo.CurrentCulture, "Unable to instantiate policy extension of type {0}.", type.AssemblyQualifiedName));
      
                  TokenProvider<X509SecurityToken> serviceProvider = instance as TokenProvider<X509SecurityToken>;
                  // Read the child elements that provide the details about the Web service's X.509 certificate.
                  serviceProvider.ReadXml(reader, extensions);
                  this.ServiceX509TokenProvider = serviceProvider;
                  reader.ReadEndElement();
              }
              base.ReadElements(reader, extensions);
              reader.ReadEndElement();
          }
      }
      
    7. Add code to return the set of policy extensions supported by the custom policy assertion by overriding the GetExtensions method.
      Override the GetExtensions method to associate the name of the XML element that is used to represent the policy assertion in a policy file with the type that implements the policy assertion.

      Public Overrides Function GetExtensions() As IEnumerable(Of KeyValuePair(Of String, Type))
      
          ' Add the CustomSecurityAssertion custom policy assertion to the list of registered
          ' policy extensions.
          Dim extensions As New List(Of KeyValuePair(Of String, Type))
          extensions.Add(New KeyValuePair(Of String, Type)("CustomSecurityAssertion", Me.GetType()))
          If Not (serviceX509TokenProviderValue Is Nothing) Then
              Dim innerExtensions As IEnumerable(Of KeyValuePair(Of String, Type)) = serviceX509TokenProviderValue.GetExtensions()
              ' Add any policy extensions that read child elements of the <serviceToken> element
              ' to the list of registered policy extensions.
              If Not (innerExtensions Is Nothing) Then
                  Dim extension As KeyValuePair(Of String, Type)
                  For Each extension In innerExtensions
                      extensions.Add(extension)
                  Next
              End If
          End If
          If Not (clientX509TokenProviderValue Is Nothing) Then
              ' Add any policy extensions that read child elements of the <clientToken> element
              ' to the list of registered policy extensions.
              Dim innerExtensions As IEnumerable(Of KeyValuePair(Of String, Type)) = clientX509TokenProviderValue.GetExtensions()
              If Not (innerExtensions Is Nothing) Then
                  Dim extension As KeyValuePair(Of String, Type)
                  For Each extension In innerExtensions
                      extensions.Add(extension)
                  Next
              End If
          End If
      
          Return extensions
      
      End Function
      
      public override IEnumerable<KeyValuePair<string, Type>> GetExtensions()
      {
          // Add the CustomSecurityAssertion custom policy assertion to the list of registered
          // policy extensions.
          List<KeyValuePair<string, Type>> extensions = new List<KeyValuePair<string, Type>>();
          extensions.Add(new KeyValuePair<string, Type>("CustomSecurityAssertion", this.GetType()));
          if (serviceX509TokenProviderValue != null)
          {
              // Add any policy extensions that read child elements of the <serviceToken> element
              // to the list of registered policy extensions.
              IEnumerable<KeyValuePair<string, Type>> innerExtensions = serviceX509TokenProviderValue.GetExtensions();
              if (innerExtensions != null)
              {
                  foreach (KeyValuePair<string, Type> extension in innerExtensions)
                  {
                      extensions.Add(extension);
                  }
              }
          }
          if (clientX509TokenProviderValue != null)
          {
              // Add any policy extensions that read child elements of the <clientToken> element
              // to the list of registered policy extensions.
              IEnumerable<KeyValuePair<string, Type>> innerExtensions = clientX509TokenProviderValue.GetExtensions();
              if (innerExtensions != null)
              {
                  foreach (KeyValuePair<string, Type> extension in innerExtensions)
                  {
                      extensions.Add(extension);
                  }
              }
          }
          return extensions;
      }
      

Example

The following code example demonstrates how to create a custom policy assertion that supports secure conversations.

Imports System
Imports System.Collections.Generic
Imports System.Text
Imports System.Security.Cryptography.X509Certificates
Imports System.Xml

Imports Microsoft.Web.Services3
Imports Microsoft.Web.Services3.Design
Imports Microsoft.Web.Services3.Security
Imports Microsoft.Web.Services3.Security.Tokens
Namespace CustomPolicyAssertions
    Public Class CustomSecurityAssertion
        Inherits SecurityPolicyAssertion
        Dim serviceX509TokenProviderValue As TokenProvider(Of X509SecurityToken)
        Dim clientX509TokenProviderValue As TokenProvider(Of X509SecurityToken)

        Public Property ClientX509TokenProvider() As TokenProvider(Of X509SecurityToken)
            Get
                Return clientX509TokenProviderValue
            End Get
            Set(ByVal value As TokenProvider(Of X509SecurityToken))
                clientX509TokenProviderValue = value
            End Set
        End Property

        Property ServiceX509TokenProvider() As TokenProvider(Of X509SecurityToken)
            Get
                Return serviceX509TokenProviderValue
            End Get
            Set(ByVal value As TokenProvider(Of X509SecurityToken))
                serviceX509TokenProviderValue = value
            End Set
        End Property


        Public Sub New()

        End Sub 'New

        Public Overrides Function CreateClientOutputFilter(ByVal context As FilterCreationContext) As SoapFilter
            Return New CustomSecurityClientOutputFilter(Me)

        End Function 'CreateClientOutputFilter


        Public Overrides Function CreateClientInputFilter(ByVal context As FilterCreationContext) As SoapFilter
            Return New CustomSecurityClientInputFilter(Me)

        End Function 'CreateClientInputFilter


        Public Overrides Function CreateServiceInputFilter(ByVal context As FilterCreationContext) As SoapFilter
            Return New CustomSecurityServerInputFilter(Me)

        End Function 'CreateServiceInputFilter


        Public Overrides Function CreateServiceOutputFilter(ByVal context As FilterCreationContext) As SoapFilter
            Return New CustomSecurityServerOutputFilter(Me)

        End Function 'CreateServiceOutputFilter
        Public Overrides Sub ReadXml(ByVal reader As System.Xml.XmlReader, ByVal extensions As IDictionary(Of String, Type))
            If (True) Then
                Dim isEmpty As Boolean = reader.IsEmptyElement
                MyBase.ReadAttributes(reader)
                reader.ReadStartElement("CustomSecurityAssertion")
                If Not isEmpty Then
                    If reader.MoveToContent() = XmlNodeType.Element AndAlso reader.Name = "clientToken" Then
                        reader.ReadStartElement()
                        reader.MoveToContent()
                        ' Get the registed security token provider for X.509 certificate security credentials. 
                        Dim type As Type = extensions(reader.Name)
                        Dim instance As Object = Activator.CreateInstance(type)

                        If instance Is Nothing Then
                            Throw New InvalidOperationException(String.Format(System.Globalization.CultureInfo.CurrentCulture, "Unable to instantiate policy extension of type {0}.", type.AssemblyQualifiedName))
                        End If

                        Dim clientProvider As TokenProvider(Of X509SecurityToken) = CType(instance, TokenProvider(Of X509SecurityToken))

                        ' Read the child elements that provide the details about the client's X.509 certificate. 
                        clientProvider.ReadXml(reader, extensions)
                        Me.ClientX509TokenProvider = clientProvider
                        reader.ReadEndElement()
                    End If
                    If reader.MoveToContent() = XmlNodeType.Element AndAlso reader.Name = "serviceToken" Then
                        reader.ReadStartElement()
                        reader.MoveToContent()

                        ' Get the registed security token provider for X.509 certificate security credentials. 
                        Dim type As Type = extensions(reader.Name)
                        Dim instance As Object = Activator.CreateInstance(type)

                        If instance Is Nothing Then
                            Throw New InvalidOperationException(String.Format(System.Globalization.CultureInfo.CurrentCulture, "Unable to instantiate policy extension of type {0}.", type.AssemblyQualifiedName))
                        End If

                        Dim serviceProvider As TokenProvider(Of X509SecurityToken) = CType(instance, TokenProvider(Of X509SecurityToken))

                        ' Read the child elements that provide the details about the Web service's X.509 certificate.
                        serviceProvider.ReadXml(reader, extensions)
                        Me.ServiceX509TokenProvider = serviceProvider
                        reader.ReadEndElement()
                    End If
                    MyBase.ReadElements(reader, extensions)
                    reader.ReadEndElement()
                End If
            End If
        End Sub

        Public Overrides Function GetExtensions() As IEnumerable(Of KeyValuePair(Of String, Type))

            ' Add the CustomSecurityAssertion custom policy assertion to the list of registered
            ' policy extensions.
            Dim extensions As New List(Of KeyValuePair(Of String, Type))
            extensions.Add(New KeyValuePair(Of String, Type)("CustomSecurityAssertion", Me.GetType()))
            If Not (serviceX509TokenProviderValue Is Nothing) Then
                Dim innerExtensions As IEnumerable(Of KeyValuePair(Of String, Type)) = serviceX509TokenProviderValue.GetExtensions()
                ' Add any policy extensions that read child elements of the <serviceToken> element
                ' to the list of registered policy extensions.
                If Not (innerExtensions Is Nothing) Then
                    Dim extension As KeyValuePair(Of String, Type)
                    For Each extension In innerExtensions
                        extensions.Add(extension)
                    Next
                End If
            End If
            If Not (clientX509TokenProviderValue Is Nothing) Then
                ' Add any policy extensions that read child elements of the <clientToken> element
                ' to the list of registered policy extensions.
                Dim innerExtensions As IEnumerable(Of KeyValuePair(Of String, Type)) = clientX509TokenProviderValue.GetExtensions()
                If Not (innerExtensions Is Nothing) Then
                    Dim extension As KeyValuePair(Of String, Type)
                    For Each extension In innerExtensions
                        extensions.Add(extension)
                    Next
                End If
            End If

            Return extensions

        End Function
        Public Overrides Sub WriteXml(ByVal writer As System.Xml.XmlWriter)

            If writer Is Nothing Then
                Throw New ArgumentNullException("writer")
            End If
            writer.WriteStartElement("CustomSecurityAssertion")
            MyBase.WriteAttributes(writer)

            If Not (Me.clientX509TokenProviderValue Is Nothing) Then
                writer.WriteStartElement("clientToken")
                Me.clientX509TokenProviderValue.WriteXml(writer)
                writer.WriteEndElement()
            End If

            If Not (Me.serviceX509TokenProviderValue Is Nothing) Then
                writer.WriteStartElement("serviceToken")
                Me.serviceX509TokenProviderValue.WriteXml(writer)
                writer.WriteEndElement()
            End If

            MyBase.WriteElements(writer)

            writer.WriteEndElement()

        End Sub 'WriteXml 

        Class RequestState
            Private clientTokenValue As SecurityToken
            Private serverTokenValue As SecurityToken


            Public Sub New(ByVal cToken As SecurityToken, ByVal sToken As SecurityToken)
                clientTokenValue = cToken
                serverTokenValue = sToken

            End Sub 'New


            Public ReadOnly Property ClientToken() As SecurityToken
                Get
                    Return clientTokenValue
                End Get
            End Property

            Public ReadOnly Property ServerToken() As SecurityToken
                Get
                    Return serverTokenValue
                End Get
            End Property
        End Class 'RequestState 
        Class CustomSecurityServerInputFilter
            Inherits SecureConversationServiceReceiveSecurityFilter

            Public Sub New(ByVal parentAssertion As CustomSecurityAssertion)
                MyBase.New(parentAssertion)

            End Sub 'New


            Public Overrides Sub ValidateMessageSecurity(ByVal envelope As SoapEnvelope, ByVal security As Security, ByVal response As MessageProtectionRequirements)
                Dim clientToken As SecurityToken = Nothing
                Dim serverToken As SecurityToken = Nothing

                ' Ensure incoming SOAP messages are signed and encrypted.
                Dim elem As ISecurityElement
                For Each elem In security.Elements
                    If TypeOf elem Is MessageSignature Then
                        Dim sig As MessageSignature = CType(elem, MessageSignature)
                        clientToken = sig.SigningToken
                    End If

                    If TypeOf elem Is EncryptedData Then
                        Dim enc As EncryptedData = CType(elem, EncryptedData)
                        serverToken = enc.SecurityToken
                    End If
                Next elem

                If clientToken Is Nothing OrElse serverToken Is Nothing Then
                    Throw New Exception("Incoming message did not meet security requirements")
                End If
                Dim state As New RequestState(clientToken, serverToken)

                envelope.Context.OperationState.Set(state)

            End Sub 'ValidateMessageSecurity
        End Class 'CustomSecurityServerInputFilter 


        Class CustomSecurityServerOutputFilter
            Inherits SecureConversationServiceSendSecurityFilter


            Public Sub New(ByVal parentAssertion As CustomSecurityAssertion)
                MyBase.New(parentAssertion)

            End Sub 'New

            Public Overrides Sub SecureMessage(ByVal envelope As SoapEnvelope, ByVal security As Security, ByVal request As MessageProtectionRequirements)
                Dim state As RequestState = envelope.Context.OperationState.Get(Of RequestState)()
                ' Sign the message with the Web service's security token.
                security.Tokens.Add(state.ServerToken)
                security.Elements.Add(New MessageSignature(state.ServerToken))

                ' Encrypt the message with the client's security token.
                security.Elements.Add(New EncryptedData(state.ClientToken))

            End Sub 'SecureMessage
        End Class 'CustomSecurityServerOutputFilter 

        Class CustomSecurityClientInputFilter
            Inherits SecureConversationClientReceiveSecurityFilter
            Private serviceX509Token As X509SecurityToken
            Private clientX509Token As X509SecurityToken


            Public Sub New(ByVal assertion As CustomSecurityAssertion)
                MyBase.New(assertion)
                If Not (assertion.ServiceX509TokenProvider Is Nothing) Then
                    Me.serviceX509Token = assertion.ServiceX509TokenProvider.GetToken()
                End If
                If Not (assertion.ClientX509TokenProvider Is Nothing) Then
                    Me.clientX509Token = assertion.ClientX509TokenProvider.GetToken()
                End If

            End Sub 'New

            Public Overrides Sub ValidateMessageSecurity(ByVal envelope As SoapEnvelope, ByVal security As Security, ByVal request As MessageProtectionRequirements)
                Dim state As RequestState
                Dim signed As Boolean = False
                Dim encrypted As Boolean = False

                ' Get the request state out of the operation state.
                state = envelope.Context.OperationState.Get(Of RequestState)()

                ' Make sure the message was signed with the server's security token.
                Dim elem As ISecurityElement
                For Each elem In security.Elements
                    If TypeOf elem Is MessageSignature Then
                        Dim sig As MessageSignature = CType(elem, MessageSignature)

                        If sig.SigningToken.Equals(state.ServerToken) Then
                            signed = True
                        End If
                    End If
                    If TypeOf elem Is EncryptedData Then
                        Dim enc As EncryptedData = CType(elem, EncryptedData)

                        If enc.SecurityToken.Equals(state.ClientToken) Then
                            encrypted = True
                        End If
                    End If
                Next elem
                If Not signed OrElse Not encrypted Then
                    Throw New Exception("Response message does not meet security requirements")
                End If

            End Sub 'ValidateMessageSecurity
            Public Overrides Function GetUnattachedTokensCore(ByVal context As SoapContext) As IEnumerable(Of SecurityToken)
                Return New SecurityToken() {Me.serviceX509Token, Me.clientX509Token}
            End Function
        End Class 'CustomSecurityClientInputFilter

        Class CorrelationState
            Inherits SerializableTokenWrapper(Of EncryptedKeyToken)

            Public Sub New()
                MyBase.New()
            End Sub 'New

            Public Sub New(ByVal token As EncryptedKeyToken)
                MyBase.New(token)

            End Sub 'New
        End Class 'CorrelationState
        Class CustomSecurityClientOutputFilter
            Inherits SecureConversationClientSendSecurityFilter
            Private clientToken As SecurityToken
            Private serverToken As SecurityToken



            Public Sub New(ByVal parentAssertion As CustomSecurityAssertion)
                MyBase.New(parentAssertion)
                ' Get the client security token.
                Dim clientX509Provider As New X509TokenProvider(StoreLocation.CurrentUser, StoreName.My, "CN=WSE2QuickStartClient")
                clientToken = clientX509Provider.GetToken()

                ' Get the server security token.
                Dim serverX509Provider As New X509TokenProvider(StoreLocation.LocalMachine, StoreName.My, "CN=WSE2QuickStartServer")
                serverToken = serverX509Provider.GetToken()

            End Sub 'New

            Public Overrides Sub SecureMessage(ByVal envelope As SoapEnvelope, ByVal security As Security, ByVal request As MessageProtectionRequirements)
                If envelope Is Nothing Then
                    Throw New ArgumentNullException("envelope")
                End If
                If security Is Nothing Then
                    Throw New ArgumentNullException("security")
                End If
                If request Is Nothing Then
                    Throw New ArgumentNullException("request")
                End If
                ' Sign the SOAP message with the client's security token.
                security.Tokens.Add(clientToken)

                security.Elements.Add(New MessageSignature(clientToken))

                ' Encrypt the SOAP message with the client's security token.
                security.Elements.Add(New EncryptedData(serverToken))

                ' Encrypt the client's security token with the server's security token.
                security.Elements.Add(New EncryptedData(serverToken, "#" + clientToken.Id))

                ' Store the client and server security tokens in the request state.
                Dim state As New RequestState(clientToken, serverToken)

                ' Store the request state in the proxy's operation state. 
                ' This makes these tokens accessible when SOAP responses are 
                ' verified to have sufficient security requirements.
                envelope.Context.OperationState.Set(state)

            End Sub 'SecureMessage
        End Class 'CustomSecurityClientOutputFilter 
    End Class 'CustomSecurityAssertion
End Namespace
using System;
using System.Collections.Generic;
using System.Text;
using System.Security.Cryptography.X509Certificates;
using System.Xml; 

using Microsoft.Web.Services3;
using Microsoft.Web.Services3.Design;
using Microsoft.Web.Services3.Security;
using Microsoft.Web.Services3.Security.Tokens;

namespace CustomPolicyAssertions
{
    public class CustomSecurityAssertion : SecurityPolicyAssertion
    {
        TokenProvider<X509SecurityToken> serviceX509TokenProviderValue;
        TokenProvider<X509SecurityToken> clientX509TokenProviderValue;

        public TokenProvider<X509SecurityToken> ClientX509TokenProvider
        {
            get
            {
                return clientX509TokenProviderValue;
            }
            set
            {
                clientX509TokenProviderValue = value;
            }
        }

        public TokenProvider<X509SecurityToken> ServiceX509TokenProvider
        {
            get
            {
                return serviceX509TokenProviderValue;
            }
            set
            {
                serviceX509TokenProviderValue = value;
            }
        }

        public CustomSecurityAssertion()
            : base()
        {
        }

        public override SoapFilter CreateClientOutputFilter(FilterCreationContext context)
        {
            return new CustomSecurityClientOutputFilter(this);
        }

        public override SoapFilter CreateClientInputFilter(FilterCreationContext context)
        {
            return new CustomSecurityClientInputFilter(this);
        }

        public override SoapFilter CreateServiceInputFilter(FilterCreationContext context)
        {
            return new CustomSecurityServerInputFilter(this);
        }

        public override SoapFilter CreateServiceOutputFilter(FilterCreationContext context)
        {
            return new CustomSecurityServerOutputFilter(this);
        }


        public override void ReadXml(System.Xml.XmlReader reader, IDictionary<string, Type> extensions)
        {
            bool isEmpty = reader.IsEmptyElement;
            base.ReadAttributes(reader);
            reader.ReadStartElement("CustomSecurityAssertion");
            if (!isEmpty)
            {
                if (reader.MoveToContent() == XmlNodeType.Element && reader.Name == "clientToken")
                {
                    reader.ReadStartElement();
                    reader.MoveToContent();
                    // Get the registed security token provider for X.509 certificate security credentials. 
                    Type type = extensions[reader.Name];
                    object instance = Activator.CreateInstance(type);

                    if (instance == null)
                        throw new InvalidOperationException(String.Format(System.Globalization.CultureInfo.CurrentCulture, "Unable to instantiate policy extension of type {0}.", type.AssemblyQualifiedName));

                    TokenProvider<X509SecurityToken> clientProvider = instance as TokenProvider<X509SecurityToken>;

                    // Read the child elements that provide the details about the client's X.509 certificate. 
                    clientProvider.ReadXml(reader, extensions);
                    this.ClientX509TokenProvider = clientProvider;
                    reader.ReadEndElement();
                }
                if (reader.MoveToContent() == XmlNodeType.Element && reader.Name == "serviceToken")
                {
                    reader.ReadStartElement();
                    reader.MoveToContent();

                    // Get the registed security token provider for X.509 certificate security credentials. 
                    Type type = extensions[reader.Name];
                    object instance = Activator.CreateInstance(type);

                    if (instance == null)
                        throw new InvalidOperationException(String.Format(System.Globalization.CultureInfo.CurrentCulture, "Unable to instantiate policy extension of type {0}.", type.AssemblyQualifiedName));

                    TokenProvider<X509SecurityToken> serviceProvider = instance as TokenProvider<X509SecurityToken>;
                    // Read the child elements that provide the details about the Web service's X.509 certificate.
                    serviceProvider.ReadXml(reader, extensions);
                    this.ServiceX509TokenProvider = serviceProvider;
                    reader.ReadEndElement();
                }
                base.ReadElements(reader, extensions);
                reader.ReadEndElement();
            }
        }
        public override IEnumerable<KeyValuePair<string, Type>> GetExtensions()
        {
            // Add the CustomSecurityAssertion custom policy assertion to the list of registered
            // policy extensions.
            List<KeyValuePair<string, Type>> extensions = new List<KeyValuePair<string, Type>>();
            extensions.Add(new KeyValuePair<string, Type>("CustomSecurityAssertion", this.GetType()));
            if (serviceX509TokenProviderValue != null)
            {
                // Add any policy extensions that read child elements of the <serviceToken> element
                // to the list of registered policy extensions.
                IEnumerable<KeyValuePair<string, Type>> innerExtensions = serviceX509TokenProviderValue.GetExtensions();
                if (innerExtensions != null)
                {
                    foreach (KeyValuePair<string, Type> extension in innerExtensions)
                    {
                        extensions.Add(extension);
                    }
                }
            }
            if (clientX509TokenProviderValue != null)
            {
                // Add any policy extensions that read child elements of the <clientToken> element
                // to the list of registered policy extensions.
                IEnumerable<KeyValuePair<string, Type>> innerExtensions = clientX509TokenProviderValue.GetExtensions();
                if (innerExtensions != null)
                {
                    foreach (KeyValuePair<string, Type> extension in innerExtensions)
                    {
                        extensions.Add(extension);
                    }
                }
            }
            return extensions;
        }
        public override void WriteXml(System.Xml.XmlWriter writer)
        {
            if (writer == null)
                throw new ArgumentNullException("writer");

            writer.WriteStartElement("CustomSecurityAssertion");
            base.WriteAttributes(writer);

            if (this.clientX509TokenProviderValue != null)
            {
                writer.WriteStartElement("clientToken");
                this.clientX509TokenProviderValue.WriteXml(writer);
                writer.WriteEndElement();
            }

            if (this.serviceX509TokenProviderValue != null)
            {
                writer.WriteStartElement("serviceToken");
                this.serviceX509TokenProviderValue.WriteXml(writer);
                writer.WriteEndElement();
            }

            base.WriteElements(writer);

            writer.WriteEndElement();

        }
    }

    class RequestState
    {
        SecurityToken clientToken;
        SecurityToken serverToken;

        public RequestState(SecurityToken cToken, SecurityToken sToken)
        {
            clientToken = cToken;
            serverToken = sToken;
        }

        public SecurityToken ClientToken
        {
            get { return clientToken; }
        }

        public SecurityToken ServerToken
        {
            get { return serverToken; }
        }
    }
    class CustomSecurityServerInputFilter : SecureConversationServiceReceiveSecurityFilter
    {
        public CustomSecurityServerInputFilter(CustomSecurityAssertion parentAssertion)
            : base(parentAssertion)
        {
            
        }
        public override void ValidateMessageSecurity(SoapEnvelope envelope, Security security, MessageProtectionRequirements response)
        {
            SecurityToken clientToken = null;
            SecurityToken serverToken = null;

            // Ensure incoming SOAP messages are signed and encrypted.
            foreach (ISecurityElement elem in security.Elements)
            {
                if (elem is MessageSignature)
                {
                    MessageSignature sig = (MessageSignature)elem;
                    clientToken = sig.SigningToken;
                }

                if (elem is EncryptedData)
                {
                    EncryptedData enc = (EncryptedData)elem;
                    serverToken = enc.SecurityToken;
                }
            }

            if (clientToken == null || serverToken == null)
                throw new Exception("Incoming message did not meet security requirements");

            RequestState state = new RequestState(clientToken, serverToken);

            envelope.Context.OperationState.Set(state);
        }
    }

    class CustomSecurityServerOutputFilter : SecureConversationServiceSendSecurityFilter
    {

        public CustomSecurityServerOutputFilter(CustomSecurityAssertion parentAssertion)
            : base(parentAssertion)
        {
        }

        public override void SecureMessage(SoapEnvelope envelope, Security security, MessageProtectionRequirements request)
        {
            RequestState state = envelope.Context.OperationState.Get<RequestState>();

            // Sign the message with the Web service's security token.
            security.Tokens.Add(state.ServerToken);
            security.Elements.Add(new MessageSignature(state.ServerToken));

            // Encrypt the message with the client's security token.
            security.Elements.Add(new EncryptedData(state.ClientToken));
        }
    }
    
    class CustomSecurityClientInputFilter : SecureConversationClientReceiveSecurityFilter
    {
        X509SecurityToken serviceX509Token;
        X509SecurityToken clientX509Token;

        public CustomSecurityClientInputFilter(CustomSecurityAssertion assertion)
            : base(assertion)
        {
            if (assertion.ServiceX509TokenProvider != null)
                this.serviceX509Token = assertion.ServiceX509TokenProvider.GetToken();
            if (assertion.ClientX509TokenProvider != null)
                this.clientX509Token = assertion.ClientX509TokenProvider.GetToken();                    

        }
        public override void ValidateMessageSecurity(SoapEnvelope envelope, Security security, MessageProtectionRequirements request)
        {
            RequestState state;
            bool signed = false;
            bool encrypted = false;

            // Get the request state out of the operation state.
            state = envelope.Context.OperationState.Get<RequestState>();

            // Make sure the message was signed with the server's security token.
            foreach (ISecurityElement elem in security.Elements)
            {
                if (elem is MessageSignature)
                {
                    MessageSignature sig = (MessageSignature)elem;

                    if (sig.SigningToken.Equals(state.ServerToken))
                        signed = true;
                }

                if (elem is EncryptedData)
                {
                    EncryptedData enc = (EncryptedData)elem;

                    if (enc.SecurityToken.Equals(state.ClientToken))
                        encrypted = true;
                }
            }

            if (!signed || !encrypted)
                throw new Exception("Response message does not meet security requirements");
        }
        public override IEnumerable<SecurityToken> GetUnattachedTokensCore(SoapContext context)
        {

            return new SecurityToken[] {this.serviceX509Token, this.clientX509Token };
        }
    }
    class CorrelationState : SerializableTokenWrapper<EncryptedKeyToken>
    {
        public CorrelationState() : base() { }
        public CorrelationState(EncryptedKeyToken token) : base(token) { }
    }

    class CustomSecurityClientOutputFilter : SecureConversationClientSendSecurityFilter
    {
    
        SecurityToken clientToken;
        SecurityToken serverToken;

        
        public CustomSecurityClientOutputFilter(CustomSecurityAssertion parentAssertion)
            : base(parentAssertion )
        {
            // Get the client security token.
            X509TokenProvider clientX509Provider = new X509TokenProvider(StoreLocation.CurrentUser, StoreName.My, "CN=WSE2QuickStartClient");
            clientToken = clientX509Provider.GetToken();

            // Get the server security token.
            X509TokenProvider serverX509Provider = new X509TokenProvider(StoreLocation.LocalMachine, StoreName.My, "CN=WSE2QuickStartServer");
            serverToken = serverX509Provider.GetToken();
        }


        public override void SecureMessage(SoapEnvelope envelope, Security security, MessageProtectionRequirements request)
        {
            if (envelope == null)
                throw new ArgumentNullException("envelope");
            if (security == null)
                throw new ArgumentNullException("security");
            if (request == null)
                throw new ArgumentNullException("request");

            // Sign the SOAP message with the client's security token.
            security.Tokens.Add(clientToken);

            security.Elements.Add(new MessageSignature(clientToken));

            // Encrypt the SOAP message with the client's security token.
            security.Elements.Add(new EncryptedData(serverToken));

            // Encrypt the client's security token with the server's security token.
            security.Elements.Add(new EncryptedData(serverToken, "#" + clientToken.Id));

            // Store the client and server security tokens in the request state.
            RequestState state = new RequestState(clientToken, serverToken);

            // Store the request state in the proxy's operation state. 
            // This makes these tokens accessible when SOAP responses are 
            // verified to have sufficient security requirements.
            envelope.Context.OperationState.Set(state);
        }
    }
}

See Also

Tasks

How to: Secure an Application Using a Custom Policy Assertion

Other Resources

Establishing a Secure Conversation