User authentication and sessions

Contents

  1. Diagram of classes and methods
  2. Logging in
  3. Impersonating another user
  4. Restricting a single session to one IP address
  5. Managing SessionControl objects

See also

Last updated: $Date: 2009-04-06 14:52:39 +0200 (må, 06 apr 2009) $

1. Diagram of classes and methods

2. Logging in

It is the SessionControl class that has the main responsibility for user authentication. Anyone can create a SessionControl using the Application.newSessionControl() method, but almost nothing can be done without logging in. Logging in is done by calling the login() method. Depending on if internal or external authentication is used the call proceeds to verifyUserInternal() or verifyUserExternal(). The only exception is that the root account is always verified with internal authentication.

The internal authentication loads the user and MD5 encrypted password from the database and compares it to what was passed to the login method. It also checks the disabled and expiration date properties of the user.

The external authentication creates an Authenticator object and passes the login and password to it. If the authentication is successful it synchronizes as much information as possible with the user information stored in the BASE database. If the external authentication fails and the cached passwords option is used it delegates to the internal authentication.

When the user is authenticated a LoginInfo object is created. It holds all information about the logged in user that is needed by the core elsewhere, including:

3. Impersonating another user

Normally a single SessionControl can only handle a single user at a time. But, sometimes it is neccessary for to "fool" the core into beleiving that another user than the actual one is logged in. For example, a job queue manager usually logs on using a special service account, but when the jobs are executed they must run as if the user owning the job was logged in. This can be done by the impersonation feature.

The impersonateLogin() takes the id of another user as input parameter. No password is required since it is not known. However, for the impersonation to succed the special ACT_AS_ANOTHER_USER permission is required. This permission is by default only granted to the root account, but can be given to any any account by an administrator. For the job queue service account we recommend that only READ and WRITE permission to jobs are given and of course the ACT_AS_ANOTHER_USER permission.

When impersonated all methods of the SessionControl acts as if the impersonated user is the one that is logged in. The only difference is that isImpersonated() returns true and the logout() method reverts to the original user.

4. Restricting a single session to one IP address

It is the SessionControl class that has the main responsibility for user authentication but it starts already with the Application.newSessionControl() and Application.getSessionControl() methods.

These two methods both hava a remoteId parameter. It is optional but it is recommended that for example the IP address of the client computer is used. Consider the following code taken from the web application:

// First request
String myIp = request.getRemoteAddr();
SessionControl sc = Application.newSessionControl(null, myIp, null);
String ID = sc.getId();
sc.login(username, password, null);

// .... later in another request
String ID = request.getParameter("ID");
String myIp = request.getRemoteAddr();
SessionControl sc = Application.getSessionControl(ID, myIp);

If the myIp parameter is not the same as in the first request an exception will be thrown by the getSessionControl() method. This makes sure that nobody can get access to the session of another user just by guessing or scanning the network for ID values. It is important the value for myIp is something that is hard to fake such as the IP address of the client computer.

If the myIp value is null in both method calls the check is disabled and there is no guarantee that following requests come from the same computer.

5. Managing SessionControl objects

The SessionControl object is thread-safe and is intended to be used throughout the entire session a user is logged in. It is possible to reuse the same SessionControl after the user has logged out, but we recommend that it is discarded and a new one is created.

It is the responsibility of the Application class to manage the creation and deletion of SessionControl objects. It holds a cache in the form of a map from the id to the SessionControl object.

Each SessionControl object has a lastAccessed property that is updated each time a call is made from a client application. A timer in the Application object is regularly checking that this value are within the limits specified by the timeout property. If not, the SessionControl is discarded and if a user was logged in he/she is logged out.

If it just happened that the user had a long lunch and later tries to get the non-existing SessionControl object an ItemNotFoundException is found, but it is possible for a client application to create a new SessionControl object with the same id. This is especially useful for the web application which can intercept the exception and let the user login again and the reload the original page. Since the reloading usually means that the old id is passed as a parameter to that page, it is essential that the new SessionControl object has the same id as the old one.