An Extensive Examination of Web Services: Part 9By Scott Mitchell
In Part 8 of this article series we discussed the Web Service Enhancements (WSE), a set of standards created by leaders in the Web services industry in order to accomplish common, everyday business activities. The WSE standards outline techniques for authentication, encryption, sending large binary attachments, establishing trust among Web services, routing messages, and so on. Back in May of this year, at TechEd 2004, Microsoft officially released their 2.0 version of the WSE Toolkit, a free .NET library with Visual Studio .NET integration that can be used to quickly create Web services that utilize the WSE standards.
Part 8 touched upon the important concepts of WSE, and looked at some of the standards from 30,000 feet. In this article we'll actually roll up our sleeves and start playing with Microsoft's WSE Toolkit. We'll look at how to download and install the WSE Toolkit, as well as how to implement UsernameToken authentication. (UsernameToken authentication is a standardized technique for a Web service client to send along authentication information in the Web service request message, and is useful if you have Web services whose methods are available only to certain, authenticated individuals.)
To learn more about UsernameToken authentication, be sure to check out the code available at the end of this article.
Downloading and Installing the WSE 2.0 Toolkit
The WSE Toolkit is a free download (an MSI file) that can be snagged from here. (One note: According to the download page, WSE 2.0 requires the .NET Framework 1.1. I've not tried installing it on a box with just the 1.0 Framework installed, so I don't know whether or not it will work. If you are using Visual Studio .NET 2003, you have the .NET Framework 1.1 installed on your computer.)
Once the file has been downloaded, double-click the MSI file to begin the installation process. During the installation you'll be asked to choose a "Setup Type". If you use Visual Studio .NET, be sure to choose the "Visual Studio Developer" option (see the screenshot to the right). By selecting this option, a GUI WSE Toolkit interface will be accessible through Visual Studio .NET.
At this point you should have completed installation of the WSE Toolkit. The remainder of this article will examine how to create a Web service and a Web service client that utilize the WSE Toolkit in order to implement UsernameToken authentication.
UsernameToken Authentication from 30,000 Feet
Authentication is the process of identifying a user. Since Web services are implemented as files on a Web server, and since most Web servers are configured to allow anonymous access, anyone who knows about your Web service can invoke it. (Of course, the Web server may be behind a corporate firewall, thereby severely limiting those who can access it; or the Web server could be configured to only allow certain IP addresses to access the Web service file, or could be configured to not allow anonymous access.) If you are creating a Web service that can only be accessed by certain individuals, or a Web service whose functionality differs based on the user accessing the service, it's important that you be able to authenticate those individuals utilizing your service. The WSE standards provide a variety of authentication standards, the simplest and most straightforward one being UsernameToken authentication.
UsernameToken authentication works as follows: the client requesting the Web service must send along a token that identifies them. With UsernameToken authentication this token includes two bits of information: a username, and a password. This token is sent along with the Web service request, thereby identifying the requestor. The Web service, then, can examine this token and determine if the user's username and password are valid. If they are not, a SOAP Fault is sent back to the user, indicating that their request has failed. If the user is authenticated, the call proceeds.
Specifically, the UsernameToken is sent as a SOAP Header. (We talked about SOAP Headers in Part 6 of this article series.) The actual contents of the UsernameToken SOAP Header depend upon the username, password, and how the password information is sent. In general, though, the SOAP request message, when using UsernameToken authentication, will look roughly like this:
The UsernameToken authentication standard allows for the client to send the password in one of three flavors:
- No password (username only) - this option is only useful if the user has already been authenticated, or if you trust that the user is who he says he is. Essentially, just the username is sent to the Web service. This technique might be used in an intranet setting, where the user invoking the Web service has already been authenticated in order to logon to the intranet.
- Password in plain-text - this sends the user's password in the SOAP Header in plain-text. Not a secure option when making a Web service call over an insecure channel.
- A hashed digest of the password - this option is the best for sending password information over the Internet. Rather than sending the actual password, a one-way hash of the password is sent instead. (For more information on hashing passwords and the cryptography behind it, be sure to read Using MD5 to Encrypt Passwords in a Database.)
The whole purpose of the WSE Toolkit is to ease the time and understanding needed in order to implement the WSE standards.
Essentially, the WSE Toolkit provides an API that you can use to implement these standards, keeping you, the developer,
at arms length from the actual low-level XML markup required. For example, for the client to send a UsernameToken to
a Web service, the client simply creates a
UsernameToken class instance, sets its
Password properties, specifies what password option to use, and attaches the
to the proxy class's
Tokens collection. With just these few lines of code, the appropriate SOAP Header is
automatically added to the outgoing SOAP message from the client. (Underneath the covers, SOAP Extensions are used to
automatically squirt in the UsernameToken SOAP Header into the outgoing message. SOAP Extensions were discussed in
Part 7 of this article series.) Similarly, using UsernameToken authentication
in a Web service is just as simple.
Implementing the Web Service
In order to implement UsernameToken authentication we'll need to create both a Web service that expects a UsernameToken sent along via the SOAP Headers, and a client that sends such a token. Let's start with creating the Web service. To begin, create a Web service application with Visual Studio .NET. Once the project has been created you'll need to indicate that it should use the WSE 2.0 Toolkit. To accomplish this, right-click on the Project name in the Solution Explorer and choose the WSE 2.0 Settings... option from the menu (see the screenshot below). (If you do not see the WSE 2.0 Settings from Visual Studio .NET, make sure you have closed all instances of Visual Studio .NET since installing the WSE Toolkit; also make sure that when installing the WSE Toolkit you chose the Visual Studio Developer Setup Type option.)
Once you have selected the WSE 2.0 Settings... option, a dialog box will appear. This dialog box has a number of tabs across the top that are useful for implementing various WSE standards in your Web service. However, before you can utilize any WSE standard in your Web service, you must first check the two checkboxes on the General tab, as shown below.
At this point, by just checking a couple of checkboxes, the Web service can authenticate users against the Windows
Users store on the Web server. That is, a client could send the username and password of a Windows User (such as
bobsPassword). When the Web service receives this token in the SOAP request message,
it will attempt to authenticate the user against the Windows User store. If the username and/or password are not
correct, a SOAP Fault will be returned. If the user is valid, they will be able to access the method requested.
(One note: in order to use the default UsernameToken authentication the password must be sent as plain-text.)
From the Web service's methods you can programmatically determine the identity of the authenticated user. I find it
helpful to add the following method to the Web service in order to access the UsernameToken instance of the requestor
with just one line of code (note: when using the
UserTokenName class add a
statements to the namespaces
With this method in the Web service class, you can access the UsernameToken programmatically in a Web service method
by simply calling
GetUsernameToken(). For example, imagine you had a method called
that returned a string with some information about the Web server. Perhaps you'd want to return more detailed information
if the requestor is
CORP\frank. You could write this method like so:
By default, the WSE Toolkit's UsernameToken authentication piece authenticates users against the Windows User store.
However, you may want to validate users against a custom user store, such as a database. To accomplish this, you can
create your own class that derives from the WSE Toolkit's
UsernameTokenManager and overrides the
AuthenticateToken(token) method. The purpose of this
is to return the password for the user making the request. (The requestor's username can be accessed via the passed-in
Creating this class and overriding the method is fairly straightforward. To add this functionality to your Web service, simply add a new class to your Web service project with the following code:
Once you have created this class you need to tell the WSE Toolkit that it should use this custom class for UsernameToken authentication, rather than the default approach of authenticating against the Windows User store. To accomplish this, open up the WSE 2.0 Settings... and select the Security tab. In the middle of this tab you'll find a Security Tokens Managers section; click the Add button. This will display the dialog box shown below, which prompts you for three fields:
- Type - Enter the fully qualified type of the custom class you created. The fully qualified type is
denoted by Namespace.Classname, Assembly. Typically the assembly and namespace are one in the
same, so the Type field will look something like: MyWebServiceProjectNamespace.AuthenticationManager, MyWebServiceProjectNamespace (here
I'm assuming you named this custom class
AuthenticationManager, as I did in the code snippet above).
- Namespace - Here you will need to enter the following hard-coded string:
- QName - Here you will need to enter the following hard-coded string:
Make certain that you enter the correct values here, as entering incorrect values into these three textboxes will cause many headaches as you try to ascertain why UsernameToken authentication is not working in your Web service. Trust me, I speak from many hours of personal experience!
At this point we have completed our Web service. We're now ready to build a Web service client that will send along a UsernameToken along with the SOAP request.
Implementing the Client
To build a client that interacts with a Web service that uses the WSE Toolkit, you'll need to do the following things in the following order:
- Create a new application - either an ASP.NET Web application or a WinForms application will suffice.
- Configure the client to use the WSE Toolkit - to accomplish this right-click on the Project name in the Solution Explorer and choose the WSE 2.0 Settings option. Realize that for WinForms applications, you will only be able to check the first checkbox in the General tab - this is OK. For Web applications, be sure to check both checkboxes.
- Create a Web Reference to the Web Service - right-click on the References folder and opt to add a new Web Reference.
When adding a Web Reference, two proxy classes will be generated. One will have the name of the Web service
and the second will have the name of the Web service prefixed with
Wse. Anytime the client needs to
make a call that involves the WSE standards (such as UsernameToken authentication), it will need to use the
proxy class that ends with
To call the Web service passing a UsernameToken, use the following code:
That's all there is to it!
In this article we saw how to implement the WSE UsernameToken authentication standard. UsernameToken authentication allows for a requestor of a Web service to send along authentication information in the form of a username and password using standardized XML markup. Using Microsoft's WSE Toolkit, you can painlessly implement UsernameToken authentication with a few lines of code and some settings via the Toolkit's settings dialog box. This article just scratched the surface of the security capabilities provided by the WSE standards and the WSE 2.0 Toolkit.
To learn more about UsernameToken authentication, be sure to check out the code available at the end of this article.