Sorry, I wasn't clear enough. If we decide to tuck away important info in the AuthenticationManager (as we did for the authentication status), the rest of the application needs to be able to access the manager during the entire request. Of course, we could assume that the application doesn't need that extra info if they're using authtools_quick_authorize(). Choices, choices.
I don't mind the manager being recreated each request.
I'll take it a step further: it
should be recreated each request. This is because the session itself is an authentication factor, so if you bind it to the session, you've got something somewhat cyclical.
Plus, Santosj brings valid points about the classes the manager will have references to. No. Only store persistent data. If necessary, we can create an AuthTools_ManagerCache object.
I am not sure I understand this, but mainly because terminology for this stuff is so unspecific. Authenication, to me, is checking credentials provided by the user again a know datasource. The datasource obviously stores data, and the credentials are only stored for the current request.
Right. However, even though the session is created from a valid username/password, it doesn't know about the username/password. While the two are connected, they're also seperate bits of authentication. So the datasource to check credentials from a session from would be... the session itself (which is automatically initialized).
After Authentication we then need to allow/deny access on a request by request basis. The application will define the requirements to allow access for a specific request. It will then check to see if the user meets those requirements. In most small to medium PHP applications with simple Access Control -- which is the bulk of them -- it probably makes sense to cache some or all of the pertinent user's data in the session. That data would be valid until the user logged-out or the sesson expired. In more complex systems the session adapter would fetch the data from a datasource each request, but that is really application dependent as this system does not really care where the data comes from. It sounds like we are going to implement some Best Practices code for common types of implementations.
Personally, I think that grabbing the access information each request from the database is the cleanest way to go about doing things, if only because there's no easy way to invalidate data in a session except by just letting it expire. Suppose you had time-based authorization: if a session extends past the end point of the authorization, the session will still think the user is authorized, while in reality it isn't.
As object (like all vars) are automatically serialized by the session manager before being saved. I guess the reason you would want to serialize an object is so that you could manually include the class before unserializing it (but after starting the session). The autoload function can handle that -- unfortunately you can have only one autoload currently. If we wanted to have our own loader we could serialize I suppose. I think it is really an application decision though, so we should push the responsiblity out to the app. This also provides implementation flexiblity.
It's a bit of a pickle, I agree. There's a php.ini configuration that automatically initializes sessions: if that's the case, you plain flat out CANNOT put objects inside the session without __autoload(). Default setting, if we DO need a CachedAuthenticationManager, should be to serialize it and store it. The session adapter should make this transparent, so we're not actually ever directly interfacing with the superglobal $_SESSION.
This is what I meant:
Code: Select all
<?php
// no access control built in!
// returns whether or not a user is authenticated,
// and registers AuthenticationManager to appropriate persistence if they are.
function authtools_quick_authenticate(
$data_adapter = false, // false to use the automatic classes
$session_adapter = false,
$credential_adapter = false,
$global_adapter = false)
{
$manager = new AuthTools_AuthenticationManager();
// give the credentials AuthenticationManager (nothing happens yet)
if (!$credential_adapter) $credentials = new AuthTools_Credentials_Auto();
$manager->setCredentials($credentials);
// likewise we need some to check the credentials against (nothing happens)
// the automatic detection is NOT recommended
if (!$data_adapter) $data_adapter = new AuthTools_Datasource_AutoMySQL();
$manager->setDataAdapter($data_adapter);
// give the session to the authentication manager. Even though parts
// of the session count as credentials, the manager also has write
// access to the session, making it special.
if (!$session_adapter) $session_adapter = new AuthTools_Session_Auto();
$manager->setSessionAdapter($session_adapter);
// the user gets authenticated.
// authenticateUser optionally takes a specific authentication command,
// otherwise, it passes the credentials to a controller which determines
// which methods should the user be authenticated by
$manager->authenticateUser();
// propagate the authentication manager. This gives the app a dependency,
// but it should be trivial to write wrappers for the most important
// methods: isUserAuthenticated() and getUserId()
$global_adapter->registerAuthenticationManager($manager);
// for small scripts that don't want to interface with the manager
return $manager->isUserAuthenticated();
}
?>
No support for caching the authentication manager, because that's how I think it should be.