Implementing Hunchentoot custom sessions.

Hunchentoot has a built-in session handling mechanism for dealing with web server sessions. The implementation appears to be quite thorough and it complies to most of the OWASP recommendations for secure session handling. Many of its properties are easily customisable and it should be sufficient for most situations but there are some properties which can only be customised by completely replacing the session mechanism.

Hunchentoot stores the session data in RAM and only sends a random token to the client. As per OWASP recommendations, the token is a meaningless number and contains no session data. It only serves as a database lookup key with some embedded security features.

The implication of keeping session information on the server and only in RAM is that a session is only accessible on the same server where it was created and that all session information will be lost when the application exits. When this happens all the users will have to log in again.

This may be an acceptable situation if the website is only served from a single server and when loss of the session data is not a problem. When sessions do contain important data it is better to store it in persistent storage.

When the website is served from multiple servers the same session information must be accessible from all the server instances otherwise a user will need to log in each time his request is handled by a different server.

To address these two issues require changing Hunchentoot’s session storage behaviour. This is also one of the properties which can not be customised without replacing session handling completely.

The documentation makes some passing remarks about replacing the session mechanism and there are some comments in the Github issues too.

Hunchentoot is implemented in CLOS and getting from the documentation to your own customised session implementation requires more than a superficial knowledge of CLOS. Without that extra bit of CLOS knowledge it is far from clear how one should approach this customisation.

Below is some code describing the beginning of what such a session replacement looks like.

(defclass custom-session () ( ;; Implement session class ) (:documentation "Custom session class does not have to descend from hunchentoot:sessions.")) (defclass custom-session-request (hunchentoot:request) ( ;; This class does not need any additional code ) (:documentation "Subclass hunchentoot:request to allow using own session class.")) (defmethod hunchentoot:session-cookie-value ((session custom-session)) ;; Implementation code ) (defmethod hunchentoot:session-verify ((request custom-session-request)) ;; Implementation code ) ;; Instantiate acceptor to use the custom session (setf *acceptor* (make-instance 'hunchentoot:easy-acceptor :request-class 'custom-session-request))

The documentation states that the only requirements for replacing the session mechanism is implementations for hunchentoot:session-verify and hunchentoot:session-cookie-value specialised on the custom session class.

At a high level this is true but on a more practical level it omits some crucial information.

hunchentoot:session-cookie-value is specialised on the session class and it returns the value to be sent as a cookie to the user.

hunchentoot:session-verify returns the current session object associated with the current request. It specialises on the request rather than the session class, thus you also need a custom request class in addition to the session class.

Even with these two functions and classes implemented Hunchentoot will still not use your custom sessions. To achieve that you must instantiate the acceptor object with your custom request class as parameter.

These steps are sufficient to make Hunchentoot use a custom session class but it is still a long way from a working implementation, much less a secure one.

Replacing the session mechanism is not a trivial project. If you are forced down this path by the limitations of the built-in mechanism the easiest approach is to copy Hunchentoot’s session code and modify it to resolve your issue.