Custom Authentication Service....

Topics: CAB & Smart Client Software Factory
Jan 24, 2007 at 12:14 AM
Does anyone have an example of how to implement custom authentication and authorization?

Specifically, I'm interested in whether I should inherit from IAuthenticationService, or if I just completely write my own stuff. It seems like security should be built in here, but all of the examples seem to use Windows auth.

Jan 24, 2007 at 8:20 PM
Security is built in. You need to implement your own concrete version of IAuthenticationService, and then replace the CAB's version of that service with your own when the application builds itself. Specifically: in the Shell's override of the AddServices method. There you can do something like this (assuming you have a class called MyAuthenticationService which implements IAuthenticationService):

RootWorkItem.Services.AddNew<MyAuthenticationService, IAuthenticationService>();

We do this ourselves, because we authenticate against a database in our application. So at least you know it's possible and works :)
Jan 25, 2007 at 2:15 PM

But is there an example of a concrete class and it's use for this? The interface only has one method called Authenticate but I'm not sure how to use this (either filling in the Authenticate method since it doesn't return anything or using it in say a login screen).

Jan 25, 2007 at 8:53 PM
Well, everyone probably implements it differently. I can tell you how we did it and maybe that will help :)

How we implemented the Authenticate method:

Keep in mind that Authenticate doesn't return a value of any kind, so what you need to do to implement this event is delegate authentication to some objects/views that can handle the whole process for you.

Our concrete class is called AuthenticationService. In the Authenticate method we actually instantiate a LoginDialog (small Windows Forms element we wrote). This is the starting point of our authentication process. Since we show the LoginDialog as a Dialog, it blocks the Shell from starting up until the authentication process is complete and the DialogResult has been confirmed.

The LoginDialog then calls out to a service that we call GenericPrincipalAuthenticationService. This is the real authentication service for us, since it does the actual authenticating. What this service does is send the credentials over the wire in a secure WCF message, and authenticates those credintials against a database. The result is passed back to the GenericPrincipalAuthenticationService in the WCF response.

The LoginDialog then reads the results of the authentication message. If the user successfully authenticated, then we set the identity and principal. Our LoginDialog closes itself, setting its DialogResult to "DialogResult.OK". At the AuthenticationService we check to make sure the DialogResult is DialogResult.OK. Since showing our LoginDialog is a blocking action, once the DialogResult is returned and the Dialog closed, the Shell begins loading.

If the user failed to authenticate then the LoginDialog issues a BadPassword error (gives the user three tries to get it right). On a failed 3rd attempt the LoginDialog returns DialogResult.Cancel or something other than DialogResult.OK. The AuthenticationService detects this, and calls Environment.Exit(0); The shell never fires up in that case.

There is probably a better way to do this, but this is how we do it. Hope that helps!