Listing 1

// Default includes
using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Web;
using System.Web.Services;

// These three references are needed for WSE 2.0
using Microsoft.Web.Services2;
using Microsoft.Web.Services2.Security;
using Microsoft.Web.Services2.Security.Tokens;

// Other necessary namespaces
using System.Security.Principal;
using System.Net;

namespace FunWebService
{
	[WebService(Namespace="http://Sunaptic.com/Kelvin.Tsang")]
	public class FunService : System.Web.Services.WebService
	{
		public FunService()
		{
			InitializeComponent();
		}

		#region Component Designer generated code
		// I omitted the code here
		#endregion

		/// This web method returns you the motivation quote of day
		[WebMethod]
		public string GetQuote(string myName)
		{
      	// The web service request should come with an authentication
			// token.  Here I call this helper function to retrieve the
			// token.
			UsernameToken tok = 
				GetUsernameToken(RequestSoapContext.Current);

			// Here I do authorization.  Only people in FunnyGroup
      	// are allowed to call this web service.
      	if (tok.Principal.IsInRole(string.Format("{0}\\FunnyGroup",
        		Dns.GetHostName())))
      	{
        		string quote = 
					"Luck is when preparation meets opportunity";
				return string.Format("Listen, {0}! {1}!", myName, quote);
	      } 
      	else
      	{
        		// Throw an error
				throw new ApplicationException("Permission denied");
      	}
		}

    	// This helper function gets the token from the web
		// service request
		private static UsernameToken GetUsernameToken(SoapContext context)
		{
			if (context != null
				&& context.Security.Tokens.Count != 0)
			{
				foreach (UsernameToken tok in context.Security.Tokens)
				{
					return tok;
				}
				throw new Exception("Request contains no UsernameToken.");
			} 
			else
			{
				throw new Exception("Request contains no security token");
			}

		}
	}

	// This UsernameTokenManager is necessary because we wil receive 
	// the authentication token as a username and a hashed password.
	// Windows has no ability to retrieve password from the operating
	// system.  Therefore, we must specify the password here, such that
	// WSE 2.0 can compute the hash, and compare this to the one from
	/ the authentication token.
	public class MyUsernameTokenManager :   UsernameTokenManager
	{
		protected override string AuthenticateToken(UsernameToken token)
		{
			ArrayList roles = new ArrayList();
			roles.Add(string.Format("{0}\\FunnyGroup",
				Dns.GetHostName()));
			token.Principal = 
				new GenericPrincipal(new GenericIdentity(token.Username), 
				roles.ToArray(typeof(string)) as string[]);

			return "password";
		}
	}
}


Listing 2

using System;

// This is for the web service that you call to get the quote of the
// day
using FunApplication.localhost;
// These three references are needed for WSE 2.0
using Microsoft.Web.Services2;
using Microsoft.Web.Services2.Security;
using Microsoft.Web.Services2.Security.Tokens;

namespace FunApplication
{
	class FunClass
	{
		[STAThread]
		static void Main(string[] args)
		{
			// Declare an instance of your web service
			// Notice that your web service is prepended with "Wse".
			// This is provided automatically if your web service is WSE
			// enabled.
			FunServiceWse proxy = new FunServiceWse();

			// Specify your name and password
			string myName = "FunnyUser";
			string myPassword = "password";

			// Create a token. "SendHashed" means you are sending a hash 
			// of your password, so your password will not be seen easily
			// by a network sniffer
			UsernameToken token = new UsernameToken(myName, 
			 		myPassword, PasswordOption.SendHashed);

			// Add the token to your web service request
			proxy.RequestSoapContext.Security.Tokens.Add(token);

			// Call the web service
			System.Console.WriteLine(proxy.GetQuote(myName));

			// Press any key to end the application
			System.Console.ReadLine();
		}
	}
}


Listing 3

- <wsse:UsernameToken xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-
 200401-wss-wssecurity-utility-1.0.xsd" wsu:
 Id="SecurityToken-00448ae6-d01a-434b-9bb4-afb480c9e4c8">
 <wsse:Username>FunnyUser</wsse:Username>
 <wsse:Password
 Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#
 PasswordDigest">l8RNg8rHgIP5mmaKUMRq+8JjiN0=</wsse:Password>
 <wsse:Nonce>9jemgbazHQRVou/CuZppZQ==</wsse:Nonce>
 <wsu:Created>2005-02-22T06:07:19Z</wsu:Created>
 </wsse:UsernameToken>