Self Issued X509 Certification Token

January 8, 2009

At the company I work for, there was a need to create a n-tier application with username authentication.

For some reason WCF requires a certificate which is understandable, but shouldn’t this be a choice of my company?I will not get deep with WCF about this part. Maybe in another section.

So what is the problem. The problem is that everyone talks about making a self issued certification token and using it to run in development, but few talk about deploying the application. And most of those few have posted questions that remain unanswered or have posted some guidelines that do not work entirely.

My development machine is Vista 32 based and target deployment was for both Vista 32 and Windows Server 2003 both environments under their respective IIS.

First of all, the token must be created. At start as many of you, I knew little about certificates. I really believe this not to be a common interest for developers, so it has been really annoying not to really understand what has been happening or why that command was user. It is fair to say that at the moment, I haven’t really understood why the solution works, probably because after not being able to find solutions for my problems I had to resort to trial and error. Additionally Microsoft does not make public a lot of information about the subject or relevant APIS and their errors. There are some tools for example that generate a very common error message that one can not track the reason causing it.

Certificates manager console will be required with knowledge of it for importing and exporting.

Anyway, lets start.

First I will discuss how to create a self issued token through the development token. To token is created for a WCF service and its store location will be LocalMachine and store name My. My post is not for WCF so I assume that one knows what the above means for WCF.

Then I will discuss how to setup IIS in the development machine.

Last in this post I will tell you how to reuse the above token in other machines.

Token Creation

In order to create a self issued token, you must have installed in the machine Windows SDK. Because the machine is a development the above should be found in :\Program Files\Microsoft SDKs\Windows\v6.0A\Bin for Vista and XP and C:\Program Files\Microsoft Platform SDK\Bin for Windows 2003.If not found for windows 2003 you can download it from here. In any case WSDK will refer from now on to the appropriate path.

In order to create the token a certification authority token must be created first and then the token itself issued by the above. In order to keep it simple we assume that TokenCA is the certificate authority token and TokenCert is the certification token based on TokenCA.

In order for the above to work for wcf, the key must be exportable so in each command that it is required the appropriate flag is used. I will not analyze the commands, you can do it from the help or Internet.

The goal of the next steps is to create a zip file with the reusable token.All files will be saved in C:\ . Password will be required. I chose one and used it everywhere.

Create Certification Authority

Open a command prompt for the WSDK path.

Execute makecert -n “CN=TokenCA” -r -sky exchange -pe -sv C:\TokenCA.pvk C:\TokenCA.cer

Create Certification Token

Execute makecert -sk =TokenCert -iv C:\TokenCA.pvk -n “CN=TokenCert” -ic C:\TokenCA.cer -sky exchange -pe C:\TokenCert.cer -sr LocalMachine -ss My

Import Token

In order to Import Token you must open the Certificates manager from the mmc.

In the Trusted Root Certification Authorities under certificated select import and choose the TokenCA.cer we created.

Then in the Personal under Certificated select import and choose TokenCert.cer.

At this stage the token is ready to be used by the development WCF Service.

Export Token

In the Personal under Certificated select import and choose the token we created and select export. On the question if you want the export the private key, choose YES.

image

Then select like the next picture

image

Then enter password, and select where it should be stored. I entered c:\Token.pfx.

At this stage in c:\ there should be 4 files starting with token which you can pack but the reusable part is the Token.pfx.

Deploying in another machine

Now we want to use the above certificate. In the certificates manager in Certificates node under Personal you import the TokenCert.pfx enter the password and mark the key as exportable like this

image

IIS Setup

In order for any process to use the token we created or imported, that process must have read rights under the user it is running over the actual file windows created for the certificate token (TokenCert).

So for IIS NETWORK_SERVICE must have read access over the file.

If the OS is Windows 2003 you can use WinHttpCertCfg.exe which has two problems. First it is deprecated for Vista and second most important it gives the user Full Control access. So I do not recommend it. In any case use it like this winhttpcertcfg -g -c LOCAL_MACHINE\My -s “TokenCert” -a “NETWORK SERVICE”

Windows itself want tell you the file itself. In order to locate it you must follow these instructions.After you have located is just give the right like every other folder/file sharing.

Now the IIS can access the certificate. If you don’t do this the service will fail in every attempt including just hitting the svc which I used as a test.

In Vista there is another way through the certificates manager. You can select the certificate token (TokenCert) and right click -> All Tasks -> Manage Private Keys will display the access rights dialog for the actual file.

Questions

I can’t understand why in other machines the TokenCA is not needed. When I had also imported that, there were errors both from the finding tool and the winhttpcertcfg. This problem was resolved based truly on trial and error, but I still can’t understand why when creating the TokenCert, TokenCA is needed and then not. I know that the key is contained in the pfx, but as a mentioned my knowledge of certificates is superficial so the question still remains.

If I use the TokenCert outside the intranet will it still work?

Future Stuff

Because I want/ need automate the procedure, tools will be written to do the above in sequence. When I do, I surely post here or on codeproject.

Conclusions

Any questions you might have, please just ask and if I can help I will. The above process has taken me 2 days to find and I personally find it unacceptable especially when there is a WCF authorization system that requires the use of a token.

This article is based again on a specific WCF deployment that was required of me, but I think it is irrelevant.

Hope I didn’t forget anything.

Finally let me just say that the simplest and oldest authorization has been turned into a deployment nightmare. Hope this article helps the community. As always everything is great when Microsoft evangelist advertise. You guys, we are not making an assignment for IT bachelors.


How to debug a WCF service

June 28, 2008

Introduction

WCF default debugging does not support edit and continue features, as I have said in my blog post

Background

In that post I said that there is an easy way to do it, but I didn’t give any code. So this article is about how to it. The reason I wrote this article, is because a fellow member wrote a useful article about wcf, and in tip1 he suggested using a console application.

My scenario for wcf service consuming and debugging is a Client Server application. I believe my solution can apply and for other scenarios.

How to do it

You need this class DebugServiceHost

internal class DebugServiceHost:IDisposable
{
    private static string serviceExecuteTypeName = "ExecutionService.ServiceExecute, ServiceSide.ExecutionService, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null";
    private static string iServiceExecuteTypeName = "ExecutionService.IServiceExecute, ServiceSide.ExecutionService, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null";
public static string Address = @"http://localhost:9999/ExecutionService/ServiceExecute/";
    public static Binding Binding = new WSHttpBinding();

    static DebugServiceHost()
    {
        isEnabled = Type.GetType(serviceExecuteTypeName) != null;
    }
    public DebugServiceHost()
    {
        Type serviceType = Type.GetType(serviceExecuteTypeName);
        Type iServiceType = Type.GetType(iServiceExecuteTypeName);
        this.debugHost = new ServiceHost(serviceType);

        this.debugHost.AddServiceEndpoint(iServiceType, Binding, Address);
        this.debugHost.Open();
    }

    private System.ServiceModel.ServiceHost debugHost;

    private static bool isEnabled = false;
    public static bool IsEnabled
    {
        get { return isEnabled; }
    }

    #region IDisposable Members
    private bool disposed = false;
    public void Dispose()
    {
        if (this.disposed)
        {
            return;
        }
        this.debugHost.Close();
        GC.SuppressFinalize(this);
    }

    #endregion
}

where ServiceSide.ExecutionService.ServiceExecute is the namespace of the wcf service and ServiceSide.ExecutionService the assembly containing it.

Using the code

I use a provider class, but its up to you how to implement the above feature.

DebugServiceHost has a static property IsEnabled, which basically checks whether the service is locally located to the running client execution folder. If that is true then using an instance of the class, host the service as well, which is automatically disposed.

This a sample code from my project that consumed the true or debug hosted service.

Collapse

public static class Provider
{
    private static DebugServiceHost dbh;
    public static void CheckAndRunDebugService()
    {
        if (DebugServiceHost.IsEnabled)
        {
            dbh = new DebugServiceHost();
        }
    }
    public static string RemoteURL { get; set; }
    private static IServiceExecute iServiceExecute = null;
    private static IServiceExecute GetInterface()
    {
        if (iServiceExecute != null)
            return iServiceExecute;
        iServiceExecute = CreateClient();
        return iServiceExecute;
    }
    private static ServiceExecuteClient CreateClient()
    {
        string address = "";
        if (DebugServiceHost.IsEnabled)
        {
            address = DebugServiceHost.Address;
        }
        else
        {
            address = String.Format("{0}/Service.svc", Provider.RemoteURL);
        }
        return new ServiceExecuteReference.ServiceExecuteClient("DefaultEndPoint", address);
    }
}

where

  • IServiceExecute is the Interface created when you add the service Reference.
  • ServiceExecuteReference.ServiceExecuteClient is the client created when you add the service reference
  • DefaultEndPoint is the endpoint in my config file.

Points of Interest

At first I at the first call to the service, I create the host. But as I mentioned in my post there was problem with that implementation.

Last problem hopefully

Finally a point of interest which was my last obstacle that took me a half day to find. I had implemented a provider class for the remoting part, which if needed, fired up the service host. Everything worked just great in the test projects, but at some point I tried to extend the framework with WPF.

The trick was that at first request, through static constructor I checked if the service was required to be hosted, and did that. But this did not work when I made the call from WPF. The only error was a timeout exception. I was going crazy, and then it kicked in. Never trust completely a 3 party library.

Solution

I made three clients, one Console, one Windows one WPF and stripped down the functionality of my framework to test. On each UI Client I made the call (and raised subsequently the host) after a UI reaction. I turns out that neither Windows Forms played correctly, when for example the call is made through a button click event. When I saw that, I made the host come up before the UI part was ever initialized and guess what? It all played just fine.

I really can’t understand how this has not been mentioned.

So I refactored the code, and at the program main entry method I call Provider.CheckAndRunDebugService()

Final thing is that, you must implement a trick in order for all serverside assemblies to be found in the client execution folder when you are debugging. There are a number of ways to do achieve this mainly by using post build event or by just adding the references and deleting them when in deployment face. I use the first.

Apologies

There is not project code, because the above resides in a framework project, I have written for the company I work for.

CodeProject Article


WCF Debugging and a WCF review

June 17, 2008

A comment

At some point, people need to understand that, business applications are not like console applications. So all these comments on the net, in blogs and forums, should be a little more double checked for real life development process because they mislead other people. Especially for LINQ to SQL and WCF, I am really bored reading about how great they are and how easy they are, but the truth is that LINQ to SQL is not for applications (reason in another post) and I was one of the victims that tried to adopt it, and WCF although is great, it can also be a pain in the ass. When searching through the net, keep in mind always that Internet is not always correct as I have wrote here. I really suspect that many of the blog post although, they can be helping, are not revealing entirely the truth and the disadvantages. I have always been fun of Microsoft Technologies but there is a limit to the indirect advertisement.

Following instructions

Back to the post subject. Many of you have done what everybody on Internet says. Add a WCF Service and a Service Reference and Great, all is ready and done. Even for debug, every time I execute debug the application, a dummy Debug Host is raised and I can debug the service. All is great? No.

Questions

First of all. What if I’m not running parts of the solution that require the service. Why should I be punished with the overhead of raising the host?

Second and most serious. Has really anyone tried to debug the service, and every underlying class used by it? Has anybody tried to utilize edit and continue, among all these guys who say how great WCF is?

I tried and as you can guess from my attitude, I could not utilize Edit And Continue. When I am developing a big Application, usually there will be at least 2 layers behind the service. Should I restart the application each time? And don’t let me talk about the debug through the dummy client, when an Operation Contract of mine, will use a complex data type. It is just not possible.

So what is the solution?

Easy someone can say, but easier said than done. As you would with .Net Remoting, If the service is located in your output directory, by whatever trick in the solution, then just raise the host programmatically in an address of your choice and then tell the client to hit this address. This way you have always simulating data transferring through WCF channels (very important), and you can of coarse use the feature of Edit and Continue.

The problem is that the dummy service the solution raised keeps coming up, which is very annoying. I haven’t found a solution, mainly because in the framework I’m developing, there is a single Operation Contract handling abstract Message Types. This was another great milestone for me in WCF. I really can’t understand why they have made DataContractSerializer as complicated, and not simple as the one used in plain old fashioned remoting. Having this service in my framework, I do not have in my solution the WCF Service so , there is no penalty overhead from the Debug Host that is raised.

Last problem hopefully

Finally a point of interest which was my last obstacle that took me a half day to find. I had implemented a provider class for the remoting part, which if needed, fired up the service host. Everything worked just great in the test projects, but at some point I tried to extend the framework with WPF.

The trick was that at first request, through static constructor I checked if the service was required to be hosted, and did that. But this did not work when I made the call from WPF. The only error was a timeout exception. I was going crazy, and then it kicked in. Never trust completely a 3 party library.

Solution

I made three clients, one Console, one Windows one WPF and stripped down the functionality of my framework to test. On each UI Client I made the call (and raised subsequently the host) after a UI reaction. I turns out that neither Windows Forms played correctly, when for example the call is made through a button click event. When I saw that, I made the host come up before the UI part was ever initialized and guess what? It all played just fine.

I really can’t understand how this has not been mentioned.

Conclusion

For me WCF is good for the plumbing. It is much more complicated than .Net remoting, really hard to troubleshoot if you are doing something outside the ordinary, which are discussed in all those praising posts and articles. Maybe I haven’t studied it as much, maybe I’m missing something but if the case is true, tell me how something that is advertised as easy and all remoting-problem solving can be this hard to utilize and debug. You will say that WPF, has as much difficult learning curve but WPF is not advertised as the magic trick that the programming world was missing. Since I have read about it, everyone mentioned that it is hard and difficult to adopt, and it is not for all kinds of applications. For me WPF is the star of .NET3.

Despite all these problems I really believe in WCF, because of other great stuff that it supports.  Regarding security MS says here that

You should not use WCF Service Host to host services in a production environment, as it was not engineered for this purpose. WCF Service Host does not support the reliability, security, and manageability requirements of such an environment. Instead, use IIS since it provides superior reliability and monitoring features, and is the preferred solution for hosting services. Once development of your services is complete, you should migrate the services from WCF Service Host to IIS.

Having this in mind, I can’t stop thinking whether WCF is a great overhead on development, when .NET is remoting is a well tested solution under IIS. But choices have been made, mainly because the new technology I believe is here to stay.

Links

Same Article at code project.