Authenticated Web Services in .NET
Sometimes I get the feeling that I’m doing something a little too out there. This usually occurs when something that I thought would be simple and widely implemented … isn’t. This was my thinking as I dived into the world of authenticated .NET web services.
My use case is simply to invoke a web service with user-provided credentials. If the credentials fail, prompt the user again, displaying the reason they could not be logged in.
The first part is straightforward. Just set the Credentials property on the SoapHttpClientProtocol instance and you’re away.
However if you want to present the user with a login dialog when credentials are required (pull, not push), it is definitely not straightforward. I was expecting something like Java’s authentication callback but I couldn’t find anything remotely like it. There may be other ways, but the way I did it was to:
- Create a class that implements
IAuthenticationModuleand decorates another instance. - Add an event to the class (I called it
AuthenticationRequiredand make it fire from theAuthenticatemethod before you delegate to the wrapped instance. The event you create needs to take custom arguments so the event handlers can modify and return the authentication details. - Use the
System.Net.AuthenicationManager.RegisteredModulesenumeration to find the module registered for the authentication type you’re using (e.g. Basic, Digest), wrap it with an instance of your event driven class, and replace it using theRegistermethod. - Register an event handler with your wrapped instance. The event handler can display a dialog, and update or replace the
ICredentialsinstance you passed in theAuthenticationRequestEventArgs.
Caution! Remember that Windows forms is not thread safe: if you do need to do some GUI work, make sure you use theInvokeandInvokeRequiredmethods onFormto avoid synchronization issues. - Make sure your
SoapHttpProtocolClientinstance has theUseDefaultCredentialsset to true, otherwise the AuthenticationModules won’t be called.PreAuthenticateshould be true as well to save a request if you know that authentication will be required.
That’s it … well, almost. This will allow you to ask for Credentials once per call. If the user enters invalid credentials, the request will fail. Not optimal. To make .NET ask you again, you have to repeat the request.
You can either do that each time you make a request, or you can create a method that takes a delegate as a parameter and does the repetition … or you could use a dynamic proxy. For me, laziness appeals, so I used Castle’s dynamic proxy implementation. This might be the subject of another post though …
September 1st, 2006 at 9:27 am
So I take it you didn’t use SWT, then?
September 1st, 2006 at 12:53 pm
No … the whole Java GUI thing just didn’t thrill me, no matter how much I like Eclipse. For that matter, I could have used the Eclipse runtime. I’m committed now, I think, though there’s not much client side actually accomplished.
I could switch to Hessian as the transport protocol - there’s a C# implementation of that. My gut feeling is still that a Java GUI will take longer to implement than a .NET one, hiccups notwithstanding. There a large amount of personal comfort in that estimation though.
Time will tell I suppose.