The place of Authentication in Domain Model

Not for 'how-to' coding questions but PHP theory instead, this forum is here for those of us who wish to learn about design aspects of programming with PHP.

Moderator: General Moderators

Post Reply
User avatar
Ambush Commander
DevNet Master
Posts: 3698
Joined: Mon Oct 25, 2004 9:29 pm
Location: New Jersey, US

The place of Authentication in Domain Model

Post by Ambush Commander »

You can skip this - these are my thoughts on the problem

In Front Controller (344) Fowler writes "In a complex Web site there are many similar things you need to do when handling a request. These things include security, internationalization, and providing particular views for certain users." The front controller, however, is for handling all requests to a web site, so stuck wondering where Authentication and Session management fit into the mix.

The most tricky thing is that certain domain objects and almost all templates must be aware who is currently logged in and what rights they have.

Previously, I put a "User" object inside the registry. This contained the username, userid, and userrights. Whenever it was needed, it was called from the Registry, and then the data it contained operated on. The thing was, when you determined the correct user to load, and whether or not the user was authenticated, and whether or not a session should be started, they where all stuck in Transaction style functions. No good for a Domain Model.

So, these are a different kind of object. They're not persisted in the database, and they do things that affect the presentation, but they still contain business logic.

Well, here we go:

Read here

authenticate() - You call this function and everything magically happens (including the user object getting registered)
login() / logout() / session() / remember() - These perform various authentication actions
assertLogin() / assertLogout() ... - This checks the environment and determines whether or not we should perform the actions (sorta like a Front Controller...)
validateLogin() / validateSession() - Determine whether or not the attempt by the user was correct: if not, then don't do the actual action
destroySession() - destroy a stale or logged out session
createSession() - create a new session
cacheSession() - send http headers to override PHP's no cache to "private"

How should I factor these functions into their own domain object classes?
User avatar
Maugrim_The_Reaper
DevNet Master
Posts: 2704
Joined: Tue Nov 02, 2004 5:43 am
Location: Ireland

Post by Maugrim_The_Reaper »

The front controller, however, is for handling all requests to a web site, so stuck wondering where Authentication and Session management fit into the mix.
It seems that both belong right at home in the Front Controller. I can't see any dedicated place to put them, unless you push the actual processes into their own distinct classes, and simply pass the relevant method call from the FC. The front controller as well as handling requests, and their mapping to the model layer, does allow centralisation of these once off "setup" like procedures.
The most tricky thing is that certain domain objects and almost all templates must be aware who is currently logged in and what rights they have.
And the problem is that what I stated as a solution breaks the separation by mixing DB calls, business logic, etc. into a single object? ;) Unfortunately I can't see any easy way around that. You could simply set up a session array to allow authentication status flags be passed freely among all layers. If you want to really make that technical you can call it State Data which is typically going to get used by a few layers anyway.

The greatest divorcement can be done using an Application Controller (which will use State to determine what actions are executed, and what Views are called upon). To be honest that seems overkill for handling a simple isLoggedin/notLoggedin decision. You could of course combine those authentication flags with some sort of ACL/Permission system which would operate directly in the Model/View layers... Either way this stuff is going to have to be shared between all layers...


Previously, I put a "User" object inside the registry. This contained the username, userid, and userrights. Whenever it was needed, it was called from the Registry, and then the data it contained operated on. The thing was, when you determined the correct user to load, and whether or not the user was authenticated, and whether or not a session should be started, they where all stuck in Transaction style functions. No good for a Domain Model.
Maybe divorce User Data from everything else? I would keep a separate User and UserACL class.

I could be reading you completely wrong, but I'd run a sequenced process.

1. Authenticate User (sets a Session/State flag)
2. Create User Object (just a data holder really) based on the selection of user details authenticated (id, name, pass) - id being obvious for a DB call.
3. Create an ACL class passing User as parameter
4. Register objects as required.

Both User and ACL would have separated Data Access classes. The Authenticate process would make a short DB call to grab the attempted login users name/pass and id. Full User data only collated after authentication. ACL sort of joins Authentication and Authorisation (permissions/rights) into one object to be passed to Model layer (of course Views may require them also - unless you set up all View variables in a Model object prior to calling the View, e.g. by using an intermediary ViewData or similar object...)
authenticate() - You call this function and everything magically happens (including the user object getting registered)
login() / logout() / session() / remember() - These perform various authentication actions
assertLogin() / assertLogout() ... - This checks the environment and determines whether or not we should perform the actions (sorta like a Front Controller...)
validateLogin() / validateSession() - Determine whether or not the attempt by the user was correct: if not, then don't do the actual action
destroySession() - destroy a stale or logged out session
createSession() - create a new session
cacheSession() - send http headers to override PHP's no cache to "private"
Nothing really "bad" with the above. Authentication, User, UserACL, SessionManagement, StateData and Response are all classes I could see factoring into.

Authentication: performs basic authentication, is passed the Request (login details - or filtered version thereof), and UserTemp (basic user details for authentication checks). It would return either void, or create a Session/State flag using StateData maybe.

User: After authentication is passed, the full User data can be fetched and object registered.

UserACL: fetch access rights data and register object. User as a parameter.

SessionManagement: basic session functions as noted perhaps.

StateData: a fancy name for a glorified sub-array, e.g. $_SESSION['_statedata']. Used for data which should be persisted across requests and specific to application flow. e.g. authentication flags.

Response: handles header/content/redirect setting (Front Controller should have final say in outputting everything). A Response object also allows centalised implementation of say output compression.


Actually, I think Authentication is Model layer, setup of ACL controller layer, and use of ACL model layer. I assume the FC would only validate the original Authentication, setup access rights, and allows individual actions (say Command objects) check user rights.
User avatar
Jenk
DevNet Master
Posts: 3587
Joined: Mon Sep 19, 2005 6:24 am
Location: London

Post by Jenk »

In my opinion, the front controller comes in two stages: the request handling and then any authentication, in that order.

Only because if the request does not require authentication (guest is probably best example) then there is no point authenticating. :)
User avatar
Maugrim_The_Reaper
DevNet Master
Posts: 2704
Joined: Tue Nov 02, 2004 5:43 am
Location: Ireland

Post by Maugrim_The_Reaper »

I agree on the order - but authentication checking is a single action process (a login), authorisation on the other hand is something done at the action level (checking user rights on all requests)...
Post Reply