How to: Add Security Credentials to a SOAP Message

The Web Services Enhancements for Microsoft .NET (WSE) provides a mechanism for creating one or more security credentials that can be added to a SOAP message. Without using WSE, you can set the Credentials property of the proxy class, which enables the ultimate destination to authenticate the client application. However, if the SOAP message is routed through intermediaries before the ultimate destination, the client credentials might not flow to the ultimate destination, and thus the client is not authenticated. If you add the security credentials to the SOAP message using WSE, rather than at the transport layer using the proxy's Credentials property, the credentials can be routed through one or more intermediaries and still be validated at the ultimate destination.

The following procedure details how to add one or more security credentials to a SOAP message. For the following procedure to be successful, a computer must be set up to accept SOAP messages embedded with security credentials. The following table outlines the procedures for setting up a computer running WSE, to accept the security credentials.

Type of security credentials Topic describing how to accept the credentials

X.509 certificate

How to: Verify Digital Signatures of SOAP Messages Signed by an X.509 Certificate

User name and password

How to: Verify Digital Signatures of SOAP Messages Signed Using a User Name and Password

Note

Adding a security token to a SOAP header does not provide any security in itself. To provide security, use the security token in conjunction with digital signing (using the MessageSignature class) or encryption (using the EncryptedData class).

To add a security token to a SOAP message

  1. Open the Web service client project in Visual Studio .NET 2003.

  2. Add references to the Microsoft.Web.Services2 and System.Web.Services assemblies.

    1. On the Project menu, click Add Reference.
    2. On the .NET tab, select the component named Microsoft.Web.Services2.dll, and then click Select.
    3. On the .NET tab, select the component named System.Web.Services.dll, and then click Select.
    4. Click OK.
  3. Add a Web Reference to the Web service that is to receive the SOAP message signed with the UsernameToken.

    1. On the Project menu, click Add Web Reference.
    2. In the Add Web Reference dialog box, type the URL for the Web service in the Address box, and then click the arrow icon.
    3. Verify that the items in the Available references box are the items you want to reference in your project, and then click Add Reference.
  4. Edit the proxy class to derive from WebServicesClientProtocol.

    1. In Solution Explorer, right-click the Reference.cs file for the Web reference just added, and then click View Code.

      Note

      If the Reference.cs file containing the proxy class is not visible, click the Show All Files icon in the Solution Explorer toolbar, and then expand the Reference.map node.

    2. Change the base class of the proxy class to Microsoft.Web.Services2.WebServicesClientProtocol.
      This modifies the proxy class to emit routing and security SOAP headers when communicating with the Web service. The following code example modifies a proxy class named Service1 to derive from Microsoft.Web.Services2.WebServicesClientProtocol.

      Public Class Service1
        Inherits Microsoft.Web.Services2.WebServicesClientProtocol
      
      public class Service1 : Microsoft.Web.Services2.WebServicesClientProtocol {
      

      Note

      If you select Update Web Reference in Visual Studio .NET 2003, the proxy class is regenerated, the base class is reset to SoapHttpClientProtocol, and you must change the class the proxy class derives from again.

  5. Add the following using directives to the top of the file containing the Web service client code:

    Imports Microsoft.Web.Services2
    Imports Microsoft.Web.Services2.Security
    Imports Microsoft.Web.Services2.Security.Tokens
    
    using Microsoft.Web.Services2;
    using Microsoft.Web.Services2.Security;
    using Microsoft.Web.Services2.Security.Tokens;
    
  6. Edit the method that communicates with the Web service to add the security credentials to the SOAP message.

    1. Create a new instance of a class deriving from SecurityToken.
      The following code example creates an instance of the UsernameToken class.

      Dim userToken As New UsernameToken(userName, password, _
                                         PasswordOption.SendHashed)
      
      UsernameToken userToken = 
                  new UsernameToken(userName, password,
                                    PasswordOption.SendHashed )
      

      Note

      It is recommended that a UsernameToken be sent with the PasswordOption set to SendNone or SendHashed when the underlying transport protocol is not secure.

    2. Get the SoapContext for the SOAP request that is being made to the Web service.
      Service1 is the name of a proxy class for the Web service in the following code example.

      Dim serviceProxy As New Service1()
      Dim requestContext As SoapContext = _
        serviceProxy.RequestSoapContext
      
      Service1 serviceProxy = new Service1();
      SoapContext requestContext = serviceProxy.RequestSoapContext;
      
    3. Add the SecurityToken to the WS-Security SOAP header.

      requestContext.Security.Tokens.Add(userToken)
      
      requestContext.Security.Tokens.Add(userToken);
      
    4. Specify the time-to-live (TTL) for the SOAP message to diminish the chance of someone intercepting the message and replaying it. The following code sample sets the TTL to one minute.

      requestContext.Security.Timestamp.TtlInSeconds = 60
      
      requestContext.Security.Timestamp.TtlInSeconds = 60;
      
    5. Call the Web service.

      serviceProxy.sayHello()
      
      serviceProxy.sayHello();
      

Example

The following code example adds a UsernameToken to a SOAP message.

Dim userToken As UsernameToken
userToken = New UsernameToken(userName, userName, PasswordOption.SendNone)
Try
    ' Creates an instance of the Web service proxy.
    Dim serviceProxy As New AddNumbers()
    ' Gets the SoapContext associated with the SOAP request.
    Dim requestContext As SoapContext = _
      serviceProxy.RequestSoapContext
    ' Sets the TTL to one minute.
    requestContext.Security.Timestamp.TtlInSeconds = 60
   
    ' Adds the token to the SOAP header.
    requestContext.Security.Tokens.Add(userToken);
   
    ' Calls the Web service.
    Dim sum As Integer = serviceProxy.AddInt(a, b)
Catch se As System.Web.Services.Protocols.SoapException
    MessageBox.Show(se.ToString())
Catch ex As Exception
    MessageBox.Show( _
      "Exception caught while invoking a Web service.")
   Return
End Try
UsernameToken userToken; 
userToken = new UsernameToken(userName, userName,
                              PasswordOption.SendNone);
try
{
    // Creates an instance of the Web service proxy.
    AddNumbers serviceProxy = new AddNumbers();
    // Gets the SoapContext associated with the SOAP request.
    SoapContext requestContext = serviceProxy.RequestSoapContext;
    // Sets the TTL to one minute.
    requestContext.Security.Timestamp.TtlInSeconds = 60;
 
    // Adds the token to the SOAP header.
    requestContext.Security.Tokens.Add(userToken);

    // Calls the Web service.
    int sum = serviceProxy.AddInt(a, b);
}
catch (System.Web.Services.Protocols.SoapException se) 
{
    MessageBox.Show(se.ToString());
}
catch (Exception ex) 
{
    MessageBox.Show(
      "Exception caught while invoking a Web service.");
    return;
}

See Also

Other Resources

Securing Web Services