How to: Encrypt a SOAP Message By Using a Security Context Token

The following procedures detail how to use policy or code to encrypt a SOAP message using a SecurityContextToken security token.

To use policy to encrypt a SOAP message with a security context token

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

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

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

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

    1. Add a <KeyInfo> Element (WSE for Microsoft .NET) (1) child element to the <Confidentiality> Element element.
    2. Add a <SecurityToken> Element child element to the <TokenInfo> Element element.
    3. Add a <TokenType> Element child element to the <SecurityToken> Element element and set its value to https://schemas.xmlsoap.org/ws/2004/04/security/sc/sct.
      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 SecurityContextToken security token must be used to encrypt the SOAP message.

    <wssp:Confidentiality wsp:Usage="wsp:Required"
      xmlns:wssp="https://schemas.xmlsoap.org/ws/2002/12/secext">
      <wssp:KeyInfo>    <wssp:SecurityToken>      <wssp:TokenType>https://schemas.xmlsoap.org/ws/2004/04/security/sc/sct</wssp:TokenType>
    
  3. Specify the security token service that issued the token by adding a <TokenIssuer> Element (WSE for Microsoft .NET) (1) element.

    The following code example specifies that the http://www.cohowinery.com/secureConversation.ashx security token service issued the SecurityContextToken security token.

    <wssp:SecurityToken>
      <wssp:TokenIssuer>    http://www.cohowinery.com/secureConversation.ashx  </wssp:TokenIssuer>
    
  4. Map the policy assertion to an endpoint by adding an <endpoint> Element element. Optionally, designate the policy as the default for all SOAP messages by adding the <defaultOperation> Element element.

    1. Add an <endpoint> Element child element to the <mappings> Element element in the policy file for the application, 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 application's 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="https://localhost/SecureConvPolicyService/SecureConvService.asmx">
        <defaultOperation>
          <request policy="#policy-c0a22319-6b89-49ff-9b82-bdbac5f04618" />
          <response policy="#policy-c0a22319-6b89-49ff-9b82-bdbac5f04618" />
          <fault policy="#policy-c0a22319-6b89-49ff-9b82-bdbac5f04618" />
        </defaultOperation>
      </endpoint>
    </mappings>
    
  5. Specify the XML elements to be encrypted by adding a <MessageParts> Element for <Confidentiality> Element element to the <Confidentiality> Element element.

    1. Add a <MessageParts> Element for <Confidentiality> Element child element to the <Confidentiality> Element element in the policy file for the application, and set the Default attribute value to "https://schemas.xmlsoap.org/2002/12/wsse#part".
      The <MessageParts> Element for <Confidentiality> Element element specifies the XML elements that must be encrypted. The Dialect attribute specifies the expression dialect used to specify the parts of the SOAP message. The only dialect supported by WSE is "https://schemas.xmlsoap.org/2002/12/wsse#part".
    2. Specify the parts of the message to be encrypted as the value of the <MessageParts> Element for <Confidentiality> Element element.
      For encryption requirements, the only element that may be specified using policy is the <Body> element.

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

    <wssp:MessageParts Dialect="https://schemas.xmlsoap.org/2002/12/wsse#part">
      wsp:Body()
    </wssp:MessageParts>
    
  6. Optionally, add a SecurityContextToken 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 SecurityContextToken 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 SecurityContextToken security token that it finds that matches the policy. If it does not find a match, WSE will attempt to request one from the security token service specified in the <TokenIssuer> Element (WSE for Microsoft .NET) (1) element (specified in step 3).

    The following code example adds a SecurityContextToken to the PolicyEnforcementSecurityTokenCache of the application.

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

To use code to encrypt a SOAP message by using a security context token

  1. Obtain a security token from a security token service. See How to: Obtain a Security Token From a Security Context Token Service.

  2. Create a new instance of the proxy class for the target Web service and get the SoapContext value for the SOAP request to the Web service.

    Service1Wse is the name of the proxy class to the Web service in the following code example.

    Dim proxy As Service1Wse = New Service1Wse
    Dim requestContext As SoapContext = proxy.RequestSoapContext
    
    Service1Wse proxy = new Service1Wse();
    SoapContext requestContext = proxy.RequestSoapContext;
    
  3. Add the security context token that is issued from the security token service to the SOAP message.

    For security reasons, it is highly recommended that a security token derived from the issued security context token be used to digitally sign or encrypt the SOAP message instead of the security context token itself so that the SOAP message is signed and/or encrypted using a key that changes. To encrypt and sign a SOAP message, derive two tokens from the security context token. Use one token to encrypt the SOAP message and the other one to sign it. This will make it more difficult for the key to be compromised.

    The following code example gets the security context token's derived token and adds that to the SOAP message.

    Dim secContextToken As SecurityContextToken = _
        CType(tokenIssuingResponse.RequestedSecurityToken.SigningToken, _
        SecurityContextToken)
    Dim derivedToken As DerivedKeyToken = New _
        DerivedKeyToken(CType(secContextToken, IDerivableToken))
    requestContext.Security.Tokens.Add(secContextToken)
    requestContext.Security.Tokens.Add(derivedToken)
    
    SecurityContextToken secContextToken = (SecurityContextToken) tokenIssuingResponse.RequestedSecurityToken.SigningToken;
    DerivedKeyToken derivedToken = new 
        DerivedKeyToken((IDerivableToken)secContextToken);
    requestContext.Security.Tokens.Add(secContextToken;
    requestContext.Security.Tokens.Add(derivedToken);
    
  4. Encrypt the SOAP request to the Web service by using the security context token.

    requestContext.Security.Elements.Add(New _
      MessageSignature(derivedToken))
    
    requestContext.Security.Elements.Add(new
      MessageSignature(derivedToken));
    
  5. Call the Web service.

    Dim result as Integer = proxy.AddNumbers(a, b)
    
    int result = proxy.AddNumbers(a,b);
    

Example

The following code example is a policy file specifying that all SOAP messages sent to the Web service at the endpoint https://localhost/SecureConvPolicyService/SecureConvService.asmx must be encrypted by a DerivedKeyToken that is derived from a SecurityContextToken security token.

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="https://localhost/SecureConvPolicyService/SecureConvService.asmx">
      <defaultOperation>
        <request policy="#policy-c0a22319-6b89-49ff-9b82-bdbac5f04618" />
        <response policy="" />
        <!-- SOAP faults are signed using the original Security Context Token -->
        <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:Confidentiality wsp:Usage="wsp:Required">        <wssp:KeyInfo>          <wssp:SecurityToken wse:IdentityToken="true">            <wssp:TokenType>https://schemas.xmlsoap.org/ws/2004/04/security/sc/dk</wssp:TokenType>            <wssp:Claims>              <wse:Parent>                <wssp:SecurityToken>                  <wssp:TokenType>https://schemas.xmlsoap.org/ws/2004/04/security/sc/sct</wssp:TokenType>                  <wssp:Claims>                    <wse:BaseToken>                      <wssp: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:SecurityToken>                    </wse:BaseToken>                    <wse:IssuerToken>                      <wssp:SecurityToken>                        <wssp:TokenType>http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3</wssp:TokenType>                        <wssp:Claims>                          <wssp:SubjectName>CN=WSE2QuickStartServer</wssp:SubjectName>                        </wssp:Claims>                      </wssp:SecurityToken>                    </wse:IssuerToken>                  </wssp:Claims>                </wssp:SecurityToken>              </wse:Parent>            </wssp:Claims>          </wssp: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 encrypts a SOAP message by using a security context token.

' Get a security token to sign the SOAP message that is sent to the
' security token service. 
Dim token As X509SecurityToken = GetSecurityToken()
If (token Is Nothing) Then
    Throw New ApplicationException("No key provided for signature.")
End If

' Create a new instance of the proxy class for the security token 
' service.
Dim tokenIssuingServiceProxy As SecurityContextTokenServiceClient = _
New SecurityContextTokenServiceClient(new Uri( _
"http://www.cohowinery.com/TokenIssuingService/secureConversation.ashx")))

' Sign the security token request.
tokenIssuingServiceProxy.RequestSoapContext.Tokens.Add(token)
tokenIssuingServiceProxy.RequestSoapContext.Elements.Add _
(New MessageSignature(token))

// Request the token, use the signing token as the Base
Dim sct As SecurityContextToken sct = _
tokenIssuingServiceProxy.IssueSecurityContextTokenAuthenticated(token)

' Create a new instance of the Web service proxy.
Dim proxy As Service1Wse = New Service1Wse

' Get the SoapContext value for the SOAP request.
Dim requestContext As SoapContext = proxy.RequestSoapContext

' Convert the requested security token to a security context
' token.
Dim secContextToken As SecurityContextToken = _
    CType(tokenIssuingResponse.RequestedSecurityToken.SigningToken, _
    SecurityContextToken)

' Create a security token that is derived from the
' SecurityContextToken security token.
Dim derivedToken As DerivedKeyToken = New _
    DerivedKeyToken(CType(secContextToken, IDerivableToken))

' Add the token that is issued from the token issuing service to the SOAP
' message.
requestContext.Security.Tokens.Add(secContextToken)

' Add the derived security token to the SOAP message.
requestContext.Security.Tokens.Add(derivedToken)

' Encrypt the SOAP message by using the derived token issued from the
' security token service.
requestContext.Security.Elements.Add(New EncryptedData(derivedToken))

' Communicate with the Web service.
Dim result As Integer proxy.AddNumbers(a, b)
// Get a security token to sign the SOAP message sent to the
// security token service. 
X509SecurityToken token = GetSecurityToken();
if (token == null)
    throw new ApplicationException("No key provided for signature.");

// Create a new instance of the proxy class for the security token 
// service.
SecurityContextTokenServiceClient tokenIssuingServiceProxy = new
SecurityContextTokenServiceClient(new Uri(
"http://www.cohowinery.com/TokenIssuingService/secureConversation.ashx")));

// Sign the security token request.
tokenIssuingServiceProxy.RequestSoapContext.Tokens.Add(token);
tokenIssuingServiceProxy.RequestSoapContext.Elements.Add
(new MessageSignature(token));

// Request the token, use the signing token as the Base
SecurityContextToken sct =
tokenIssuingServiceProxy.IssueSecurityContextTokenAuthenticated(token);

// Get the SoapContext value for the SOAP request that will be sent
// to the target Web service.
Service1Wse proxy = new Service1Wse();
SoapContext requestContext = proxy.RequestSoapContext;

// Cast the requested security token to a security context token.
SecurityContextToken secContextToken = (SecurityContextToken)
  tokenIssuingResponse.RequestedSecurityToken.SigningToken;

// Create a security token that is derived from the
// SecurityContextToken security token.
DerivedKeyToken derivedToken = new
    DerivedKeyToken((IDerivableToken)secContextToken);

// Add the token that is issued from the token issuing service to the SOAP
// message.
requestContext.Security.Tokens.Add(secContextToken);

// Add the derived security token to the SOAP message.
requestContext.Security.Tokens.Add(derivedToken);

// Encrypt the SOAP message by using a token derived from the token
// issued from the security token service.
requestContext.Security.Elements.Add(new EncryptedData(derivedToken));

// Communicate with the Web service.
int result = proxy.AddNumbers(a,b);

See Also

Tasks

How to: Decrypt a SOAP Message Encrypted Using a Security Context Token
How to: Specify the Parts of a SOAP Message That Are Signed or Encrypted

Reference

SecurityContextToken

Other Resources

Issuing Security Context Tokens
Security Context Token