Team LiB
Previous Section Next Section

Security

One of the other features that WSE provides is the ability to extend the security of a web service by providing APIs and tools that deal with use name identity transmission, X.509 certificates, and digital signatures. The next section will show you how to write a web service that can not only accept a username and password combination embedded in the SOAP envelope, but can also validate the authenticity of the message itself using digital certificates.

Introduction to WSE Security

WSE security is built around adding various elements to the SOAP header. An element called a UsernameToken can be added to the header that identifies the username and password of the message sender. Additional elements include security verification elements for signatures and more.

Previous versions of WSE were more difficult to work with. To get certain things working, programmers had to manually add entries to the web.config file and add references and more. With WSE 2.0, the Visual Studio .NET 2003 integration is fairly complete. You can now right-click the web project and select WSE Settings 2.0.

Doing so pulls up a multipage tabbed dialog of various policy settings, security settings, and options for WSE-based applications.

UsernameTokens

A UsernameToken is a special element defined by the WS-Security standard. It can pass credentials from the client to a service. These credentials can either be a simple username, a username and a clear text password, or even a username and an encrypted username hash digest.

The WSE security subsystem automatically detects the presence of UsernameTokens in every message sent to a WSE-enabled web service. By default, the identity contained in the UsernameToken is compared against an Active Directory or the NT domain user list.

If you want to implement your own user identity system (most systems are based on a relational database that contains a list of usernames and encrypted passwords), WSE provides a pluggable architecture that allows for this.

To validate your own tokens, you can create a class that derives from UsernameTokenManager. Then override a method called AuthenticateToken . Listing 33.5 shows such a sample class.

Listing 33.5. A Custom UsernameToken Processing Class; Always Returns a Valid Result
using System;
using System.Security.Permissions;
using System.Security;
using Microsoft.Web.Services2.Security;
using Microsoft.Web.Services2.Security.Tokens;
using Microsoft.Web.Services2;

namespace Chap33WSE
{
  /// <summary>
  /// Summary description for CustomUsernameTokenManager.
  /// </summary>
  [SecurityPermission(SecurityAction.Demand,
    Flags= SecurityPermissionFlag.UnmanagedCode)]
  public class CustomUsernameTokenManager : UsernameTokenManager
  {
    public CustomUsernameTokenManager()
    {

    }
    protected override string AuthenticateToken(UsernameToken token) 
    {
      if (token == null)
        throw new ArgumentNullException();

      // the user will be considered valid if a string is returned.
      // if an empty string is returned, the user is not valid.
      // typically the username/password hash are compared against
      // a database

      byte[] userName =
        System.Text.Encoding.UTF8.GetBytes(token.Username);

      return System.Text.Encoding.UTF8.GetString( userName );
    }

  }
}

In order to register a custom token manager with WSE, you have to open up the WSE Settings 2.0 dialog and go to the Security tab. This tab will prompt you for the fully qualified type name of your class, followed by a comma, and then the name of the assembly in which the class can be found. The next prompt is for the namespace of the security token, and finally the name of the token. There are links for examples that will show you how to set up each of these items.

The following simple lines of code show how you can create an instance of a WSE proxy client and add a UsernameToken to it to pass credentials from client to server:

RemoteService.ServiceWse proxy = new RemoteService.ServiceWse();
UsernameToken ut = new UsernameToken("user", "pass", PasswordOption.SendHashed);
proxy.RequestSoapContext.Security.Tokens.Add( ut );
proxy.InvokeMethod();

X.509 Certificates

X.509 digital certificates are used in encryption. The way they work with WSE is that one half of the certificate's key is used to encrypt the data being sent to the server, and the other half is used to verify or decrypt the data on the other end of the communications.

Signing Messages

A message signature is essentially a hash of the message. The hash is completely unique to that message. In other words, when a message is signed by a client, the server can then verify the hash of the message against the signature and will be able to verify that the message sent by the client was indeed sent by the client. This prevents malicious attackers from intercepting and modifying messages en route to the server. There are multiple ways to sign a message, including using X.509 tokens and UsernameTokens. To sign a message using a UsernameToken, you can create a signature from a UsernameToken, and add that signature to the WSE context for the web service proxy client as shown here:

UsernameToken ut = new UsernameToken("Kevin", "password", PasswordOption.SendHashed);
MyService.Service proxy = new MyService.Service();
Proxy.RequestSoapContext.Security.Tokens.Add( ut );
MessageSignature sig = new MessageSignature( ut );
Proxy.RequestSoapContext.Security.Elements.Add( sig );

Everything hinges on the WSE context's Security object. This object controls the serialization of all the tokens and security elements including signatures into the various industry-standard SOAP headers.

    Team LiB
    Previous Section Next Section