Programatically using the BasicHttpsBinding and UserNamePasswordValidator classes in a WCF C# .NET Windows Service.

“Now we find out if that code is worth the price we paid.” – Princess Leia

I wrote an article recently regarding how to create a WCF based C# .NET Windows Service (here). I’m going to build upon that further here by moving from the BasicHttpBinding class to the BasicHttpsBinding class, and from Windows authentication to a custom user name and password style authentication.

Now, if you’re using WCF services hosted by IIS then the solution is slightly different – however if you’re hosting the WCF functions in your own application/service then this comes in handy for providing HTTPS (SSL/TLS) encryption to your communications. Additionally, whilst Windows authentication is great in an enterprise environment for system to system communications, there may be times when you wish to use an alternative credential source to authenticate your WCF functions.

Let’s start with the HTTPS binding. You can do most (all) of this from the application configuration files, but there are numerous examples of that. Here, I’m going to do the work in the code instead.

private static ServiceHost _sHost = null;

internal static void StartService()
{
	BasicHttpsBinding httpsBinding = null;

	// Create Service Host
	_sHost = new ServiceHost(typeof(WCFServiceClass));

	// Create HTTPS Binding with TransportWithMessageCredential security
	httpsBinding = new BasicHttpsBinding(BasicHttpsSecurityMode.TransportWithMessageCredential);

	// Use UserName Message Authentication
	httpsBinding.Security.Message.ClientCredentialType = BasicHttpMessageCredentialType.UserName;

	// Use Custom UserName Authentication Mode
	_sHost.Credentials.UserNameAuthentication.UserNamePasswordValidationMode = UserNamePasswordValidationMode.Custom;

	// Use the Custom ServiceAuthentication Class for Validation
	_sHost.Credentials.UserNameAuthentication.CustomUserNamePasswordValidator = new ServiceAuthentication();

	// Attach a Certificate from the Certificate Store to the HTTP Binding
	_sHost.Credentials.ServiceCertificate.SetCertificate(StoreLocation.LocalMachine, StoreName.My, X509FindType.FindByThumbprint, "Certificate Thumbprint Here");

	// Add Binding
	_sHost.AddServiceEndpoint(typeof(IWCFServiceClass), httpsBinding, "WCF URI Here");

	// Start Service Host
	_sHost.Open();
}

internal static void StopService()
{
	if (_sHost != null)
		_sHost.Close();
}

Ok, so a lot of the code in there should be familiar from the earlier introductory WCF article. I’ve modified that example slightly to change the security mode to TransportWithMessageCredential. That basically means that the transport is encrypted and the messages are authenticated (per message). With that configuration, I then need to specify an authentication mode, and I’ve chosen UserName which means that I now need to specify a credential provider. The credential provider used here is a custom authentication class (code below). This class will perform the User Name and Password validation – it could be based on a flat file, database etc.

After that, I’ve then specified the certificate to use for the HTTPS binding. The certificate in question was loaded into the computer certificate store, and then referenced by the certificate thumb print. The certificate could also be picked up from file, or from various other sources. I’d rather the security of the local certificate store though to protect the keys. The thump print will basically look like this “003214DFSDF23432FSDF234SDF”. You can extract the thumb print directly from the certificate, remove the spaces between the hex bytes, and then put it together like the string above. If you do copy and paste though, beware of hidden characters coming in that corrupt the string. I’ve had to manually retype the first byte a few times to get the “invalid hexadecimal format” error to go away.

The URI you use is then typically in the format of https://servername:port/ApplicationName.

With the URI and the certificate thumb print specified, now you need to configure the OS HTTP module, given that the HTTPS module in the OS handles incoming HTTPS calls. Simply provide the port/IP information from your URI, the certificate thumb print, and then a GUID for the new HTTPS configuration. You can just copy the GUID from your application (AssemblyInfo.cs).

netsh http add sslcert ipport=0.0.0.0:1234 certhash=003214DFSDF23432FSDF234SDF appid={739e45bf-abcd-4a2a-9f00-4181858e637e}

The only remaining activity on the server side is the custom authentication class.

using System.IdentityModel.Selectors;
using System.IdentityModel.Tokens;

public class ServiceAuthentication : UserNamePasswordValidator
{
	public override void Validate(string strUserName, string strPassword)
	{
		if (strUserName == null || strPassword == null)
			throw new ArgumentNullException();

		if (strUserName != "user1" || strPassword != "password")
			throw new SecurityTokenException("Unknown Username or Password");
	}
}

Obviously you’d put some actual effort into the code that validates the user name and password including validation of the input itself, before attempting to validate against a credential store. You will also need to reference the System.IdentityModel.Dll assembly.

The client code below is fairly similar to the original example, with the binding type and the credential type now changed.

ChannelFactory<IWCFService> cfClient = null;
BasicHttpsBinding httpsBinding = new BasicHttpsBinding(BasicHttpsSecurityMode.TransportWithMessageCredential);

httpsBinding.Security.Message.ClientCredentialType = BasicHttpMessageCredentialType.UserName;

cfClient = new ChannelFactory<IWCFService>(httpsBinding, "WCF URI Here");

cfClient.Credentials.UserName.UserName = "user1";
cfClient.Credentials.UserName.Password = "password";

cfClient.CreateChannel().WCFFunctionName();

I really like using WCF – it’s certainly much easier than it used to be. In the next example I’ll show you how to send and receive JSON data from your WCF service, making it easier to interact with non-.NET based applications, e.g. a Java application running on Unix.

~ Mike

2 thoughts on “Programatically using the BasicHttpsBinding and UserNamePasswordValidator classes in a WCF C# .NET Windows Service.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s