WS-Security

New Technologies Help You Make Your Web Services More Secure

David Chappell

This article assumes you're familiar with XML and Security Basics

Level of Difficulty123

SUMMARY

Without good security, Web Services will never reach their potential. WS-Security and its associated technologies, the focus of this article, represent the future of security for Web Services. Provided here is an overview of these emerging security standards that explains what they do, how they work, and how they get along together. Topics discussed include integrity and confidentiality and how these are provided by public key cryptography, WS-Security, and more. Some of the key components of WS-Security, such as the wsu namespace, are also covered.

Contents

WS-Security
Sending Security Tokens
Integrity
Confidentiality
Specifying Policies: WS-SecurityPolicy
Acquiring Security Tokens: WS-Trust
Establishing Context: WS-SecureConversation
Using SAML and Other XML-based Tokens
Conclusion

Web Services without effective security aren't very useful. Yet the original creators of SOAP chose to put off defining how this problem should be solved. This was a defensible decision, since getting Web Services off the ground meant keeping them simple—and providing security is seldom simple. The problem, however, can't be put off forever so Microsoft and IBM, among others, are working together to address this issue. Their efforts have resulted in a group of specs for providing Web Services security, the most important of which is WS-Security. With this article I'll provide a big-picture view of how these technologies work.

From one perspective, the task facing the creators of Web Services security looks simple. After all, effective mechanisms already exist for distributed security, including Kerberos, public key technologies, and others, so the task these creators faced wasn't inventing new security mechanisms. Instead, their goal was to define ways to use what already existed in a Web Services world, a world built on XML and SOAP. There are several security-related specifications, which include the following:

  • WS-Security, the foundation for all of the other specs. It defines extensions to SOAP that allow passing security tokens which securely identify and authenticate clients, ensuring message integrity, and providing message confidentiality. An accompanying spec, the Web Services Security Addendum, adds some details and fixes to the original document.
  • WS-SecurityPolicy, which specifies how to define security assertions that clearly state a Web Service's preferences and requirements.
  • WS-Trust, which defines how to acquire security tokens.
  • WS-SecureConversation, which defines how to create a context for a particular conversation with a Web Service and how to create keys that can be used in that context.
  • Web Services Security Profile for XML-based Tokens, which defines how XML-based technologies such as the Security Assertion Markup Language (SAML) and the eXtensible rights Markup Language (XrML) can be used with WS-Security. It also wins the prize for longest spec name.

Taken as a group, these specs lay the foundation for a usable, interoperable, and quite complete approach to providing security for Web Services.

WS-Security

The fundamental technology for adding security to SOAP is defined by WS-Security. Its ambitious goal is to provide end-to-end message-level security for SOAP messages, and yet the WS-Security spec isn't especially hefty, weighing in at just over 20 pages. This is because WS-Security defines very little new technology but instead defines a way to use existing security technology with SOAP.

Perhaps the most fundamental thing WS-Security defines is a <Security> element that lives inside the SOAP header. The structure of a SOAP message that includes this element is shown in Figure 1. As this simple skeleton shows, WS-Security defines its own namespace. Still, the creators of WS-Security defer to existing standards and technologies wherever possible, focusing instead on specifying how to use them with SOAP.

Figure 1 Security Element

<?xml version="1.0" encoding="utf-8"?>
<s:Envelope xmlns:s="https://schemas.xmlsoap.org/soap/envelope/" 
  xmlns:wsse="https://schemas.xmlsoap.org/ws/2002/12/secext">
    <s:Header>
        <wsse:Security> ••• </wsse:Security>
    </s:Header>
    <s:Body> ••• </s:Body>
</s:Envelope>

WS-Security describes how to attain integrity, which allows a receiver to be sure that data it receives in a message was not modified in transit, and confidentiality, which ensures that data can't be read in transit. It also describes how to send security tokens, such as a username/password combination, a Kerberos ticket, or an X.509 certificate. The next three sections describe how WS-Security addresses each of these areas.

Sending Security Tokens

The most basic question the receiver of a message can have is: who am I talking to? The question is simple, but the answer is not. There are many different ways of indicating identity on a network (a username, Kerberos ticket, X.509 certificate, and so on) and there are also different ways of authenticating that identity. With a username, for example, you might provide an accompanying password to prove that this really is your identity. A Kerberos ticket, by contrast, is encrypted by its issuer using a key that the ticket's receiver can verify is correct. Additionally, digital signature might be sent along with a certificate to authenticate your identity. (For more information on digital signatures, take a look at the sidebar "What's a Digital Signature?")

Wisely, the creators of WS-Security chose to rely on more than one approach for conveying and authenticating identity. In fact, WS-Security doesn't define how to do authentication at all. Instead, the spec defines how a variety of different security tokens can be conveyed within a SOAP header's Security element. The receiver of a token can use the information it contains in any way it likes. The most common use is likely to be authenticating the identity of the token's sender, but tokens can also be used in other ways.

While it allows any type of security token, the WS-Security specification explicitly defines three options. The simplest (although not always the most secure) option is to send a security token containing a username and password. To allow this, WS-Security defines a <UsernameToken> element that can contain a username and password. Here's a simple example of a Security element containing just a <UsernameToken>:

<wsse:Security xmlns:wsse="https://schemas.xmlsoap.org/ws/2002/12/secext">
    <wsse:UsernameToken>
        <wsse:Username>Diana</wsse:Username>
        <wsse:Password>mY5ecRet</wsse:Password>
    </wsse:UsernameToken>
</wsse:Security>

More powerful options are also defined, such as sending a digest version of the password. Because sending unencrypted passwords across a network isn't a very effective authentication mechanism, the UsernameToken element is most likely to be used to authenticate SOAP messages sent across an encrypted connection, such as one that uses Secure Sockets Layer (SSL).

A second option defined by WS-Security is to send a security token containing a Kerberos ticket. Like all security tokens, this ticket is sent in the SOAP header as part of the Security element. Here's an example:

<wsse:Security xmlns:wsse="https://schemas.xmlsoap.org/ws/2002/12/secext">
    <wsse:BinarySecurityToken ValueType="wsse:Kerberosv5ST" 
      EncodingType="wsse:Base64Binary"> QMwcAG ... </wsse:BinarySecurityToken>
</wsse:Security>

As this snippet shows, a Kerberos ticket is sent using the more general <BinarySecurityToken> element. This element's ValueType attribute indicates that this is a Kerberos Version 5 service ticket, which is used to authenticate a client to a particular service. (When a ticket-granting ticket is sent, the ValueType is wsse:Kerberosv5TGT.) The ticket itself, only the first few bytes of which are shown, is represented using base64 encoding, although an option for hexadecimal encoding is also defined.

The third option WS-Security defines for representing security tokens, X.509 certificates, also relies on the <BinarySecurityToken> element. Here's an example:

<wsse:Security xmlns:wsse="https://schemas.xmlsoap.org/ws/2002/12/secext">
    <wsse:BinarySecurityToken ValueType="wsse:X509v3" 
      EncodingType="wsse:Base64Binary"> KkFPle ... </wsse:BinarySecurityToken>
</wsse:Security>

As you can see, not much is different from the previous Kerberos ticket example. This time, the ValueType attribute of the <BinarySecurityToken> indicates that what's being sent is an X.509 certificate. Base64 encoding is used once again, and the certificate itself makes up the content of this element, just as the Kerberos ticket did in the earlier case.

Along with these three options for embedding a security token directly in the header of a SOAP message, WS-Security also defines a <SecurityTokenReference> element. As its name suggests, this element contains a URI that indicates where a security token can be found. This allows the message's receiver to pull the token from wherever it resides, such as a named location on the Internet. This element can also be used to refer to a security token contained within this message's SOAP header, a feature whose usefulness will become clear in the next section.

WS-Security takes an admirably flexible approach to conveying and authenticating identities, yet there's one important implication here: two systems can both conform to WS-Security, but still be incapable of authenticating one another. One system might support only Kerberos, for instance, while the other allows only digital signature-based authentication using X.509 certificates. Just agreeing to use WS-Security isn't enough. Some agreement must also be in place about exactly what kinds of security tokens will be used.

Integrity

Conveying and authenticating identity with SOAP messages is a multifaceted problem, one with many possible solutions. Accordingly, WS-Security takes a commendably broad approach. Providing integrity for SOAP messages, however, is much cleaner. The solution is to use some kind of digital signature, and fortunately, a W3C standard already exists that addresses this area. Called XML Signature, it provides a detailed mechanism for digitally signing XML documents. Rather than reinvent what already exists, WS-Security simply points to this existing specification and fills in a few details on how to use it with SOAP messages.

The main thing defined by the XML Signature specification is a <Signature> element whose contents include both the digital signature itself and information about how this signature was produced. Although there are a few options, a typical instance of <Signature> as used with SOAP contains the <SignedInfo> and <KeyInfo> elements.

The <SignedInfo> element describes the information that is being signed. This element itself contains several subelements, each of which specifies something about the signed information. The most important of these include the following elements.

  • <CanonicalizationMethod> identifies the algorithm that was used to convert this XML document into a standard form before the signature was generated. This process is necessary because for digital signatures to work, each party's view of the signed document must be identical bit-for-bit. Yet without canonicalization, two XML documents that are semantically equivalent can be different at the bit level. One may represent line breaks with a carriage return/line feed pair, for instance, while another may use just a line feed. Canonicalization transforms an XML document into a standard form, ensuring that both parties view a document in the exact same way before signing it.
  • <SignatureMethod> identifies the algorithm used to create the digital signature. Both the XML Signature standard and WS-Security require support for the Digital Signature Standard, which uses Secure Hash Algorithm (SHA)-1 to create a message digest together with the DSA algorithm, and also recommend support for using SHA-1 together with the RSA algorithm.
  • <Reference> identifies the information being signed, along with any transformations that were applied to it. When used with SOAP, this part of the signature typically references the signed parts of this SOAP message, such as the body and parts of the header. The <Reference> element also contains the base64-encoded message digest that was generated from the signed information and specifies the algorithm used to create that digest, such as SHA-1.
  • <SignatureValue> contains the bytes that make up the digital signature.
  • <KeyInfo> indicates what key should be used to validate this signature. The key can be identified in a variety of ways, such as referencing a certificate that contains the appropriate public key. This element can even be omitted entirely, since the recipient may know what key to use by some other means.

Given this basic understanding of XML Signature's <Signature> element, it's possible to see how WS-Security uses it. Figure 2 is an example of how a SOAP message containing a digital signature might look.

Figure 2 SOAP Message with Digital Signature

<?xml version="1.0" encoding="utf-8"?>
<s:Envelope xmlns:s="https://schemas.xmlsoap.org/soap/envelope/" 
  xmlns:wsse="https://schemas.xmlsoap.org/ws/2002/12/secext" 
  xmlns:wsu="https://schemas.xmlsoap.org/ws/2002/07/utility">
    <s:Header>
        <wsse:Security>
            <wsse:BinarySecurityToken ValueType="wsse:X509v3" EncodingType="wsse:Base64Binary" 
              wsu:Id="X509Cert"> KkFPle ... </wsse:BinarySecurityToken>
            <ds:Signature xmlns:ds="https://www.w3.org/2000/09/xmldsig#">
                <ds:SignedInfo>
                    <ds:CanonicalizationMethod Algorithm="https://www.w3.org/2001/10/xml-exc-c14N"/>
                    <ds:SignatureMethod Algorithm="https://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
                    <ds:Reference URI="#MessageBody">
                        <ds:DigestMethod Algorithm="https://www.w3.org/2000/09/xmldsig#sha1"/>
                        <ds:DigestValue> aOb4Luuk... </ds:DigestValue>
                    </ds:Reference>
                </ds:SignedInfo>
                <ds:SignatureValue> A9qqIrtE3xZ... </ds:SignatureValue>
                <ds:KeyInfo>
                    <wsse:SecurityTokenReference>
                        <wsse:Reference URI="#X509Cert"/>
                    </wsse:SecurityTokenReference>
                </ds:KeyInfo>
            </ds:Signature>
        </wsse:Security>
    </s:Header>
    <s:Body wsu:Id="MessageBody"> ••• </s:Body>
</s:Envelope>

In this example, the Header's <Security> element begins with a <BinarySecurityToken>. This element is nearly identical to the X.509 certificate example shown in the previous section. The only difference is that this element uses the Id attribute defined by the Web Services Security Addendum to provide a name for this <BinarySecurityToken>. (Take a look at the sidebar "The wsu Namespace" for more information.) The Id attribute's value, which here is "X509Cert", allows it to be referenced from elsewhere in this header. As you'll see shortly, this is quite useful when a digital signature is also contained in this message.

The <Signature> element defined by the XML Signature standard appears next, containing the subelements described earlier: <SignedInfo>, <SignatureValue>, and <KeyInfo>. Within the <SignedInfo> element appear the identifiers for the algorithms used to canonicalize this XML document and to create its digital signature. The <Reference> element has a URI attribute that specifies exactly what is being signed. In this example, just the body is signed, and so this URI matches the value of the Id attribute associated with the message's <Body> element. The Reference element also contains the two subelements: <DigestMethod> and <DigestValue>. The first of these identifies the algorithm used to create the message digest for this digital signature, while the second contains the message digest value itself. Because only the body is signed in this example, this digest was computed from the canonicalized version of the SOAP message's <Body> element.

The next <Signature> subelement, <SignatureValue>, contains the bytes of the digital signature itself, created by encrypting the message digest with the signer's private key. Finally, the last subelement in <Signature>, <KeyInfo>, identifies where to find the public key that should be used to validate this signature. In this example, that key appeared earlier in the message (in the security token), and it's referenced here through <SecurityTokenReference>. The key is identified using its Id attribute, "X509Cert".

Ensuring data integrity is critically important for many Web Services applications, and having a well-defined and widely accepted approach to providing this service with SOAP is very useful. Digital signatures created using public key technology are also useful for authentication because providing a valid signature along with a trusted certificate proves knowledge of a particular private key and so authenticates one's identity. Yet creating digital signatures for XML documents isn't the simplest thing in the world. Exactly what is being signed must first be identified, then put in canonical form, then actually signed. It can be even more complex than the example shown here, since WS-Security allows the creation of multiple signatures for the same message, each possibly created by a different recipient in the message's path, and each perhaps covering different or overlapping parts of the message. Building all of this according to the W3C XML Signature standard makes good sense, yet SOAP headers that use this aspect of WS-Security are bound to be bigger and more complex than those that don't need this particular security service.

Confidentiality

Keeping data safe from prying eyes while it's in transit is important for a significant number of applications. Accordingly, the third service defined by WS-Security is confidentiality, providing a way to encrypt some or all of a SOAP message before it's transmitted. In the same way they addressed the question of integrity, the authors of WS-Security chose to build on existing standards for confidentiality rather than create something new. Once again, the existing standard they chose, a spec called XML Encryption, came from the W3C. Using this standard, WS-Security allows encrypting all or part of a SOAP message's header information, its body, and any attachments. The XML Encryption spec is not a terribly complex document. WS-Security, for example, uses only three of the XML elements defined by this standard: <EncryptedData>, <EncryptedKey>, and <ReferenceList>.

The most important of these is certainly <EncryptedData>. As its name suggests, this element contains the actual encrypted data in a subelement called <CipherData>. This element can also contain subelements which indicate the encryption algorithm that was used, the key that was used in order to perform the encryption, and more. Figure 3 shows an example of how a simple SOAP message might look if its sender chose to encrypt the message body as defined by WS-Security.

Figure 3 SOAP Message with Encrypted Body

<s:Envelope xmlns:s="https://schemas.xmlsoap.org/soap/envelope/" 
  xmlns:ds="https://www.w3.org/2000/09/xmldsig#" 
  xmlns:xenc="https://www.w3.org/2001/04/xmlenc#">
    <s:Body>
        <xenc:EncryptedData>
            <EncryptionMethod Algorithm='https://www.w3.org/2001/04/xmlenc#tripledes-cbc'/>
            <ds:KeyInfo>
                <ds:KeyName> CN=Key13, C=US </ds:KeyName>
            </ds:KeyInfo>
            <xenc:CipherData>
                <xenc:CipherValue> r5KipsDV . . . </xenc:CipherValue>
            </xenc:CipherData>
        </xenc:EncryptedData>
    </s:Body>
</s:Envelope>

Note first that no SOAP header appears in the message. While this isn't likely in a real application, it is possible to use XML Encryption as defined by WS-Security without the Security element or any other Header elements. In this simple example, the message's body contains only an <EncryptedData> element with three subelements. The first of these, <EncryptionMethod>, indicates what algorithm was used to encrypt the data. In this case, the symmetric algorithm TripleDES was chosen, and so the same key is used to encrypt and decrypt the data. The next subelement is <KeyInfo>, borrowed from XML Signature. Here, it is assumed that both sides already know all of the keys available for use in encryption and decryption, so the only thing required is to inform the receiver of which one was chosen. The key's name could be anything, but one possibility is that keys be named with LDAP-style distinguished names. Accordingly, this example specifies the key's name as "CN=Key13, C=US". Whatever name is used, the important thing is that both sides understand exactly which key this name references. Finally, the <CipherData> subelement appears, carrying within its <CipherValue> subelement the base64 encoding of the actual encrypted data.

It's also possible to convey an encrypted key in the same message that carries data that was encrypted using that key. A common example of this is when data is encrypted using a symmetric key, as in the TripleDES example in Figure 3, then that symmetric key is encrypted using the public key of the message's recipient and sent along with the data. When the message arrives, the recipient can use its private key to decrypt the embedded symmetric key, then use this symmetric key to decrypt the actual data. To send an encrypted key, XML Encryption defines an element with the obvious name of <EncryptedKey>. For use with SOAP messages, WS-Security specifies that this element should appear in the <Security> header. Accordingly, a SOAP message that carries both encrypted data and the encrypted symmetric key needed to read that data might look like Figure 4.

Figure 4 Encrypted SOAP Message with Key

<s:Envelope xmlns:s="https://schemas.xmlsoap.org/soap/envelope/" 
  xmlns:wsse="https://schemas.xmlsoap.org/ws/2002/12/secext" 
  xmlns:wsu="https://schemas.xmlsoap.org/ws/2002/07/utility" 
  xmlns:ds="https://www.w3.org/2000/09/xmldsig#" 
  xmlns:xenc="https://www.w3.org/2001/04/xmlenc#">
    <s:Header>
        <wsse:Security>
            <xenc:EncryptedKey>
                <xenc:EncryptionMethod Algorithm="https://www.w3.org/2001/04/xmlenc#rsa-1_5"/>
                <ds:KeyInfo>
                    <ds:KeyName> CN=Key13, C=US </ds:KeyName>
                </ds:KeyInfo>
                <xenc:CipherData>
                    <xenc:CipherValue> ir4DfG . . . </xenc:CipherValue>
                </xenc:CipherData>
                <xenc:ReferenceList>
                    <xenc:DataReference URI="#EncryptedBody"/>
                </xenc:ReferenceList>
            </xenc:EncryptedKey>
        </wsse:Security>
    </s:Header>
    <s:Body>
        <xenc:EncryptedData wsu:Id="EncryptedBody">
            <xenc:EncryptionMethod Algorithm='https://www.w3.org/2001/04/xmlenc#tripledes-cbc'/>
            <xenc:CipherData>
                <xenc:CipherValue> r5KipsDV . . . </xenc:CipherValue>
            </xenc:CipherData>
        </xenc:EncryptedData>
    </s:Body>
</s:Envelope>

Unlike the unrealistically simple example in Figure 3, the SOAP message in Figure 4 contains a header with a Security element. This element contains just the subelement <EncryptedKey>, defined in the XML Encryption standard. The format of <EncryptedKey> is much like <EncryptedData> and in this example, it has the three familiar subelements: <EncryptionMethod>, <KeyInfo>, and <CipherData>. What's being encrypted here is a symmetric key, so <EncryptionMethod> describes how this key was encrypted rather than how the actual data was encrypted. Since we're assuming that this is a symmetric key encrypted using the recipient's public key, this element indicates that the RSA algorithm was used to encrypt this key. The <KeyInfo> element names the symmetric key that's conveyed as part of this <EncryptedKey>, and since we're assuming it's the same key as in the previous example, it has the same name. Unlike the earlier <EncryptedData> element, the <CipherData> element in this <EncryptedKey> contains an encrypted symmetric key rather than any user data.

The <EncryptedKey> element has a new subelement as well, one that wasn't present in <EncryptedData>. This element, <ReferenceList>, plays the important role of associating this key with the data that was encrypted using it. It contains a URI that identifies the portion of this SOAP message that was encrypted using the key contained in this <EncryptedKey> element. In Figure 4, the entire SOAP body is encrypted with this key and so the rather unimaginative name, "EncryptedBody," is used.What's a Digital Signature?

M ost of the time, the term "digital signature" refers to something created using public key technology. This technology assumes that you are given a pair of keys: a private key, which only you know, and a corresponding public key, which you can freely reveal to anyone. The cool thing about these two keys is that anything encrypted using one key can be decrypted only with the other one.

If I want to attach a digital signature to something, I first compute a special kind of checksum called a message digest on the information I want to sign. I then encrypt this digest, which is typically around 20 bytes, using my private key. The result is a digital signature for this information. If I send you the information along with this signature, you need know only my public key to validate the signature. To do this, you compute a message digest on the received data, and then use my public key to decrypt the digital signature. If the results of these two operations are identical, you can be certain both that the data wasn't changed in transit (integrity) and that the data was signed by me (authentication). Of course, you have to be certain that this really was my public key, so you'll probably extract it from a certificate whose issuer you trust.

This is the classic definition of a digital signature. Interestingly, though, that's not exactly what is meant in XML Signature. While XML Signature certainly allows using public key-based digital signatures, it also supports the idea of encrypting a message digest with a symmetric (secret) key. This approach still provides integrity (it's what Kerberos uses, for example), but it doesn't provide the same level of authentication as a public key-based signature. Since two or more parties know the symmetric key, data encrypted using it could have come from any one of them. Accordingly, this kind of signature doesn't allow you to learn exactly who created it. Still, it's a useful option, so WS-Security supports this non-public key-based approach to providing data integrity as well as more conventional digital signatures.

The SOAP body itself looks much as it did in Figure 3. One difference is that the beginning tag of the <EncryptedData> element now has an Id attribute with the name "EncryptedBody." As just described, this is how the data this element carries is associated with the key used to encrypt that data. The other difference is that since the key used to encrypt this element's contents is clearly identified, there's no need for the <KeyInfo> element in <EncryptedData>.

As defined by WS-Security, XML Encryption can be used in a number of ways with SOAP messages. You can encrypt the entire body, the body and certain header elements, just parts of the body, or even attachments sent with the message. Different receivers of a SOAP message can add their own encrypted headers or decrypt and process parts intended solely for them. Because the requirements for confidentiality in Web Services are so diverse, the standard that defines how to do it must also be quite versatile.

WS-Security does a good job of specifying the basics for providing security with SOAP, but it doesn't address everything. As a result, several other specifications have been created that fill in some of the gaps. The following sections take a look at these documents and the technology they define.

Specifying Policies: WS-SecurityPolicy

Whenever security mechanisms are being used, some kind of security policies must also exist. These policies clarify the specific security requirements for a particular situation. With a Web Service using WS-Security, for example, many details need to be made clear. Does this service accept Kerberos tickets for authentication, X.509 certificates and digital signatures, or something else? What digital signature algorithms are accepted? What encryption algorithms are supported for providing confidentiality? Answering these kinds of questions means defining security policies.

Policies are useful in areas other than security, of course, and so Microsoft, IBM, and others have created the WS-Policy specification. This document defines a general approach to specifying policies of all kinds for Web Services. WS-SecurityPolicy builds on this foundation, defining XML elements that can be used to specify security-related policies. These elements are referred to as assertions because they allow a Web Service to specify its policies in an unambiguous way. The assertions defined by WS-SecurityPolicy include the following.

  • <SecurityToken> allows a Web Service to specify what types of security tokens it will accept and, optionally, which issuers of those tokens it trusts.
  • <Integrity> allows a Web Service to specify various options about the digital signatures it will accept, such as the algorithm used to create a message digest.
  • <Confidentiality> allows a Web Service to specify options about how encryption should be performed, such as the encryption algorithm used.
  • <Visibility> allows a Web Service to specify that certain portions of a message must be unencrypted.

Exactly how security policies are conveyed from their creator to any interested clients is not defined by WS-SecurityPolicy. The XML elements that express policies might be sent in a SOAP message or conveyed in some other way. WS-Policy does define a general <Policy> element, however, that can contain one or more policy assertions. Here's a simple example of how a <SecurityToken> assertion might look for a Web Service that requires a Kerberos ticket for authentication:

<wsp:Policy xmlns:wsp="https://schemas.xmlsoap.org/ws/2002/12/policy 
  xmlns:wsse="https://schemas.xmlsoap.org/ws/2002/12/secext"> 
  <wsse:SecurityToken wsp:Usage="wsp:Required"> 
    <TokenType> wsse:Kerberosv5ST</TokenType> 
  </wsse:SecurityToken> 
</wsp:Policy>

This <Policy> element specifies namespaces defined in both WS-Policy and WS-Security, and contains just the <SecurityToken> subelement. This subelement's usage is marked as Required, which means that the Web Service requires adherence to this policy. In other words, as the <TokenType> element indicates, this particular Web Service will now accept only Kerberos tickets as the basis for authentication.

A single <Policy> element can contain policies about security tokens, integrity, and other things. There are also several more options, including ways to specify relative preferences. For example, a Web Service can define a <SecurityToken> that allows clients to authenticate using either Kerberos or X.509 certificates, then indicate that it prefers Kerberos. Whatever options are used, however, the value of policies is apparent. By providing an unambiguous way for a Web Service to state its security requirements, they make clear what clients must do to access that service.

Acquiring Security Tokens: WS-Trust

Security tokens are fundamental to WS-Security, yet they've just magically appeared and no mechanism has been defined to give them out. The truth is that just as various kinds of security tokens already exist, software services already exist that are capable of handing them out. To get a Kerberos ticket, for instance, you contact a Kerberos Key Distribution Center (KDC), while to get an X.509 certificate, you might contact a certification authority (CA). While WS-Security defines how to wrap Kerberos tickets and X.509 certificates inside standard XML for transmission in a SOAP message, it doesn't define a way to use SOAP to talk to a KDC, a CA, or any other service capable of handing out a security token.

Figure 5 WS-Trust

Figure 5** WS-Trust **

WS-Trust fixes this problem. The main thing this spec defines is a mechanism for requesting security tokens from some security token service, such as a KDC or a CA. Figure 5 illustrates this idea. Suppose a client wants to invoke both Web Service A and Web Service B. Suppose further that Web Service A requires a Kerberos ticket for authentication, while Web Service B demands a digital signature and matching X.509 certificate. As the figure shows, the client might first make a SOAP request to Security Token Service X, which is in fact a KDC, requesting a Kerberos ticket wrapped inside a <BinarySecurityToken>. It can then invoke Web Service A, passing this newly acquired token in the <Security> element of the SOAP message. Next, the client can make a SOAP request to Security Token Service Y, which is a CA, requesting an X.509 certificate. Once this is returned, the client can invoke Web Service B, passing this certificate and a matching digital signature.

WS-Trust defines what requests to a security token service look like and how responses are sent back. The interaction relies on two elements: <RequestSecurityToken> and <RequestSecurityTokenResponse>. The basic idea is to send a SOAP message containing a <RequestSecurityToken> as its body, then get back a SOAP message containing a <RequestSecurityTokenResponse>, complete with the new security token. Figure 6 shows a simple example of a request message.

Figure 6 Request Message

<?xml version="1.0" encoding="utf-8"?>
<s:Envelope xmlns:s="https://schemas.xmlsoap.org/soap/envelope/" 
  xmlns:wsse="https://schemas.xmlsoap.org/ws/2002/12/secext" 
  xmlns:wsu="https://schemas.xmlsoap.org/ws/2002/07/utility">
    <s:Header>
        <wsse:Security>
            <wsse:UsernameToken wsu:Id="MyCert">
                <wsse:Username>Diana</wsse:Username>
                <wsse:Password>mY5ecRet</wsse:Password>
            </wsse:UsernameToken>
        </wsse:Security>
    </s:Header>
    <s:Body>
        <wsse:RequestSecurityToken>
            <wsse:TokenType>wsse:X509v3</wsse:TokenType>
            <wsse:RequestType>wsse:ReqIssue</wsse:RequestType>
            <wsse:Base>
                <wsse:Reference URI="#MyCert"/>
            </wsse:Base>
        </wsse:RequestSecurityToken>
    </s:Body>
</s:Envelope>

The Security header contains a <UsernameToken> to authenticate this request. While the simple choice used here might be reasonable if this request was sent over an encrypted SSL connection, sending this request in the clear would require a more robust security token, probably one that included both a digital signature and a timestamp. The message body contains the <RequestSecurityToken> element, which requests that an X.509 certificate be issued. Assuming the request is successful, the body of the response returned by the security token service might look like this:

<s:Body>
    <wsse:RequestSecurityTokenResponse>
        <wsse:RequestedSecurityToken>
            <wsse:BinarySecurityToken ValueType="wsse:X509v3" 
              EncodingType="wsse:Base64Binary"> 
              KkFPle ... 
            </wsse:BinarySecurityToken>
        </wsse:RequestedSecurityToken>
    </wsse:RequestSecurityTokenResponse>
</s:Body>

The requested certificate is returned, wrapped in the <BinarySecurityToken> element defined by WS-Security. Although it's not shown in this example, it's also possible that the private key associated with this certificate's public key would be returned as well. To allow this, WS-Trust defines a <RequestedProofToken> element to contain this or analogous information for other types of security tokens.

WS-Trust also defines quite a few extensions to the basic <RequestSecurityToken> element. Among them are options for requesting that specific algorithms and key sizes be used in constructing the requested security token. For instance, the requester can ask that RSA with 1024-bit keys should be used for creating digital signatures. There is also a mechanism for requesting a security token on behalf of someone other than the requester. And a third extension offers a way to specify the lifetime of the security token and whether that lifetime can be renewed.

WS-Trust also defines a challenge/response mechanism that can optionally be used when a security token is requested from a security token service. While a straightforward authentication mechanism such as the one shown in Figure 5 might be fine in some cases, it's possible that a security token service might want more proof of who it's talking to. What if, as in the example just shown, the request contains no timestamp? How can the security token service be certain that this isn't a replay of an earlier request that is now being sent by an attacker? In order to prevent this, the security token service might challenge the requester to digitally sign a specific set of information, then validate the signature before issuing the requested security token.

Establishing Context: WS-SecureConversation

Sometimes all that's required to solve a problem is a simple exchange of one or two SOAP messages. Invoking a single remote operation, for example, might require nothing more than this. But suppose an application needs to exchange lots of SOAP messages with some other application, perhaps by invoking a series of operations. In cases like this, it can be useful to create some kind of shared security context between the two applications. One common use of this shared context is to define a lifetime for an encryption key that will be used for the context's duration. For example, two communicating parties might want to create a symmetric key, then use it to encrypt the information they exchange over the lifetime of a particular security context. (A non-Web Services example of this is SSL, which creates a new key to encrypt the bytes transferred within each session.)

WS-SecureConversation defines XML types and interactions that allow the establishment of a security context and the creation of keys that are specific to that context—that is, keys that are used only for a particular session. The foundation for these mechanisms is the <SecurityContextToken> element. As defined by this spec, every security context has a name and a shared secret, and so a <SecurityContextToken> can contain an <Identifier> subelement that uniquely names this context together with one or more encrypted keys for use in this context.

WS-SecureConversation defines three possible approaches to creating a <SecurityContextToken>. First, a <SecurityContextToken> can be requested from some security token service. To do this, the requester sends a SOAP message containing a <RequestSecurityToken> element to a security token service in the body, just as if an ordinary security token were being requested. The service responds with a SOAP message, the body of which contains a <RequestSecurityTokenResponse> element that contains the requested <SecurityContextToken> and a <RequestedProofToken> containing a shared secret for this new context, such as an encrypted symmetric key.

Second, a <SecurityContextToken> can be created by one of the communicating parties and sent to the other. In this case, the creator of <SecurityContextToken> sends the new token in a SOAP message containing a <RequestSecurityTokenResponse>. (There is no <RequestSecurityToken> sent first). This is the same message received from the security token service in the previous case, so it contains both the new <SecurityContextToken> and the <RequestedProofToken>.

Third, a <SecurityContextToken> can be created through negotiation between the parties that will use the context. One party sends the other a SOAP message containing a <RequestSecurityToken>, then receives a response that contains a <RequestSecurityTokenResponse>. Although it's not required, this exchange is likely to rely on the WS-Trust-defined challenge/response negotiation process described earlier. If the negotiation succeeds, the result is that both parties wind up with a new <SecurityTokenReference> and <RequestedProofToken>.

However it's created, a security context always contains a shared secret, such as a symmetric key. This key can be used directly for encrypting or signing messages, but WS-SecureConversation recommends against this. Instead it's more secure to derive one or more keys from the security context's shared secret and then use a derived key for the communication. The spec defines one algorithm for creating derived keys, based on the approach used in the Transport Level Security (TLS) spec. Other approaches can also be used to generate derived keys, as the spec doesn't require the use of the algorithm that it defines.

Once a security context has been created, all that's required is to identify the context in each SOAP message. Each side of the communication already knows which key (or keys) to use in processing this message, since the context implies this. Once the context exists, then the Security element of a SOAP message using it will contain a <SecurityContextToken> element with this context's unique identifier. By examining this identifier, the message's receiver can determine what security context is being used.

Security contexts are nice to have, as shown by their use today in SSL and Kerberos, among other security technologies; WS-SecureConversation makes them available to Web Services applications.

Using SAML and Other XML-based Tokens

As I described earlier in this article, WS-Security defines two XML elements for representing security tokens. But what about other kinds of security tokens? In particular, what about security tokens that are already defined using XML? WS-Security itself doesn't address how this kind of token should be represented, so a specification called Web Services Security Profile for XML-based Tokens remedies this problem. It defines a general approach to using XML-based security tokens with WS-Security, and then specifies how to use two types of existing XML tokens.

The first type of XML security token addressed by this spec is defined using the Security Assertion Markup Language (SAML). SAML is likely to be a reasonably popular technology, but understanding it is nontrivial. (If you're an insomniac, then a copy of the SAML spec works like a charm when sleep won't come.) As its name suggests, the language allows you to express a wide range of assertions about subjects, such as people or applications. These assertions can be about authentication (how it was done), or authorization (whether access was granted to a particular resource), or something else. The assertions themselves can be authenticated using XML Signature, although this isn't required.

Rather than define another type of security token element, SAML assertions can be inserted directly into a SOAP header's <Security> element. Unlike Kerberos tickets or X.509 certificates, SAML assertions are already expressed in XML, so this is easy to do. The slightly simplified result is shown in Figure 7. As this example illustrates, a SAML Assertion element can be dropped in its native form into the Security element. Although it's not shown in this example, the AssertionID attribute can be used to associate this SAML security token with a digital signature or something else within this SOAP message.

Figure 7 SAML Assertion

<?xml version="1.0" encoding="utf-8"?>
<s:Envelope xmlns:s="https://schemas.xmlsoap.org/soap/envelope/" 
  xmlns:wsse="https://schemas.xmlsoap.org/ws/2002/12/secext" 
  xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion">
    <s:Header>
        <wsse:Security>
            <saml:Assertion MajorVersion="1" MinorVersion="0" AssertionID="SecurityToken-ef375268" 
              Issuer="dcatignani" IssueInstant="2003-05-23T11:04:15.8357639-08:00"> 
              ••• 
            </saml:Assertion>
        </wsse:Security>
    </s:Header>
    <s:Body> ••• </s:Body>
</s:Envelope>

The other type of XML security token addressed by the Web Services Security Profile for XML-based Tokens spec is XrML. XrML allows you to express rights about digital content or services, such as the right to access a particular Web Service or to play a specific audio file. It defines a <license> element that can be dropped into a SOAP header's Security element in the same manner as a SAML <Assertion>.

SAML and XrML are relatively new technologies, so you might not see these options used with SOAP for a while yet. Still, either or both of them may become very popular over time, and other XML-based tokens are also likely to emerge. Providing a standard approach for including those tokens in a SOAP message makes sense.The wsu Namespace

T he Web Services Security Addendum defines quite a few extensions (and some fixes) to the original WS-Security spec. The new XML elements this document defines are contained in a Web Services utility namespace, identified by https://schemas.xmlsoap.org/ws/2002/07/utility and conventionally given the prefix wsu. This namespace includes two things that are most important for WS-Security. The first is an Id attribute that can be applied to various elements. In WS-Security, it plays an important role in both signatures and encryption. The second is a <Timestamp> element that can be sent within a SOAP message's header. Among other things, this element can contain subelements that indicate when a message was created, when any intermediaries received it, and when it should expire. The receiver of a message might use this information to decide whether a message is stale and should be ignored, to detect replays of the same message, or for some other purpose. No particular mechanism is mandated for synchronizing clocks, however, so the systems involved must deal with this problem in some other way.

Getting complicated specs right the first time is essentially impossible, so it's not too surprising that some things were added after the first version. Chances are that you'll see more additions as the understanding of the problems to be solved improves.

Conclusion

Effective security for Web Services is essential. Given that most of what's needed is already in place (and the problem is simply a matter of mapping this existing security technology to XML and SOAP), you might think that WS-Security and its associated specs would be very simple (and this article would be very short). Yet accommodating the diverse security mechanisms in use today, along with allowing for those that will appear tomorrow, requires a nontrivial set of technology. Once this technology is in place, the world of secure and interoperable Web Services that we'd all like to see can become a reality. I don't know about you, but I can't wait for this day to arrive.

For background information see:
WS-Security Specification Index Page
ASP.NET Security: An Introductory Guide to Building and Deploying More Secure Sites with ASP.NET and IIS
MSDN Magazine Security issue

David Chappellis Principal of Chappell & Associates in San Francisco, CA. He has given keynotes and seminars on Microsoft technologies in more than 30 countries, and his most recent book, Understanding .NET, was published last year by Addison-Wesley.