This section demonstrates how to incorporate security into your web service. We will do so in two ways: system security and application security. System-level security allows for restricting access to the web services from unauthorized clients. It is done in a declarative fashion, whereas application-level security is more flexible. With system-level security, you will most likely have the list of authorized clients' IP addresses that you will let access your web service through the use of some configuration-management tools. With application-level security, you will incorporate the authentication into your web service, thus providing a more flexible configuration.[18]
[18] As always, consult your security expert on this decision.
Because web services communication is done through HTTP, you can apply system-level security on web services just as you do for other web pages or resources on your web site.
There are a number of different ways you can secure your web services. For a business-to-business (B2B) solution, you can use the IIS Administration Tool to restrict or grant permission to a set of IP addresses, using the Internet Protocol Security (IPSec) to make sure that the IP address in the TCP/IP header is authenticated. When you rely only on the client to provide the IP in the TCP/IP header, hackers can still impersonate other host IPs when accessing your web services. IPSec authenticates the host addresses using the Kerberos authentication protocol. You can also use a firewall to restrict access to your web services for your partner companies. For a business-to-consumer (B2C) scenario, you can take advantage of the authentication features of the HTTP protocol.
To show you how to use the authentication feature of the HTTP protocol to secure your web services, let's revisit the example web service we have in this chapter, PubsWS. All we have to do to secure PubsWS web service is go to the IIS Admin Tool and choose to edit the File Security properties for the PubsWS.asmx. Instead of keeping the default setting, which leaves this file accessible to all anonymous users, we change this setting to "Basic Authentication" only, which means unchecking "Anonymous Access" and checking only "Basic Authentication" in the Authenticated Access frame. After this change, only users that pass the authentication can make use of the web service.
For real-life situations, of course, we are not going to use just the Basic Authentication method, because it sends the username and password in clear text through the HTTP channel. We would choose other methods, such as Secure Sockets Layer (SSL) underneath Basic Authentication, so that the data passed back and forth is secure. Available methods include:
Sends the username and password to the Web Server in clear text. IIS authenticates the login against the database of users for the domain.
Similar to Basic Authentication, except that the username and password are sent with SSL encryption.
Uses a hashing technique, as opposed to SSL encryption, to send client credentials securely to the server.
Good for intranet scenarios only. Uses the login information of the client for authentication.
Requires each of the clients to obtain a certificate that is mapped to a user account. The use of client-side digital certificates is not widespread at this time.
A less systematic way of securing your web services involves taking security into your own hands. You can program your web services so that all of their methods require an access token, which can be obtained from the web service after sending in the client's username and password. The client credentials can be sent to the server through SSL, which eliminates the risk of sending clear-text passwords across the wire. Through this SSL channel, the server returns an access token to the caller, who can use it to invoke all other web service methods. Of course, all of the other web methods that you publish must have one parameter as the token. A simple pseudocode example of a bank account web service can be the following:
web service Bank Account Web Methods: Login(user id, password) returns access token or nothing Deposit(access token, account number, amount, balance) returns boolean Withdraw(access token, account number, amount, balance) returns boolean
The only method that should be on SSL is the Login method. Once the token is obtained, it can be used for other web methods. Of course, you should be able to make sure that subsequent calls using this token are coming from the same IP as the Login( ) call. You can also incorporate an expiration timestamp on this access token to ensure that the token only exists in a certain time frame until a renewal of the access token is needed.
You can also use public/private keys (asymmetric) encryption for better key- management. The following scenario might suit your needs.
The client gets the server's public key and uses it to encrypt the requesting data (possibly including the client's private symmetric encryption key) before calling the web service. This ensures that the requesting data is encrypted and only the server can decrypt it. The server decrypts the data using the private key, figures out what the request is and uses the client's private key to encrypt the response before sending it back to the client. This time, the response data is encrypted. The client then decrypts the response package with its private symmetric key to view clear data. Since asymmetric cryptography operations are always much slower than symmetric, it's probably best if you only use asymmetric cryptography for key distribution. Once the key is communicated, you can use the symmetric operation for better performance. Rolling your own security is always harder than using a standard security solution. There are numerous areas you will have to manage yourself such as identity authentication, message authentication, and so on. Be forewarned if you choose this route.
The Microsoft .NET Cryptographic Services can be very useful if you choose to apply application security for your web services. DES, RC2, RC4, TripleDES, and RSA cryptography algorithms are supported along with hashing methods such as SHA and MD5. These implementations in the .NET library enable developers to avoid low-level grunt work and focus on the application logic.