CoverStory
LANGUAGES: C#
ASP.NET VERSIONS: 1.0 | 1.1
Security by Design
Build Secure Web Services with WS-Security
By Jeffrey Hasan
Many companies have not adopted the Web services technology because it lacks a security specification that can ensure the integrity of transmitted messages and data. The WS-Security specification is a joint effort by several vendors to address this important issue.
What do we actually mean when we talk about security ? In broad terms, we are talking about authentication and authorization:
- Authentication is the process of validating a user s identity based on credentials, or tokens. The token may be a username-password combination, or it may be based on an X.509 certificate. This certificate is a signed public key that has been issued by a certificate authority to vouch for the identity and integrity of a user.
- Authorization is the process of allowing access to selected resources based on a user s authenticated identity. For example, you can restrict access to a Web service s methods by specific users.
Together, authentication and authorization provide for a security model by allowing you to identify a user and then give them selective access to resources.
Currently, it is possible to secure SOAP communications over HTTP using the certificate-based Secure Sockets Layer (SSL) protocol. SSL provides encryption and digital signing of both SOAP messages and standard HTTP requests and responses. But SSL has two major limitations that make it unsuitable for securing Web services communications within a service-oriented application. First, SSL is designed for point-to-point communication. However, service-oriented Web services may exchange SOAP messages between two or more endpoints, and so they require a security solution that supports hops across multiple endpoints and multiple domain boundaries. Second, the SSL protocol is built on the HTTP protocol. Web services technology is transport-neutral, and supports message exchange across different protocols, including TCP and SMTP, in addition to HTTP. The SSL protocol is simply too limiting for Web services technology.
The WS-Security specification is designed to overcome these limitations and provide an extensible security implementation that will evolve as the Web services technology becomes more sophisticated.
The WS-Security Specification
The prime currency in Service Oriented Architecture (SOA) applications are SOAP messages, because they are the means by which requests are made and responses are received from Web service methods. The WS-Security specification provides a way for you to protect the integrity and confidentiality of messages and to implement authentication and authorization models in your Web services. The WS-Security specification enables you to implement the following protections in your Web service calls:
- Authentication. Security credentials, or tokens, may be exchanged between a client and a Web service to validate the identity of the caller. The tokens are added directly to the header of the SOAP message.
- Digital Signing. This is the process of signing a SOAP message with a signature that is based on a security token (such as an X.509 certificate). Digital signing creates a cryptographic signature attached to the message that uniquely identifies the sender. The receiver can check this signature to verify the identity of the sender and the integrity of the message. A SOAP exception is raised on the receiving end if anyone tampered with the contents of a SOAP message.
- Encryption. This is the process of hashing a SOAP message to ensure its confidentiality. There are many available encryption algorithms. In addition, you can encrypt a SOAP message based on an X.509 certificate.
The WS-Security specification is platform-independent and transport-neutral, as are all the other WS specifications. Security information is generated by the client and stored within the envelope of the SOAP request message. The Web service in turn will deserialize this information, verify its validity, and process the requested operation. In the event that the message security does not pass verification, the Web service will return a SOAP fault back to the client.
Web Services Enhancements (WSE) 2.0 provides the API for implementing WS-Security in .NET-based Web services and client applications. The API allows you to write code to format secured SOAP request messages in the client and process secured messages within a Web service.
Implement WS-Security Using WSE 2.0
The focus of this article is to show you how to write the code to implement WS-Security in Web services and their client applications. We will look at two examples:
1) Digitally sign a SOAP request message with an X.509 certificate.
2) Encrypt a SOAP request message with an X.509 certificate.
Note that WSE 2.0 must be properly installed and configured for the sample projects to work.
The WSE 2.0 sample projects ship with test certificates and keys, which we will use here because they are convenient. Here are the installation steps for the sample certificates that ship with WSE 2.0:
1) Open the MMC console and add the Certificates snap-in for both Current User and Local Machine.
2) Open the Personal folder of the Current User certificate store and import the sample personal information exchange file entitled Client Private.pfx. This is the private key that the Web service client will use to encrypt requests to the Web service.
3) Open the Personal folder of the Current User certificate store and import the sample test certificate entitled Server Public.cer. This is the public key that the client uses to digitally sign requests for the Web service.
4) Open the Personal folder of the Local Machine certificate store and import the sample test certificate entitled Server Public.cer. This is the public key that the Web service uses to decrypt the client s request.
After the certificates are installed, you re ready to create Web service clients and services that exchange digitally signed and encrypted SOAP requests. (Note that SOAP responses may also be encrypted; however, that topic is beyond the scope of this article.)
How to Digitally Sign SOAP Messages
A digital signature is essentially a cryptographic hash that is added to a SOAP message, and is based on a security token. Digital signatures may be generated using several token types, including an X.509 certificate. The certificate is used to generate a pair of related keys, called the private and public keys. The private key is known only to the client and is used for the following purposes:
- To digitally sign an outgoing SOAP request message.
- To decrypt an incoming SOAP response message.
The public key is made available to authorized services, which use it for the following purposes:
- To verify an incoming signed SOAP request message.
- To encrypt an outgoing SOAP response message.
The digital signing process with X.509 certificates works as follows:
1) The client obtains an X.509 certificate and generates a private-public key pair. The service receives a copy of the public key.
2) The client applies a hash algorithm to the message, which creates a so-called message digest.
3) The client then encrypts the message digest with their private key, which creates the digital signature.
4) The client attaches the digital signature to the SOAP request message. (Programmatically, WSE performs steps 3 and 4 together.)
5) The client sends the SOAP request message out to the service.
6) The service receives the SOAP message and checks the security token type.
7) After the service determines that an X.509 certificate was used, it decrypts the message signature using the public key. This process allows the service to retrieve the original message hash. If the decryption process fails, then the service assumes that the client is not the original sender of the message, or the message has been tampered with, and a SOAP exception is raised.
8) The service then generates its own message digest using the same algorithm that the client used.
9) The service compares its generated message digest against the one that has been obtained from the client. If the two message digests match, then the signature has passed verification. If it does not, then the service assumes that the message has been tampered with and a SOAP exception is raised.
Digital signatures can have real consequences on message delivery if they are not applied correctly, or if the verification process fails, because either of these issues will prevent the service from processing the incoming SOAP request message. In addition, certificates will expire, so verification will fail if the certificate is not current. The X509SecurityToken and X509SecurityCertificate classes both provide a Boolean IsCurrent property that verifies whether a given certificate is still valid.
Implement a Web Service that Accepts Digitally Signed Requests
Now let s look at an example Web service and client that implement digital signatures. The full code listing is available for download (see end of article for details), so to preserve space I ll simply highlight parts of the code. Consider a Web service that provides stock ticker information. Figure 1 shows the required Web.config file settings for the Web service.
type="Microsoft.Web.Services2.Configuration. WebServicesConfiguration,
Microsoft.Web.Services2, Version=2.0.0.0, Culture=neutral,
PublicKeyToken= 31bf3856ad364e35"
/> "StockTrader.CustomUsernameTokenManager,
StockTraderSecure"
xmlns:wsse= "http://docs.oasis-open.org/wss/2004/01/ oasis-200401-wss-wssecurity-secext-1.0.xsd"
qname="wsse:UsernameToken"
/> allowRevocationUrlRetrieval="false"
verifyTrust="false" /> Figure 1:
Web.config settings for the secure Web service project. The The Web service must be modified to iterate through the
collection of signatures and tokens that are assigned to a SOAP request
message. It is in fact possible to add multiple tokens and signatures to a single
message, although the code listings shown here do not do this. The Web service
should process the signed SOAP message as follows: 1) Loop
through the collection of signatures attached to the SOAP message. 2) For
each signature in the collection, determine on which type of token it is based. 3) For
username tokens, implement a custom token manager to validate the token. Figure 2 shows you how to loop through the collection of
signatures and tokens attached to a SOAP request message. Note that this code
listing is implemented directly inside the RequestQuote Web method so that a
SOAP fault may be raised directly from the method should the user fail to be
authenticated or authorized to access the method. using System.Web; using System.Web.Services; using System.Web.Services.Protocols; using System.Web.Services.Description; using System.Xml.Serialization; using Microsoft.Web.Services2; using Microsoft.Web.Services2.Security; using Microsoft.Web.Services2.Security.Tokens; using System.Security.Permissions; using StockTraderTypes; [WebService()] public class StockTraderService : System.Web.Services.WebService,
IStockTrader { [WebMethod()] public override Quote
RequestQuote(string Symbol) { // Initialize the custom token manager, in case it's needed CustomUsernameTokenManager
objMgr = new
CustomUsernameTokenManager(); // Verify the signature on the Web service // request to this method bool SignatureIsValid =
false; SoapContext
requestContext = RequestSoapContext.Current; foreach (ISecurityElement
objElem in requestContext.Security.Elements) { if (objElem is
MessageSignature) { MessageSignature
clientSignature = (MessageSignature)objElem; if
(clientSignature.SigningToken is X509SecurityToken) { SignatureIsValid =
true; } else if
(clientSignature.SigningToken is UsernameToken) { SignatureIsValid =
true; objMgr.VerifyToken(
clientSignature.SigningToken ); } } } // Proceed with request if signature is valid Quote q = new Quote(); if (SignatureIsValid) {} // Implementation code for RequestQuote() } return q; } Figure 2: Loop
through the collection of signatures and tokens attached to a SOAP request
message. Now let s write a Web service client that generates signed
SOAP request messages. Figure 3 shows the portion of the code that retrieves an
X.509 certificate and applies it to a SOAP request message as a digital
signature. using Microsoft.Web.Services2.Security; using Microsoft.Web.Services2.Security.Tokens; using Microsoft.Web.Services2.Security.X509; X509CertificateStore store; X509SecurityToken token; // Open the CurrentUser Certificate Store store = X509CertificateStore.CurrentUserStore( X509CertificateStore.MyStore
); // Retrieve the X509 certificate from the // CurrentUserStore certificate store string ClientBase64KeyId =
"gBfo0147lM6cKnTbbMSuMVvmFY4="; X509CertificateCollection certs = store.FindCertificateByKeyIdentifier(
Convert.FromBase64String(
ClientBase64KeyId ) ); if (certs.Count > 0) { // Get the first
certificate in the collection token = new
X509SecurityToken( ((X509Certificate)
certs[0]) ); } // Add the token and digital signature to the // SOAP request message serviceProxy.RequestSoapContext.Security.Tokens.Add( token ); serviceProxy.RequestSoapContext.Security.Elements.Add( new MessageSignature(
token ) ); // Send the Web service request via the proxy class // (Code listing not shown here.) Figure 3:
Digitally sign a Web service request using an X.509 certificate. Security tokens and digital signing allow you to identify
a service requestor, and to determine whether a request message has been
tampered with, but they do nothing to protect the contents of a SOAP message
from network sniffers. Encryption technology enables you to generate a
cryptographic hash of the SOAP message for transport, and to decrypt the
message contents at the receiving end. There are two kinds of encryption: Interestingly enough, when a SOAP message is encrypted,
only the body of the message gets hashed. If your SOAP message includes custom
SOAP header values, then you must encrypt them separately. In the following
section we ll review how to encrypt the body of a SOAP message using asymmetric
encryption. To get started, you can implement asymmetric encryption as
outlined in the following steps: 1) Generate
a private-public key pair based on a digital certificate. 2) Install
the private key in the client s local certificate store. 3) Install
the public key in the server s local certificate store. 4) Implement
code in the Web service client to generate an encrypted SOAP request message. The client code for generating encrypted SOAP request
messages is very similar to the code for digitally signing messages. The client
retrieves the applicable X.509 certificate-based private key from its personal
certificate store and then uses this key to generate a hash of the SOAP
message. Figure 4 shows you the required code. public void EncryptRequestUsingX509Certificate() { // Retrieve the X509 certificate from the // CurrentUserStore certificate store X509SecurityToken token; string ClientBase64KeyId =
"gBfo0147lM6cKnTbbMSuMVvmFY4="; // Open the CurrentUser Certificate Store X509CertificateStore store; store = X509CertificateStore.CurrentUserStore( X509CertificateStore.MyStore
); // Find the certificate based on the server's // base64 key identifier X509CertificateCollection certs = store.FindCertificateByKeyIdentifier(
Convert.FromBase64String(
ClientBase64KeyId ) ); if (certs.Count > 0) { // Get the first
certificate in the collection token = new
X509SecurityToken( ((X509Certificate)
certs[0]) ); } if (token == null) throw new ApplicationException( "Unable to obtain
security key."); StockTraderServiceWse serviceProxy = new
StockTraderServiceWse(); // Add the certificate key to encrypt the request serviceProxy.RequestSoapContext.Security.Elements.Add( new EncryptedData( token
) ); // Call the Web service RequestQuote() method Console.WriteLine("Calling {0}", serviceProxy.Url); WSStockTraderClient.StockTraderEncrypted.Quote strQuote = serviceProxy.RequestQuote("MSFT"); // Results Console.WriteLine("Web Service call successful.
Result:"); Console.WriteLine( " " ); Console.WriteLine( "Symbol: " + strQuote.Symbol ); Console.WriteLine( "Price: " + strQuote.Last ); Console.WriteLine( "Change: " + strQuote.PercentChange +
"%"); } Figure 4: Encrypt
a SOAP request message using an X.509 certificate. Certificate-based keys must be retrieved from the
certificate store using their base64 key identifier. WSE 2.0 ships with a
useful utility called the WSE X.509 Certificate Tool, which allows you to
browse certificates for the Current User and Local Machine certificate stores,
and to retrieve base64 key identifier information. Figure 5 shows the tool
displaying the client private key certificate that is used in the example shown
in Figure 4. For asymmetric encryption, the Web service does not
require additional code for processing encrypted SOAP request messages. You
must simply ensure that the public key for decryption is installed in the Local
Machine certificate store on the same server where the Web service is
installed. If the public key is not installed correctly, the client application
will receive a SOAP fault indicating a problem on the receiving end. But if the
certificates are installed correctly, the WSE 2.0 handlers will automatically
decrypt the incoming request for you. From a procedural standpoint you may still want to put code
in place in the Web method to verify that the request message is in fact
encrypted. Figure 6 shows the policy-oriented code listing for verifying that
an incoming request message is encrypted. bool EncryptionIsValid = false; SoapContext requestContext = RequestSoapContext.Current; foreach (ISecurityElement objElem in requestContext.Security.Elements) { if (objElem is
EncryptedData) { // Encrypted Data
exists in the Element collections. // Now check if it is
the body that was encrypted. EncryptedData encData
= objElem as EncryptedData; if
(encData.TargetElement.LocalName == "Body") { EncryptionIsValid =
true; // Process the Web
service request (code not shown) } } } Figure 6: Code to
verify that an incoming request message is encrypted. This article has demonstrated how to use WSE 2.0 and the
WS-Security specification to implement several types of security measures in
SOAP messages, including: The
sample code referenced in this article is available for download. Jeffrey Hasan is president
of Bluestone Partners, Inc., an IT solutions company based in Orange County, CA
(http://www.bluestonepartners.com).
Jeff is an experienced enterprise architect and .NET developer, and is the co-author
of several books and articles on .NET technology, including the just-released Expert Service Oriented Architecture in C#: Using the
Web Services Enhancements 2.0 (Apress, 2004). Contact Jeff at mailto:[email protected]. Modify the Web Service to Process Signed SOAP Messages
Create the Web Service Client
Encrypt SOAP Messages with an X.509 Certificate
Implement the Web Service Client
Figure 5: The WSE X.509 Certificate
Tool. Modify the Web Service to Process Encrypted SOAP Messages
Conclusion