By Peter Bell

Authentication of Method Calls without Session Scope

So, if we are designing a model API that doesn't require session state, where do we start? The starting point is to look at the controller API for an HTML controller and for a truly stateless controller and then figure out what would be the DRYest possible implementation . . .

In the past, my HTML controller had the concept of a SiteUser. I had a SiteUserService with the following fairly self explanatory code for getting the site user for a given user request:

<cffunction name="getSiteUser" returntype="any" hint="I return the correct site user for a given page request." output="false">
   <cfscript>
      var SiteUser = "";
      If (IsDefined("session.UserID"))
      {SiteUser = getByID(session.UserID);}
      Else
      {SiteUser = new();};
   </cfscript>
   <cfreturn SiteUser>
</cffunction>

Then the SiteUser object had methods like getCart() and isAuthenticated() that also keyed off of session and even cookie scopes. Every page request loaded SiteUser = SiteUserService.getSiteUser() into the page request bucket and things worked quite nicely. If you want to support calls that don't include session or cookie scope, things get a little more interesting.

For truly stateless calls, if there are any security or logging requirements (or any other requirements that require some kind of authentication of the identity of the requester), you either need to include security credentials in each call or a security token (such as an IP and time limited UUID security key) to avoid having to include authentication credentials in every single request.

There is also often the need to track "guest" user behavior to later associate to a given user, so if you go to a website, do a bunch of things and then log in, it has the capacity to associate those things to your user ID after the fact. For example, one way of implementing persistent shopping carts allows a guest user to build a cart (which is persisted in a database). The user then logs in and the cart (in the database) is now associated to their user ID. If they log in at a later time on another machine, they may have access to that cart (there are business decisions you need to make about which cart to show them if they have just started to create a new cart as a guest user before logging in - usually you give them the newest cart with contents as that will normally be the expected behavior).

So, what does this mean? Firstly it means that every model method call needs some kind of user identifier passed into it. Secondly it must support unique identification of guest users and thirdly there must be generalized support for identifying guest users across requests even if session scope is not available. The two obvious solutions are either to pass in a SecurityToken as a required parameter for every method call or to pass in the SiteUser itself.

I think on balance I like the flexibility of passing in a SiteUser as that allows me to completely vary my approaches to site user persistence without breaking my entire model API and secondly it means that if I want to encapsulate smart behaviors within the SiteUser I can do so easily enough.

So, I'm going to add SiteUser as a parameter to all of my model method signatures.

Thoughts?

Comments
BlogCFC was created by Raymond Camden. This blog is running version 5.005.