Web Service Security Protocols



Web Service Security Protocols

Of course, the security features found in Windows and the .NET Frame-work do not by themselves provide a complete security solution. Further-more, standards are needed for the use of these security features inside of SOAP messaging systems.

In the spring of 2002, Microsoft, IBM, and VeriSign jointly published a new specification called WS-Security that is designed to deal specifically with the issues surrounding Web service security. This specification lays the groundwork for many upcoming security specifications. Instead of trying to be a complete solution, WS-Security deals with the basics of how Web service stacks can pass security information back and forth.

Definitions

Before diving into how this specification works, you'll need to understand the terms it uses. These terms have precise meaning in the context of this specification, and so it's important to be clear about them—especially because earlier versions of SOAP-based security specifications (like the first WS-Security) used a different nomenclature.

Security Token

A security token in the most basic sense is a piece of security-related information. More specifically, a security token typically relays some form of identity, although this isn't strictly required. Typical examples of security tokens include x.509 certificates and XrML (eXtensible rights Markup Language) documents. WS-Security includes both signed and unsigned tokens.

A signed security token is a piece of security information such as a Kerberos ticket or an x.509 certificate that is cryptographically signed. This signature assures issuers and recipients of these tokens that the security information hasn't been tampered with. Typically, a signed security token is in a binary format. This means that if it is present in a SOAP message, it probably will be base64 or binHex encoded.

An unsigned security token does not contain a cryptographic signature that can verify its issuer. Typically, this means that the token doesn't need this cryptographic assurance. The usual example for this is that of a username token. Clearly, there is no need to sign this kind of thing.

Obviously then, these kinds of tokens don't usually contain binary data, but are instead typically pure XML. You wouldn't expect a base64 encoding (or any kind of encoding) for these tokens.

Claim

A claim is a particularly difficult idea to get across without the definition becoming self-referential. Basically, a claim is a set of assertions made either by the subject (see below) of the security token, or the issuer of the token. These claims are usually things such as the role the subject can play, or the resources it can access.

Subject

A subject is the person or identity of the security token. In other words, it's the principal of an x.509 certificate, or the user of a username. A subject will usually have some set of claims made on its behalf with the more sophisticated tokens.

Policy

Policy is the set of specific security-related requirements a Web service has. These can range from a specific security token that is expected, certain claims that must exist, or even the key size for encrypting messages to the service.

WS-Security

With these definitions in mind, we can now delve into the WS-Security specification in more detail. The version of WS-Security I am writing about is the one that Microsoft, IBM, and VeriSign published on 12 April 2002. This version of the specification has the namespace of http://schemas.xmlsoap.org/ws/2002/04/secext for the XML elements it defines.

This specification defines a single SOAP header named <Security>. This header may occur multiple times in a SOAP message, as long as each occurrence has a different SOAP actor. Of course, there also may be one occurrence of this header with no SOAP actor.

By allowing this header to appear multiple times, a single message can pass through many intermediaries with security-related information not only for the final destination, but also for each intermediary. In fact, one intermediary can add some of these security headers for another intermediary. Figure illustrates the process.

5. Security Architecture with Several Recipients

graphics/13fig05.gif

Specifically, the WS-Security specification explains how to send three types of security-related information in the security SOAP header: security tokens, signatures, and encrypted data. Although the method for doing the signing is left open, it is strongly recommended that this be done with the XML Signature specification. Similarly with encryption, anything can be used, but the W3C's XML Encryption standard is recommended. Of course, the security tokens allowed can be anything, and there is no single recommendation regarding this in the specification. Rather, the specification provides for how to deal with both the signed and unsigned varieties. Listing 13.5 shows an example of how a SOAP message could look with signatures and tokens.

Using Signatures and Tokens with SOAP
<S:Envelope xmlns:S="http://www.w3.org/2001/12/soap-envelope"
            xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
  <S:Header>
      <wsse:Security xmlns:wsse="http://schemas.xmlsoap.org/ws/2002/04/secext">
         <wsse:UsernameToken Id="someIdentifier">
             <wsse:Username>KeithBa</wsse:Username>
         </wsse:UsernameToken>
         <ds:Signature>
             <!— insert XML signature info here —>
         </ds:Signature>
</wsse:Security>
</S:Header>
<S:Body>
...
</S:Body>
</S:Envelope>

As you can see, in concept the WS-Security specification actually defines a fairly simple structure. It defines only a few specific items, and allows for an open content model for custom additions. Specifically, it defines the following items:

  • Username security tokens

  • Binary security tokens, which allows for x.509, Kerberos, and other signed security tokens

  • References to security tokens

  • Signature information as defined in the XML Signature specification

  • Encryption information, such as encrypted data or key information for encrypted pieces of the document

Security Tokens

There are two types of security tokens defined in WS-Security. One type is the username token, which is an unsigned token designed for passing user information in a basic manner. Of course, the other type is the binary security token, which is often used for signed security tokens.

The username token has a simple schema. It has an ID, as well as the ability to have a username and password. The password can be omitted, added as plain text, or hashed. Listing 13.6 shows an example.

A WS-Security Message
<S:Envelope xmlns:S="http://www.w3.org/2001/12/soap-envelope"
            xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
  <S:Header>
      <wsse:Security xmlns:wsse="http://schemas.xmlsoap.org/ws/2002/04/secext">
         <wsse:UsernameToken Id="userID">
             <wsse:Username>KeithBa</wsse:Username>
             <wsse:Password>GoofyBoy</wsse:Password>
         </wsse:UsernameToken>
</wsse:Security>
</S:Header>
<S:Body>
...
</S:Body>
</S:Envelope>

With Web Services Enhancements for Microsoft .NET (WSE), you can easily add a username token to a request message, as shown in Listing 13.7.

Adding a Username Token to a Request Message
UsernameToken token = new UsernameToken("ChristianEdgar",
                                        "GoofyBoy",
                                         PasswordOption.SendPlain);
proxyClass.RequestSoapContext.Security.Tokens.Add( token );
// now, any calls made with the
// proxyClass will include a username token

The Password element can also send across a textual password. However, this field may also contain a digest, which is indicated with the Type attribute, as shown in Listing 13.8.

A Username Token
<S:Envelope xmlns:S="http://www.w3.org/2001/12/soap-envelope"
            xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
  <S:Header>
      <wsse:Security xmlns:wsse="http://schemas.xmlsoap.org/ws/2002/04/secext">
         <wsse:UsernameToken Id="userID">
             <wsse:Username>ChristianEdgar</wsse:Username>
             <wsse:Password
                    wsse:Type="wsse:PasswordDigest">
               SE!Kjkaj
             </wsse:Password>
         </wsse:UsernameToken>
</wsse:Security>
</S:Header>
<S:Body>
...
</S:Body>
</S:Envelope>

With the WSE, to send a message with the password hashed, you merely need to change the third parameter in the constructor of the User-nameToken object to be SendHashed:

UsernameToken token = new UsernameToken("ChristianEdgar", 
                                        "GoofyBoy",
                                        PasswordOption.SendHashed);

You can also include binary tokens, of course, in a Security header. These binary tokens are useful for many more interesting situations and tokens, such as x.509 certificates and Kerberos tickets. The relevant element is called BinarySecurityToken, and it includes two important attributes: ValueType and EncodingType. The ValueType attribute is a QName that refers to the token type in use, such a x.509 certificate. The Encoding-Type attribute specifies how the token is encoded from binary data to XML.

Listing 13.9 shows an example of a binary token that contains x.509 certificate information.

A Binary Security Token
<S:Envelope xmlns:S="http://www.w3.org/2001/12/soap-envelope"
            xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
  <S:Header>
      <wsse:Security xmlns:wsse="http://schemas.xmlsoap.org/ws/2002/04/secext">
         <wsse:BinarySecurityToken
             Id="NewX509SecurityToken"
             ValueType="wsse:X509v3"
             EncodingType="wsse:Base64Binary">
             JHUQI8jakak . . .
          </wsse:BinarySecurityToken>
</wsse:Security>
</S:Header>
<S:Body>
...
</S:Body>
</S:Envelope

With the WSE, adding a binary token is just as easy. Assuming you have an X509Certificate object call certificate, you merely need to create an X509SecurityToken object, and add that, as shown in Listing 13.10.

Using x.509 Certificates
X509SecurityToken token = new X509SecurityToken( cert );
proxyClass.RequestSoapContext.Security.Tokens.Add( token );

In addition to the X.509 value, WS-Security includes QNames for two different types of Kerberos tickets. (Kerberos defines ticket-granting tickets and service tickets.) WS-Security also specifies how to reference security tokens. Typically, URIs refer to tokens that may exist outside of the message, as shown in Listing 13.11.

Signatures with WS-Security
<S:Envelope xmlns:S="http://www.w3.org/2001/12/soap-envelope"
            xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
  <S:Header>
      <wsse:Security xmlns:wsse="http://schemas.xmlsoap.org/ws/2002/04/secext">
         <wsse:SecurityTokenReference
          xmlns:wsse="http://schemas.xmlsoap.org/ws/2002/04/secext">
            <wsse:Reference
       URI="http://www.keithba.com/Path/Resource#SomeSecurityToken" />
         </wsse:SecurityTokenReference>
</wsse:Security>
</S:Header>
<S:Body>
...
</S:Body>
</S:Envelope

The receiver can use this kind of reference to a security token to pull down the claims and other security information contained in the message.

Integrity and Encryption

WS-Security also refers to XML Signature and XML Encryption to deal with how to embed integrity and encryption information. This is very straightforward. The only difference from XML Signature itself is that the WS-Security specification states that the SOAP envelope transformation that is defined with XML Signature should not be used. Instead, the elements of the envelope to be signed should be explicitly called out. This allows for a more sophisticated and smaller surface area to be dealt with in the signing. As well, it details that you can use a variety of canonicalization schemes.

To sign a message with an X509SecurityToken in the WSE, you merely need to add the token, and then add a signature to the elements collection of the security tokens, as shown in Listing 13.12.

Using X509 Certificates and Signatures
X509SecurityToken token = new X509SecurityToken( cert );
Signature sig = new Signature( token )
proxyClass.RequestSoapContext.Security.Tokens.Add( token );
proxyClass.RequestSoapContext.Security.Elements.Add( sig );