Monday, September 28, 2009

User Authentication Design

Most systems today, in fact, any system today in which a user interacts with a system, will have some kind of user abstraction. Whether that abstraction is the incoming request for application data or a instantiated class that lives on the server, it nonetheless exists. More often than not, the application needs to know who this user is. It can then make decisions about what, if any, data this user can see or modify. This, of course, is authentication.

There are many different approaches taken to implement user authentication. Most web application frameworks have a built-in authentication system. If that authentication system is flexible enough, it will allow for an external authentication system to be used. This is often the route that is taken by any commercial application simply because systems that were designed to authenticate, often do it well. There is no need to reinvent the wheel. Another reason for doing this might be performance.

However, most simple applications, often web applications, need only simple authentication. By simple, I mean they don't need a production-ready authentication system that can simultaneously handle millions of users. This isn't necessary and would be a waste of time. In these scenarios, simple HTTP authentication will be enough to allow the application to behave as required.

Even simple authentication needs to be designed. There are many approaches that can be taken to implement the underlying authentication one of which is a self-authenticating user abstraction. The user abstraction is necessary no matter what and should always be present in any design. The self-authenticating approach means that the authentication activity is performed by the user abstraction itself, with no need to invoke a separate party. The structure of such an abstraction is illustrated below.

Once an application receives a request for authentication to happen, the user abstraction is instantiated. Once instantiated, this abstraction is then passed the necessary data in order to authenticate itself. The result of the authentication is then passed to the controller responsible for instantiating the user. This sequence is illustrated below.

There are obvious benefits and drawbacks to using such an approach. The drawback is that the user abstraction is instantiated regardless of what the authentication outcome is. This is because the authentication can't happen without a user instance. Should a user instance, even if only momentarily, exist if not authenticated? The benefit here is the self containment. There is no need for an external authentication system since the user is able to state to the system whether or not it is who it says it is. Of course, this may not even be a good thing. An authentication system may be a desired design element.