Avisi Blog

The user and its password

Geschreven door Mats Stijlaart | 22 November 2012

Many applications make use of user management and user authentication. It is a commonly used and understood aspect, but I think we are doing it wrong.

The Domain

When you browse the web or read a book you will probably find one of the following 3 domains (or one that is pretty similar).

1. The basic user.

----------
|User    |
----------
|username|
|password|
----------

With this user you are able to login and have all user rights in the system. Sometimes a boolean field will be added to indicate if a user is a administrator.

2. The auhoritized user.


-----------             -----------
|User     |             |Authority|
----------- 1         * -----------
|-username|-------------|name     |
|-password|             -----------
-----------

With this domain users have certain rights based on the referenced authorities.

3. The roles and groups.

----------             -----------         -----------
|User    |             |Role     |         |Authority|
---------- 1         * ----------- 1     * -----------
|username|-------------|name     |---------|name     |
|password|             -----------         -----------
----------

With this domain users have roles or are members of groups. For example: 'administrators', 'blog-posters', 'board-member', etc. Those roles each have certain authorities resulting that a user has many authorities through many roles.

The Problem

I am missing one aspect that I would like to see in this model and that is authentication. Yes I know, there is a username and password but I do not like it.
The status quo of web applications allows users to authenticate themselves with multiple authentication methods (Facebook, OAuth, Twitter, username/password combinations, Google accounts, etc.) and the rigid domains do not support this.

The Solution

Step 1
To allow one of the above domains to support facebook authentication we can extend the domain like this (the roles and authorities are omitted):

----------             ------------------
|User    |             |FBAuthentication|
---------- 1      0..1 ------------------
|username|-------------|facebookUserId  |
|password|             ------------------
----------

I'm still not satisfied because this domain has 2 bad smells:

  1. We have 2 different authentications in two different type of models. The 'normal' authentication is embedded in the user model and the 'facebook' authentication in another type model.
  2. Users that log in or sign up with facebook do not need a password. This domain can only support that if the password field in the user model may be 'null' which makes the validation on the user model a mess.

Step 2
The next step would be to extract the username/password combination from the user model. Lets say you use the Spring Security framework, the domain will look like this:

---------------------            ---------           ------------------
|SpringAuthentiction|            |User   |           |FBAuthentication|
--------------------- 0..1     1 --------- 1    0..1 -----------------|
|username           |------------|       |-----------|facebookUserId  |
|password           |            ---------           ------------------
---------------------

This domain will indicate that a user will have zero or many authentications.

Step 3
The last step is to add attributes to the user. These attributes could be a value if the user is enabled or a screen name for the user.

Conclusion

This solution has advantages and disadvantages.
The main disadvantage is a more complex domain and so a more complex application. The main advantage is that a user is able to add multiple authentication methods to its user account. Even more of a singular type.
Another advantage is that this model allows better merging between 2 users. The user for a single authentication can be changed.

Let me hear what you think about this concept and if you can think of reasons why you should or shouldn't adopt it.