When you think ASP, think...
Recent Articles
All Articles
ASP.NET Articles
ASPFAQs.com
Message Board
Related Web Technologies
User Tips!
Coding Tips
Search

Sections:
Book Reviews
Sample Chapters
Commonly Asked Message Board Questions
JavaScript Tutorials
MSDN Communities Hub
Official Docs
Security
Stump the SQL Guru!
Web Hosts
XML
Information:
Advertise
Feedback
Author an Article
Jobs

ASP ASP.NET ASP FAQs Message Board Feedback ASP Jobs
 
Print this Page!
Published: Wednesday, July 14, 2004

An Extensive Examination of Web Services: Part 9

By Scott Mitchell


An Extensive Examination of Web Services Index
An Extensive Examination of Web Services is a multi-part article series spanning several months. Listed below are the current "parts," along with a very brief synopsis and the date published.
  • Part 1 - Examines the basics of Web services, what Web services are, and the technologies and standards that serve as the underpinnings of Web services. (October 8th, 2003)
  • Part 2 - Examines creating Web services using Visual Studio .NET. Looks underneath the hood of the code created by VS.NET. (October 15th, 2003)
  • Part 3 - Examines creating a client application that consumes a Web service. Discusses the purpose and structure of a WSDL document, along with creating and using proxy classes to consume a Web service. (November 5th, 2003)
  • Part 4 - Examines the utility of Web services and common scenarios where Web services make sense. A business-oriented look at Web services. (November 19th, 2003)
  • Part 5 - Takes an in-depth look at XML serialization, which is the process of converting a data type, such as an integer, array, or custom class, into its XML representation, and back again. Every time a message is passed to or from a Web service, XML serialization transpires. (December 17th, 2003)
  • Part 6 - Looks at sending metadata to a Web method through the use of SOAP headers. Examines defining and accepting a SOAP header on the Web service end, and looks at sending a populated SOAP header from the client. (December 31st, 2003)
  • Part 7 - Examines how the incoming and outgoing messages to a Web service can be programmatically modified via SOAP Extensions. (January 21st, 2004)
  • Part 8 - Learn about the Web Service Enhancements (WSE) and Microsoft's free class library for implementing the WSE standards. (June 30th, 2004)
  • Part 9 - See how to implement UsernameToken authentication using the WSE 2.0 Toolkit. (July 14, 2004)
  • Part 10 - Learn how to send large amounts of data as attachments using DIME and WS-Attachments. (September 8th, 2004)
  • Part 11 - Create (and consume) client-side script-accessible Web Services using Microsoft's ASP.NET AJAX framework. (September 26th, 2007)

Introduction


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.

- continued -

The WSE Toolkit installation screen.

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:

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
               xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
               xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Header>
    <wsse:Security soap:mustUnderstand="1">
        <wsse:UsernameToken namespaces>
          <wsse:Username>username</wsse:Username>
          <wsse:Password Type="type info">password</wsse:Password>
          <wsse:Nonce>nonce</wsse:Nonce>
          <wsu:Created>date created</wsu:Created>
        </wsse:UsernameToken>
    <wsse:Security>
  </soap:Header>
  <soap:Body>
    <WebServiceMethodName xmlns="Web Service Namespace" />
  </soap:Body>
</soap:Envelope>

The UsernameToken authentication standard allows for the client to send the password in one of three flavors:

  1. 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.
  2. 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.
  3. 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 Username and Password properties, specifies what password option to use, and attaches the UsernameToken object 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 CORP\bob and 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 using/Imports statements to the namespaces Microsoft.Web.Services2.Security and Microsoft.Web.Services2.Security.Tokens):

private UsernameToken GetUsernameToken()
{
	if (RequestSoapContext.Current == null)
	   throw new Exception("Only SOAP requests are permitted.");

	// Make sure there's a token
	if (RequestSoapContext.Current.Security.Tokens.Count == 0)
	{
	   throw new SoapException(
	      "Missing security token", 
	      SoapException.ClientFaultCode);
	}
	else
	{
	   foreach (UsernameToken tok in RequestSoapContext.Current.Security.Tokens)
	      return tok;
	   throw new Exception("UsernameToken not supplied");
	}
}

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 GetServerInfo() 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\bob or CORP\frank. You could write this method like so:

[WebMethod()]
public string GetServerInfo()
{
	UsernameToken token = GetUsernameToken();
	if (token.Username == "CORP\\bob" ||
	    token.Username == "CORP\\frank")
	{
	   // return detailed info
	}
	else
	{
	   // return limited info
	}
}

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 AuthenticateToken(token) method is to return the password for the user making the request. (The requestor's username can be accessed via the passed-in token.)

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:

public class AuthenticationManager : UsernameTokenManager
{
  protected override string AuthenticateToken(UsernameToken token)
  {
	string username = token.Username;

	... Lookup the user's password based on their username ...
	
	return user's password;	
  }
}

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: http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd
  • QName - Here you will need to enter the following hard-coded string: wsse:UsernameToken

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:

  1. Create a new application - either an ASP.NET Web application or a WinForms application will suffice.
  2. 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.
  3. 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 Wse.

To call the Web service passing a UsernameToken, use the following code:

// Call the Web service.  First, create a UsernameToken instance
UsernameToken token = null;
token = new UsernameToken(username.Text, password.Text, PasswordOption.SendHashed);

// Create a new instance of the Web service proxy
WebServiceProxyClassWse ws = new WebServiceProxyClassWse();

// Add the token to the Tokens collection
ws.RequestSoapContext.Security.Tokens.Add(token);

// Try calling the WS
try 
{
   string info = ws.GetServerInfo();
}
catch (SoapHeaderException she)
{
   // there was an authentication problem
}
catch (Exception ex)
{
   // there was some other kind of exception...
}
finally
{
   ws = null;
}

That's all there is to it!

Conclusion


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.

Happy Programming!

  • By Scott Mitchell


    Attachments:


  • Download the Web Service and Client Files


    Beginner's .NET XML Web Services

    Beginner's .NET XML Web Services DVD

    Beginner's .NET XML Web Services offers nearly eight hours of training on .NET XML Web services in a video format. This two-disc DVD set, presented by author Scott Mitchell, offers a unique opportunity for learning about the fundamentals of Web services. The 14 lessons begin with an examination of the core Web service standards, and then quickly move into showing you how to create and consume Web services in Microsoft's .NET Framework. There are in-depth lessons for each of the core Web service standards - XML, SOAP, and WSDL - along with examples of the Web Service Enhancements (WSE). Scattered throughout each of these chapters are extensive demos, depicting how to build, deploy, and access Web services using Microsoft's Visual Studio .NET. The DVD also contains a thorough examination of a real-world, end-to-end Web service application.

    Scott Mitchell is the editor and founder of 4GuysFromRolla.com, author of the An Extensive Examination of the Web Services article series, and author of numerous ASP and ASP.NET books.

    [Buy this DVD]

    Why get stuck with a 600-page paperweight when you can learn about .NET Web Services through an interesting and interactive video presentation?



  • ASP.NET [1.x] [2.0] | ASPMessageboard.com | ASPFAQs.com | Advertise | Feedback | Author an Article