Security interoperability with .NET/WSE and WebLogic Workshop 8.1

In this article, Michele Leroux Bustamante shows how to create interoperable applications in .NET with WSE and WebLogic Workshop using web services that implement the WS-Security specification. In particular, she shows how to use UsernameTokens in a .NET client and then authenticate it using WebLogic, and vice versa.

Platform tools for Web services have come a long way since Simple Object Access Protocol (SOAP) and Web Service

Description Language (WSDL) burst onto the scene in 2000. Early adopters of SOAP -- anxious to be free of the integration challenges across other RPC-based protocols such as DCOM, CORBA and RMI -- were ready to embrace the first SOAP protocol libraries offered by their respective platforms.

By the time the .NET Framework was released, SOAP was already a household name (at least among geeks) and thus was fully integrated into the framework with baked-in IDE support in Visual Studio. Of course Sun and Apache also supplied Java libraries to support SOAP protocol very early on (among others), and from this the possibilities of true message level interoperability between .NET and Java were immediately present.

Of course, there were some bumps along the way with respect to incompatibilities between platform serialization mechanisms, forcing early adopters of the protocol to stare at XML for hours, drink more coffee and lose sleep in order to resolve issues. These valiant efforts are what fed today's almost seamless interoperability between implementations as libraries have evolved and adapted their interpretations of SOAP, WSDL and XML Schema to be more predictable. Serialization incompatibilities still exist, but they are far less frequent and can generally be overcome by intercepting the serialization process and slinging some custom code to make it work.

Why the brief history? It just so happens that we're in the middle of a déjà vu regarding the evolution and adoption of other new protocols that extend SOAP. An inescapable pileup of specifications -- affectionately known as WS* -- are helping to standardize mechanisms for secure and reliable messaging, workflow, transactions and more. As in the early days of SOAP protocol the early adopters of WS* must come together to work through interoperability issues so that tool support can influence mass adoption by simplifying the process of applying these specifications.

Figure 1 illustrates the core categories of Web services messaging standards, specifically detailing the core list of security standards – some ratified, and some on their way to ratification. WS-Security was the first of the emerging specifications to be ratified by OASIS with Web Services Security: SOAP Message Security 1.0 (WSS: SOAP Message Security) and a number of token profiles including the UsernameToken Profile 1.0 (UsernameToken Profile) and the X.509 Certificate Token Profile 1.0 (X.509 Certificate Profile). Soon after, WS-I provided a set of guidelines for interoperability through its publication of Basic Security Profile 1.1 (Basic Security Profile). WS-Security describes an interoperable way to authenticate the message sender, ensure message integrity, protect messages with encryption and even prevent replay attacks.

Figure 1: Standards for securing Web services

Though WS-Security is an approved standard, the challenge facing platform vendors is supporting the same level of seamless interoperability with emerging standards as they have achieved for the most part with SOAP and WSDL. But this challenge runs deeper than before, because they must come up with viable implementations of the standards while they continue to mature, even before they are ratified. This requires an escalated release cycle, coupled with platform configurability and extensibility to overcome discrepancies during the transition.

There is no doubt that the future of WS* interoperability is bright with SOA platforms such as the Windows Communication Framework (formerly code name Indigo) and equivalent major updates in the world of J2EE. But, the fact is that I receive numerous requests about interoperability for today’s deployed platforms.

In this article, I will focus on the state of WS-Security interoperability between the .NET Framework with Web Services Enhancements (WSE) and BEA’s productivity platform for Web services, WebLogic Workshop 8.1 (WebLogic Workshop). In the process I will discuss the core components of OASIS WS-Security, how to implement relevant security scenarios in both platforms, and specifically discuss approaches to configuring WSE in order to address variations in each platform’s interpretation of the ratified standard.

You Had Me at SOAP…Now Grant me Security!

Before I get to the implementation details of OASIS WS-Security for WSE and WebLogic Workshop, let me elaborate on the importance of message level security. The first question on your mind is probably, “Why isn’t SSL enough?” In fact, since SOAP didn’t provide any mechanism for securing messages, SSL has been long considered “good enough security” for Web services over HTTP. Other transport-level security mechanisms like TLS and IPSec may also be embraced to transmit SOAP messages in a similar, encrypted and secure tunnel. For many companies this may still be good enough, however, the decision to stick with transport level security should only be made after being educated on the benefits of message level security with WS-Security.

SSL, TLS and IPSec are all techniques for creating a secure channel through which messages can be transported. Through a secure key exchange, a session key is negotiated between sender and receiver that can be used encrypt messages between parties for the duration of the session. In the case of a Web service request, this key is used to encrypt the request that posts the message to the receiver and the message response returned (synchronously) to the sender. This point-to-point encryption relies on a trust relationship between the message sender and the ultimate receiver as shown in Figure 2 (a). When a message arrives at either point it is immediately decrypted. But this does not address the case when an intermediary hop exists between sender and receiver. Message level security can ensure messages are encrypted through to the ultimate receiver, as illustrated in Figure 2 (b).

Figure 2: (a) SSL, TLS and IPSec make it possible to secure messages point-to-point. (b) With message level security the actual message is encrypted until safely arriving at the ultimate receiver, despite transport hops.

In most cases, the involvement of an intermediary will not be known to applications sending or receiving messages. An XML firewall could be installed at the receiver to inspect SOAP headers and handle rejection of messages that don’t comply with security policy. A router endpoint could receive messages before deciding the path for the message behind the firewall. Even on the sender side, proxies are sometimes present to mask the sender’s IP address. The bottom line is, unless the data being sent is not considered private or critical to the business, the fact that the data is in the clear to anyone other than the intended recipient is just plain risky.

Besides providing confidentiality of the message through to the ultimate receiver, other principles of message level security can also be applied to specific message parts despite the presence of intermediaries and possibly varied protocols for transporting messages between points, such as the following:

  • Encrypting specific message parts enabling intermediaries to inspect certain message headers, like those that apply to routing, security or other policy verification, without gaining access to other protected message parts.
  • Authentication to prove not only the physical origin of the message, but the originating entity as described by username, X509 certificate or some other symmetric security token.
  • Signing specific message parts so that they can be separately verified for integrity by each signing party.
  • Preventing message replay beyond that supplied by the transport protocol. There are many layers to how Denial of Service (DoS) attacks can be prevented including firewalls that intelligently inspect packets for suspected replays, but it can also be useful inspect message parts for specific elements that should not be replayed.

WS-Security describes how to attach XML and binary tokens to SOAP messages, and how to leverage the XML Digital Signature and XML Encryption specifications to achieve these goals. In the following sections I’ll describe how .NET with WSE and WebLogic Workshop apply these security principles, and what we have to do to make sure they work well together.

Authentication with UsernameToken

One of the primary goals of securing a Web service is authentication of the sender of the message. Before WS-Security, many services rolled their own authentication mechanism whereby credentials were passed to the service. Typical patterns included passing credentials in each method call or the provision of Login and Logout methods that relied on an active session for method calls in between to be legal. The former meant receiving credentials in method calls, littering the business functionality of the method call with authentication semantics. The latter often relied on HTTP sessions to authenticate calls to protected methods, coupling authentication to the underlying transport protocol.

Although the actual data passed to the service providing credential information could be interoperable across platforms simply by leveraging WSDL to describe the required parameters, the inability to switch protocols or authentication mechanisms without modifying the service and its clients proposes a problem. Not to mention the productivity loss from rolling custom code every time a service or client wants to work with what would seem to be a very simple construct.

The WS-Security UsernameToken profile provides a standards-based way to send simple user credentials so that applications and platforms can unify their approach. It moves credentials outside the actual operation into SOAP headers, making it possible to alter authentication without touching the operation. It also enables platforms to include generic code to process username and password to remove the work from developers and allow for interoperability.

UsernameToken can be used to identify different types of users including the user logged in to the application that invokes the service or the actual enterprise that has a partnership with the service provider. Regardless of their meaning, using the UsernameToken profile these credentials can be passed in a standards-based way, and both WebLogic Workshop and WSE 2.0/3.0 support the standard with some minor variations between them.

Facets of the serialized UsernameToken include:

  • The actual Username and Password value, where Password can be omitted (assumes authentication has already taken place), sent in clear text, or sent hashed according to specification rules.
  • A Nonce and Created timestamp value that together increase the security of the password hash, and can be used to prevent token replay attacks.
  • UsernameToken can be used to sign message parts, typically by calculating a DerivedKeyToken that is used for signing.

Let’s see how WSE and WebLogic Workshop are able to exchange messages that authenticate with this token format.

UsernameToken: From WSE to WebLogic Workshop

To add WS-Security messaging support to a .NET client application, you have to first enable WSE support for the project through the IDE. A reference is added to the Microsoft.Web.Services2.dll and a new configuration section is defined in the client’s configuration file (app.config or web.config). Ultimately, the Web service proxy is in charge of message serialization/deserialization, so it is important to enable WSE before creating a Web Reference to the target service’s WSDL. When WSE is enabled, two proxy types are generated: one inherits SoapHttpClientProtocol (plain old WSDL support), the other inherits WSE’s WebServicesClientProtocol (WS* support).

public class ImageLibraryWse : 


Microsoft.Web.Services2.WebServicesClientProtocol { …  }

WSE provides two ways to configure WS-Security: declaratively through policy, or imperatively in code using the WSE library. Policy configuration is achieved through a wizard interface installed with the WSE Visual Studio extension. Alternatively code can be written to manually attach tokens, signatures and encrypted data elements to the proxy in order to trigger serialization of those objects. The WSE library includes built-in abstractions of the WS-Security specification elements, for example a <wsse:UsernameToken> WS-Security element is represented by the UsernameToken type found in the Microsoft.Web.Services2.Security.Tokens namespace. The internals of the proxy handle serialization of objects you attach to it. So, after collecting username and password from the application user you can create a UsernameToken object and attach that to the Tokens collection of the WSE proxy as follows:

using Microsoft.Web.Services2.Security.Tokens;


UsernameToken token = new UsernameToken(username, password,
PasswordOption.SendHashed);
this.serviceProxy.RequestSoapContext.Security.Tokens.Add(token);

When a service operation is invoked through the proxy, the UsernameToken will be serialized into the WS-Security message header as follows:

<wsse:Security soap:mustUnderstand="1">

<wsu:Timestamp wsu:Id="Timestamp-fd73c1d5-c9c1-4b1d-af4b-f1c6766bbb0d">
  
  <wsu:Created>2005-07-12T18:39:14Z</wsu:Created> 
  
  <wsu:Expires>2005-07-12T18:44:14Z</wsu:Expires> 

</wsu:Timestamp>

<wsse:UsernameToken xmlns:wsu="http://docs.oasis-
  open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
   wsu:Id="SecurityToken-9efa893f-2ab4-4fc7-8ade-cf76fae00dd3">

 <wsse:Username>Admin</wsse:Username> 
 
 <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-
   200401-wss-username-token-profile-
  1.0#PasswordDigest">NX68xPJrCL2AXsEgYnxz8yUoYxw=</wsse:Password> 
  
 <wsse:Nonce>W4rsmktRtlVjBHc2z7xafg==</wsse:Nonce> 
  
 <wsu:Created>2005-07-12T18:39:14Z</wsu:Created> 

</wsse:UsernameToken>

</wsse:Security>

Notice that the password is hashed. It's a simple way to protect it during transport when the message is not otherwise encrypted. Hashed passwords rely on the Nonce and Created timestamp to generate the hashed password value based on the following algorithm defined in the UsernameToken Profile specification:

Password_Digest = Base64 ( SHA-1 ( nonce + created + password ) )

Hashed passwords are not currently supported by WebLogic. In fact the only password format supported today by WebLogic Workshop is clear text. So, in the name of interoperability we must send the password in clear text and use another form of encryption to protect it which I’ll discuss later.

Changing the PasswordOption parameter to PasswordOption.SendPlainText will serialize the UsernameToken to the following:

<wsse:UsernameToken xmlns:wsu="http://docs.oasis-
   open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
   wsu:Id="SecurityToken-fda8d5fa-4904-4ab1-9544-8c66641b5ea0">

  <wsse:Username>Admin</wsse:Username>

  <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-
   200401-wss-username-token-profile-
    1.0#PasswordText">p@ssw0rd</wsse:Password>

  <wsse:Nonce>yyN2OvkjSR+fQY3KsjSwXw==</wsse:Nonce>

  <wsu:Created>2005-07-12T18:31:10Z</wsu:Created> 

</wsse:UsernameToken>

Now let’s see how to configure WebLogic to authenticate the user specified by the UsernameToken element.

The WebLogic Workshop stack provides built-in support for WS-Security, so there are no additional installation steps to gain support within the IDE. It is important to note that for WebLogic development there are two distinct stacks available: the WebLogic Server stack and the WebLogic Workshop stack. The former comprises the low-level APIs for building server applications including Web services, and the latter provides additional classes and configuration capabilities for building applications including Web services more productively through the WebLogic Workshop development environment. (You can assume for the rest of this article when I say “WebLogic” I am referring to the WebLogic Workshop stack.)

Web service endpoints are exposed by WebLogic through a .jws file. Its properties include ws-security-service, a setting that names the WS-Security configuration file for the service. To add WS-Security support to a service endpoint you set this property to the name of the file as shown in Figure 3. Creating the actual file by this name is done by adding a new WS-Security Policy File template to the application.

Figure 3: Web services and service controls that invoke remote services can have a policy file associated with them to configure WS-Security settings.

The final version of the inbound service configuration for the sample is shown in Listing 1 below.

<?xml version="1.0" ?> 

<wsSecurityPolicy xsi:schemaLocation="WSSecurity-policy.xsd"
    
 xmlns="http://www.bea.com/2003/03/wsse/config"
    
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    
 <wsSecurityIn>
  
  <token tokenType="username"/>
        
  <encryptionRequired>
   
   <decryptionKey>
    
    <alias>iwserver</alias>
    
    <password>iwserver</password>
   
   </decryptionKey>
  
  </encryptionRequired> 
        
  <signatureRequired>true</signatureRequired>
    
 </wsSecurityIn>
    
 <keyStore>
        
  <keyStoreLocation>teststore.jks</keyStoreLocation>
        
  <keyStorePassword>teststore</keyStorePassword>
    
 </keyStore>

</wsSecurityPolicy>

Listing 1 – Security policy configuration for the WebLogic service receiving messages from a .NET client.

To require a UsernameToken be provided with incoming messages to the service, the policy configuration file should include the following <token> element:

<token tokenType="username"/>

This tells the runtime that inbound messages to the associated service MUST include a valid UsernameToken. WebLogic by default will authenticate the user against its application credential store and throw a SOAP fault for unauthenticated users.

Summary: UsernameToken Interoperability from WSE to WebLogic Workshop

WSE can serialize UsernameToken using all password format variations. WebLogic accepts only clear text passwords today therefore alternate encryption mechanisms must be used to protect the password.

Thoughts on Password Hashing

In fact sending hashed passwords is not the best way to communicate with any service due to the fact that most credential stores store their passwords hashed. If the UsernameToken password is hashed there will be no way to reverse the WSE hash and compare the actual password against the hashed credential store. To solve this problem clients must either a) use the same database hashing algorithm on the clear password before WSE hashes (double hashing), or b) send encrypted clear text passwords so that the service can decrypt the password and use its own database hashing algorithm on the supplied password to compare against the hashed database value. Option b) keeps the database hashing algorithm secret from clients, and reduced overhead of clients invoking the service. For more details on this implementation see my blog post on the subject.

UsernameToken: From WebLogic Workshop to WSE

Web service platforms usually consume the WSDL contract for a target service to generate a proxy that can handle messaging necessary to invoke operations. In the WebLogic environment the Web service proxy is generated by creating a Web Service Control from the WSDL (a .jcx file). As a consumer of a target service that supports WS-Security, this proxy must also be able to serialize WS-Security elements that match the policy of the service it is invoking. Configuring a Web service proxy to use WS-Security is similar to configuring a service endpoint in Workshop. A policy configuration file is associated to the proxy through its ws-security-service property. After generating the policy file it can be modified by adding the <userNameToken> element shown in <wsSecurityOut> section of the sample’s outgoing policy file listed in Listing 2 below.

<?xml version="1.0" ?> 

<wsSecurityPolicy xsi:schemaLocation="WSSecurity-policy.xsd"
    
 xmlns="http://www.bea.com/2003/03/wsse/config"
    
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

<wsSecurityOut>
       
    <userNameToken>
           
     <userName>Partner
            
   <password type="TEXT">password
        
  </userNameToken>
       
     <signatureKey>
            
   <alias>iwserver</alias>
            
   <password>iwserver</password>
       
     </signatureKey>

</wsSecurityOut>
    
 <keyStore>
        
  <keyStoreLocation>teststore.jks</keyStoreLocation>
        
  <keyStorePassword>teststore</keyStorePassword>
    
 </keyStore>

</wsSecurityPolicy>

Listing 2 – Security policy configuration for the .NET service proxy sending messages from WebLogic to .NET.

The first thing you’ll notice is that the UsernameToken credentials are hard coded into the configuration file. Furthermore the password value is not encrypted. Of course, if this were an interactive client application the user’s credentials would likely be collected when they log in, and be dynamically attached to the proxy. In the case of a Web service invoking another service it is possible that a single credential is used to identify the calling partner, in which case configuration could be acceptable so long as the credentials are encrypted in the policy file. Encrypting policy file contents is quite easy to do and described clearly in the WebLogic Workshop documentation.

In either case, WebLogic serializes the UsernameToken in the outgoing message as follows:

<wsse:UsernameToken xmlns:wsu="http://docs.oasis-
       open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
    wsu:Id="Id-HfkQGtbqa4NRnIihuGpUDmTx">
    
  <wsse:Username>Partner</wsse:Username> 
  
  <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-
  200401-wss-username-token-profile-
  1.0#PasswordText">password</wsse:Password> 

</wsse:UsernameToken>

Notice that the Nonce and Created timestamp are missing, something we’ll have to attend to when the token is processed by WSE at the target service.

To authenticate the serialized UsernameToken at the target .NET Web service the first step is enabling WSE support as discussed for the client application in the previous section. The WSE wizard provides an interface for configuring a SecurityTokenManager to handle authentication of tokens attached to incoming messages. In the case of the UsernameToken, the incoming message will be contained within the OASIS-compliant <wsse:UsernameToken> element, and the WSE configuration should indicate which type will process this type of token.

The default UsernameTokenManager provided by the WSE runtime will process the header and authenticate against the configured Windows credential store. For Internet applications that use custom credential stores such as a SQL Server database, a derivation of this type must override the authentication step. WSE will deserialize the UsernameToken attached to an incoming message and pass it to the AuthenticateToken method of the UsernameTokenManager type.

To create a custom token manager, create a class that derives from UsernameTokenManager, and override the AuthenticateToken virtual method. This method must validate the username and return the user’s password to WSE for comparison against the token provided in the serialized message as shown here:

using Microsoft.Web.Services2.Security.Tokens;

protected override string AuthenticateToken(UsernameToken token)
{ 
   return Membership.Provider.GetPassword(token.Username);
}

To configure this token manager with WSE the wizard will generate the following section in the web.config for the service:

<securityTokenManager type="ImagingServices.MyUsernameTokenManager,
ImagingServices" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-
200401-wss-wssecurity-secext-1.0.xsd" qname="wsse:UsernameToken" />

Notice that the namespace and qname for the entry match the OASIS specification for the <wsse:UsernameToken> element. This indicates that all OASIS-compliant UsernameToken elements arriving at the service endpoint will be processed by this configured token manager.

Here’s where things get interesting. Recall that the BEA token does not include a Nonce or Created timestamp. This causes the default implementation of the base class UsernameTokenManager to reject the message with a SOAP fault indicating that an invalid security token was provided. That’s because the WSE runtime invokes the token manager’s DetectReplay method before authenticating the user, which requires the presence of Nonce and Created elements to prevent token replay. The base class UsernameTokenManager implementation caches a list of Nonce values with an expiry time, and verifies that a token is not replayed with the same Nonce within that period. If the service owner is willing to overlook this default replay check, and resort to other methods of Denial of Service (DoS) prevention at the hardware or outer message level, this issue can be overcome by suppressing the call to DetectReplay.

One way to do this is by modifying the SecurityTokenManager configuration setting to disable replay detection in the web.config:

<securityTokenManager type="ImagingServices.MyUsernameTokenManager,
ImagingServices" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-
200401-wss-wssecurity-secext-1.0.xsd" qname="wsse:UsernameToken">
 
 <replayDetection enabled="false" />
 
</securityTokenManager>

But this will disable replay detection for all inbound messages containing the <wsse:UsernameToken> element. Instead, by overriding the DetectReplay method in CustomUsernameTokenManager you can selectively prevent replay detection if the incoming token is missing a Nonce and Created timestamp value. With this small change, the UsernameToken is successfully passed from WebLogic and processed by WSE. The service operation is invoked if the password returned by AuthenticateToken matches the password sent in the message.

Summary: UsernameToken Interoperability from WebLogic Workshop to WSE

WebLogic does not send the Nonce or Created timestamp portion of the <wsse:UsernameToken> element by default, however these are not required elements according to the UsernameToken Profile 1.0 specification. They are, however, RECOMMENDED elements, and this explains why the WSE runtime is configured to expect it by default as the best practice. Fortunately, this default behavior is easy to override to allow the token to be accepted for authentication.

UsernameToken: DerivedKeyToken Signing

If the policy wizard had been used to configure the client to send a UsernameToken, by default this policy will also use the token to sign core message parts using a DerivedKeyToken. Likewise, when policy configuration is used on the service side, the UsernameToken received in incoming messages to the service is expected to be used to sign message parts with a DerivedKeyToken.

Though signatures are quite important for verifying the integrity of messages, the use of UsernameToken to apply signatures is not generally supported by other platforms. The technique used for deriving keys is not documented in the WS-Security specification, therefore subject to interpretation. In fact, in the interest of interoperability it is an enlightening experience to read the actual specifications where you will find statements like this one in the Web Services Security: UsernameToken Profile 1.0 specification:

“When a UsernameToken is referenced from a <ds:KeyInfo> element, it can be used to derive a key for a message authentication algorithm using the password. This profile considers specific mechanisms for key derivation to be out of scope. Implementations should agree on a key derivation algorithm in order to be interoperable.”

The currently non-ratified WS-SecureConversation specification does in fact define a mechanism for using derived keys for message signature, and this is the implementation that WSE is using for username token signatures through policy. However, interoperable messages should not use the UsernameToken for signing message parts. Instead, other symmetric or asymmetric keys should be applied as will be discussed in the next section.

Summary: UsernameToken Signing from WSE to WebLogic Workshop

WSE employs the WS-SecureConversation specification to generate DerivedKeyToken values from a UsernameToken, in order to sign message with the derived key. WebLogic does not support signatures with derived key tokens.

Thoughts on WS-SecureConversation and WS-Trust

WS-SecureConversation and WS-Trust are among the next generation of security specifications that will soon become ratified. In many respects their token issuance and secure conversation mechanisms are superior to the existing OASIS WS-Security options for authentication and secure communication because they incorporate the concept of dynamic key generation for authentication, signing and encryption and reduce some of the key management issues that exist today. WSE includes an early look at these protocols which helps early adopters to provide useful feedback, but interoperability on that level will not be reliable until the specifications are actually approved.

X.509 Authentication and Message Integrity

Though passing UsernameToken information is quite important for providing an audit trail of the application user invoking a service, X.509 certificates can be additionally useful to identify the organization or system sending the message, and ensure the message was not tampered with en route by signing message parts with the certificate’s private key. An X.509 certificate makes it possible to identify the message origin in absolute terms since the owner of the private key is the only party that can sign messages with that key. Passwords are subject to dictionary attacks, not to mention they have been known to be written down on sticky notes attached to the user’s computer monitor! A properly secured private key installed into a certificate store that is accessible only behind the firewall of the calling system, is much less at risk and can’t be spoofed.

When a message is signed with a private key, the related public key is sent with the message so that the receiver can authenticate the message is sent by a trusted party, verify that signed message parts were signed with the matching private key, and confirm that signed message parts were not tampered with during transport.

Combining the use of X.509 tokens with UsernameToken makes it possible then to identify the organization or system, and the actual user that logged in to the application triggering the message. Even in cases where the logged in user does not have credentials with the target service, an audit trail can be maintained at a more granular usage level if the user name is included in the message.

X.509 Signatures: From WSE to WebLogic Workshop

Configuring WSE to sign messages with an X.509 certificate can be done through the policy wizard or manually by writing code to create signatures and subsequently attach them to the proxy. From an interoperability perspective the end result is the same, so I’ll focus on the use of security policy in this example. A short walk through the WSE policy wizard allows you to specify that X.509 Certificate will be the type of token used to sign outgoing messages, and then select the X.509 certificate to use from the Windows certificate store. By default this generates a security policy that tells the WSE runtime to sign core WS-Addressing headers, the WS-Security Timestamp header, and the body of the message. This policy file currently follows the WS-SecurityPolicy specification although it is only used internally to configure the runtime behavior. The runtime uses this policy to find the signing certificate and apply the signature to the appropriate message parts.

In the policy file generated for the client application in the sample code, the <wssp:Integrity> section indicates X.509 as the security token type to use for signing. The policy contains enough information for the runtime to find the certificate, and to select the correct message parts to sign. Separate from the signing policy there is also a <wsp:MessagePredicate> section indicating which message parts should be present in all outgoing messages:

<wsp:MessagePredicate wsp:Usage="wsp:Required"
Dialect="http://schemas.xmlsoap.org/2002/12/wsse#part">wsp:Body()
wsp:Header(wsa:To) wsp:Header(wsa:Action) wsp:Header(wsa:MessageID)
wse:Timestamp()</wsp:MessagePredicate>

Policy verification verifies all message parts are present, then proceeds to sign those parts indicated by the signing policy. The application configuration file (app.config in this sample) includes a setting for the certificate store to be used to retrieve certificates specified by policy. In this example, the CurrentUser store is expected to contain all signing and encrypting certificates specified by policy. No additional code to retrieve certificates is necessary at this point, so let’s move to the WebLogic configuration required to receive signed messages.

A WebLogic service can require an X.509 signature be applied to incoming messages by configuring its security policy to include the <signatureRequired> section in the <wsSecurityIn> section shown in Listing 1 above. In addition to requiring signatures, notice that a Java key store is also specified. This is the key store where the public key portion of the certificate should be found for authentication.

This configuration assumes the use of X.509 certificates for signing, and expects only the body of the message to be signed since WebLogic doesn’t currently require or process WS-Addressing headers or the security Timestamp header (WSE supplies these by default). Superfluous, signed message parts are simply ignored by WebLogic, therefore the message is still processed according to plan.

WebLogic will require the body to be signed and validate the message signature. However, the runtime does not actually authenticate the signature against the key store. To achieve authentication additional code must be written on the WebLogic side.

Summary: X.509 Signature from WSE to WebLogic Workshop

Signing messages from WSE to WebLogic is interoperable although their runtime implementations differ significantly. WSE by default supplies WS-Addressing headers and a security Timestamp header. WSE security policy will by default sign those headers along with the message body. WebLogic ignores the presence of WS-Addressing and security Timestamp headers in its current implementation, but will validate the signature of the message body if it is signed. For the signature to be useful for authentication purposes, additional code must be written on the WebLogic side to process the signing token. This is outside of the scope of the WS-Security specification.

Other binary security tokens can be used to sign messages, for example derived keys based on the UsernameToken, Kerberos tokens, other binary security tokens, and any XML token including SAML tokens. WSE provides built-in support for UsernameToken, Kerberos and X.509 through the security policy wizard and is extensible to support additional token types either by hand-modifying policy or by writing code to manually attach tokens to the outgoing message. The current release of WebLogic currently only supports X.509 tokens for signing messages.

X.509 Signatures: From WebLogic Workshop to WSE

Now let’s visit the process of signing messages from WebLogic to .NET. Once again the Web service proxy and its security policy file must be modified to influence outgoing messages to the .NET Web service. Referring back to the policy file shown in Listing 2, the <signatureKey> element of the <wsSecurityOut> section instructs the WebLogic runtime to sign the body of the message with an X.509 certificate to be found in the key store: teststore.jks.

The certificate alias is iwserver, and the password to access it, the same. The WebLogic runtime will use this configuration setting to add a BinarySecurityToken to the <wsse:Security> header, representing the public key portion of the certificate, and subsequently use the private key to sign the body of the message. Once again, WS-Addressing headers and a security Timestamp header are not serialized in the outgoing message from WebLogic.

To require inbound messages to be signed at the .NET target service, the WSE security policy wizard can be used to configure a server side policy that not only requires specific message parts to be signed, but also includes a list of trusted public keys for authentication. By default, this policy will require that messages include WS-Addressing headers, a security Timestamp header, and of course a message body. The <wssp:Integrity> setting will also require these message parts be signed.

Since we already know that WebLogic does not send addressing and timestamp headers, nor sign them, we know that the message will fail policy verification by the WSE runtime. So, the security policy must be hand-edited to reduce the requirements. This can be done by manually removing all but wsp:Body() from both the <wsp:MessagePredicate> and the <wssp:Integrity> section’s <wssp:MessageParts> list. Once missing elements of the incoming messages are no longer required by policy, the message will pass verification by the WSE runtime. After the signed message body passes verification, the WSE runtime will also authenticate the source of the message by looking up the public key in the configured certificate store.

Summary: X.509 Signature from WebLogic Workshop to WSE

Signing the message body from WebLogic to WSE is interoperable. The distinction between the platforms really lies in the default behaviors such as: WSE by default requires additional headers that are not required by the specification today; WSE also provides an authentication step against the signature, although this also is not a requirement of the specification.

X.509 Encryption and Message Confidentiality

In this final section I’ll discuss how messages are encrypted with X.509 certificates to provide message level encryption regardless of the transport protocol. Any message part can be encrypted but typically the body of the message is the primary focus. Sensitive headers, such as security tokens and timestamps also make great candidates for encryption.

When a message part is encrypted, an encrypted version of the message part is put in its place in the context of the message. Information about the encryption key and the algorithm used to encrypt are sent along with the encrypted message to provide key material to the receiver. The correct procedure for attaching key material and encrypted data to a SOAP message are collectively defined by the WSS: SOAP Message Security, X.509 Certificate Profile, XML Encryption and XML Signature specifications. As you might imagine, given the size of some of these specifications the number of approaches toward forming encrypted messages, referencing tokens, supplying key material and so forth, will make your head spin.

When X.509 tokens are used to encrypt messages, there are two exchanges to consider. The message sender will use the public key of the receiver to encrypt messages that can only be decrypted by that receiver’s protected private key. The message receiver may encrypt message responses to the sender by using the public key associated with the private key the sender used to sign the message. In other words, X.509 signatures can play a role in encrypting responses to signed requests.

X.509 Encryption: From WSE to WebLogic Workshop

WSE configuration steps for encrypting messages with X.509 certificates is similar to that discussed for signing messages with X.509 certificates. The policy wizard provides steps for selecting a public key from the configured Windows certificate store. This public key should match the private held and protected by the recipient of the message so that only that recipient can decipher the encrypted message parts sent.

By default, the WSE security policy generated will encrypt only the body of the message as indicated by the <wssp:MessageParts> section of the <wssp:Confidentiality> element. It is possible to manually edit this policy to include other message parts in the encryption process. For example, since the UsernameToken element is sending clear text passwords, it would be good to encrypt that token as well. By modifying the confidentiality section of the policy to include wse:UsernameToken() in the message parts list, the WSE runtime will properly encrypt it along with the body of the message:

<wssp:Confidentiality>

   …
 
   <wssp:MessageParts
Dialect="http://schemas.xmlsoap.org/2002/12/wsse#part">wsp:Body()
wse:UsernameToken()</wssp:MessageParts>

</wssp:Confidentiality>

In fact, according to the WS-SecurityPolicy specification, the MessageParts element should have required wsse:UsernameToken() however a typo in the WSE runtime requires this be wse:UsernameToken(). The point is that although the wizard configures certain default behaviors for encryption, the WSE runtime is capable of parsing additional policy settings not injected by the wizard.

These steps will generate a message that replaces both the UsernameToken and message body elements with EncryptedData elements.

To configure WebLogic to require encryption, the security policy file of the target service will be modified to include an <encryptionRequired> element within the <wsSecurityIn> section as shown in Listing 1. The <decryptionKey> element specifies the private key for the service, with a password to access it from the specified key store.

WebLogic doesn’t require the configuration setting to indicate which parts will be encrypted, so long as at least one message part is encrypted. In fact, it does not have to be the body of the message! If the outgoing security policy of the WSE client requests only the UsernameToken be encrypted, that will suffice. In this case, since both the body and UsernameToken are encrypted, WebLogic will properly decipher both message parts using the key material indicated in the message, and the user will successfully be authenticated, the body of the message parsed accordingly.

Summary: X.509 Encryption from WSE to WebLogic Workshop

Encrypting messages from WSE to WebLogic is interoperable. The WebLogic runtime will automatically decipher whatever parts are encrypted, so long as they are message parts that the WebLogic runtime recognizes.

X.509 Encryption: From WebLogic Workshop to WSE

Now I’ll once again return to the WebLogic environment to configure the proxy for sending encrypted messages. The security policy file thus far associated with the proxy is listed in Listing 2. In order to add encryption to the outgoing message the following <encryption> section should be added to the <wsSecurityOut> section of the policy:

<encryption>
 
      <encryptionKey>
    
         <alias>wseserver</alias>

      </encryptionKey> 

</encryption>

The <encryptionKey> setting indicates which public key from the key store to encrypt the body of the outgoing message. In this case, the public key name is wseserver, and the matching private key is held by the .NET service to decrypt messages.

The policy wizard can be used to configure the .NET service to require encryption. In this case, the default requirement of the policy for the message body to be encrypted. Still, encrypted messages from WebLogic can not be processed by the WSE runtime due to an interoperability issue.

With encryption policy enabled, the WSE runtime will throw a security fault as it attempts to decrypt the EncryptedData value. The error refers to the format of the EncryptedData using Element type, and incorrectly containing more than one XML element. Solving a problem like this can get ugly, because without understanding the way encrypted message parts are supposed to be serialized according to specification, how is it possible to determine where the error occurred and if it is something you have control over?

The EncryptedData element passed from WebLogic looks like this:

<SOAP-ENV:Body xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-
200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="Id-
gBlyI9_yecYJBlUU_uXGckGH"> 
 
 <xenc:EncryptedData xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"
Id="Id-pZpR5Z4Clx9m__86ivLULMkM"
Type="http://www.w3.org/2001/04/xmlenc#Element">

   <xenc:EncryptionMethod
Algorithm="http://www.w3.org/2001/04/xmlenc#aes128-cbc" />

  <xenc:CipherData>

     <xenc:CipherValue>…</xenc:CipherValue> 

  </xenc:CipherData>

 </xenc:EncryptedData> 

</SOAP-ENV:Body>

Notice that the Type attribute indicates the encrypted data was generated as #Element. This means that the encrypted data represents the encrypted contents of a child of the body element. In theory, a single root element exists within the body element, but in fact multiple children of the body is supported by the SOAP specification. As a result, the WS-SecurityPolicy specification which drives the WSE policy processor looks for EncryptedData to be based on the #Content type.

Consider this snapshot of the encrypted data element sent by WSE to WebLogic:

<soap:Body wsu:Id="Id-ea2877b2-5ad2-4d43-a715-07d66fb8a3e4"> 
 
 <xenc:EncryptedData Id="EncryptedContent-a0529d26-78bf-409d-91bc-
9891ea68b842" Type="http://www.w3.org/2001/04/xmlenc#Content"
xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
 
   <xenc:EncryptionMethod
Algorithm="http://www.w3.org/2001/04/xmlenc#aes128-cbc" />

   <xenc:CipherData> 

      <xenc:CipherValue>…</xenc:CipherValue> 

   </xenc:CipherData> 
 
 </xenc:EncryptedData> 

</soap:Body>

Though it is likely the yield from both EncryptedData elements would be equivalent if performed on the same originating message, the #Content type absolutely guarantees that the entire contents of the message body are encrypted.

So, what happens if we remove WS-SecurityPolicy from the equation and send the EncryptedData from WebLogic to WSE for processing? A new problem rears its head in this case. Although the message no longer fails policy verification, it now fails to retrieve the referenced security token from the EncryptedKey element.

The error message in fact describes the problem completely. Deep inside the plumbing of WSE, the EncryptedKey type is used to parse the key material passed with the message. This parsing process is looking for a way to reference the actual security token required to decrypt the message. In fact it is specifically looking for a key value, and WebLogic is providing a key name in its stead. Here’s where the water gets muddy once again: so many specifications; so many possibilities; and so many technically correct ways to achieve the same goal. Which specification should we follow?

The desired result was to encrypt the body of the message and provide key material. That is exactly what WebLogic did, where the key material was provided in an <xenc:EncryptedKey> element as follows:

<xenc:EncryptedKey xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"> 

   <xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-
1_5" /> 

   <dsig:KeyInfo xmlns:dsig="http://www.w3.org/2000/09/xmldsig#"> 

      <dsig:KeyName>CN=WSE2QuickStartClient</dsig:KeyName> 

   </dsig:KeyInfo> 

   <xenc:CipherData> 

      <xenc:CipherValue>…</xenc:CipherValue> 

   </xenc:CipherData> 

   <xenc:ReferenceList> 

      <xenc:DataReference URI="#Id-5CkREMYaZ3xdmZ7G2H2xasl_" /> 

   </xenc:ReferenceList> 

</xenc:EncryptedKey>

In order to decrypt the message body the recipient of the message must be able to find the key required to perform the decryption. KeyName is one legal way to identify the decryption key – in fact it is the RECOMMENDED way according to the XML Encryption specification. But according to the X.509 Certificate Profile, KeyInfo should contain a SecurityTokenReference that in turn can reference the key in one of several ways including KeyIdentifier and KeyName (where the former is preferred). For example, WSE sends the KeyInfo element in this way:

<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#"> 

   <wsse:SecurityTokenReference> 

      <wsse:KeyIdentifier ValueType="http://docs.oasis-
   open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-
   1.0#X509SubjectKeyIdentifier" EncodingType="http://docs.oasis-
   open.org/wss/2004/01/oasis-200401-wss-soap-message-security-
   1.0#Base64Binary">+pS7tYztAOJhscYSdiL1MGsXic8=</wsse:KeyIdentifier> 

   </wsse:SecurityTokenReference> 

</KeyInfo> 

So, although legal according to the XML Encryption specification, the way WebLogic serializes encryption violates the interoperability requirements of WS-Security today. Fortunately BEA does supply a workaround for this issue that can be requested directly through their developer support channels.

Summary: X.509 Encryption from WebLogic Workshop to WSE

Encrypting messages WebLogic to WSE is not currently interoperable due to each platform’s interpretations of the various specifications. According to the OASIS WSS: SOAP Message Security specification, WebLogic is not serializing EncryptedKey elements in a compliant manner. This issue extends also to encrypted responses from WebLogic to .NET clients.

WS-Security Interoperability and Beyond

Throughout this article I have focused on the current state of interoperability between WebLogic Workshop 8.1 and the .NET Framework with WSE. From this, you should be able to draw two conclusions:

  • The same early adoption interoperability pain exists today with emerging standards as existed when SOAP and WSDL were first supported by various vendor platforms
  • Achieving WS-Security interoperability today begins with vendor tools that simplify the process of generating complex WS-Security constructs for authentication, encryption and digital signatures; leads to comparing the underlying serialized messages when problems arise; and ends with verifying that XML against WS-Security specifications and their predecessors to better understand the problem

The state of SOAP and WSDL today has proven to us that we can achieve fantastic levels of interoperability as standards stabilize and vendors ship their compliant implementations of those standards that have been through several rounds of early adoption feedback. So, achieving interoperability is about more than just following a set of standards. It is about the adaptability of each vendor platform, and their respective ability to inject updates as standards evolve, and to provide extensibility and configuration hooks that will allow early adopters to overcome interoperability issues with greater control.

In the coming months as the next generation of platforms release for BEA and Microsoft respectively, we’ll see great improvements in interoperability with this basic set of WS-Security scenarios. However, that won’t be the end of our security needs since issues of message bloating, key management, and federated identity will demand the implementation of other soon to be implemented standards including WS-Trust and WS-SecureConversation with SAML. Interoperability between these emerging security standards will soon be the focus as WS-Security today stabilizes…so brace yourself.

Download the code sample for this article.

About the author

Michele Leroux Bustamante is a Chief Architect with IDesign, Microsoft Regional Director for San Diego, Microsoft MVP for Web Services and a BEA Technical Director. In addition, Michele is a member of the board of directors for the International Association of Software Architects (IASA). At IDesign Michele provides high-end architecture consulting services, training and mentoring. Her specialties include architecture design for robust, scalable and secure .NET architecture; localization; Web applications and services; and interoperability between .NET and Java platforms. Michele is a member of the INETA; a frequent conference presenter at major technology conferences such as Tech Ed, PDC, SD and Dev Connections; conference chair for SD’s Web Services track; and a regularly published author. Visit her blog for additional information.


This was first published in January 2008

Dig deeper on .NET Framework security best practices

0 comments

Oldest 

Forgot Password?

No problem! Submit your e-mail address below. We'll send you an email containing your password.

Your password has been sent to:

SearchCloudComputing

SearchSoftwareQuality

SearchSOA

TheServerSide

SearchCloudApplications

Close