Authentication is the practice of checking that users are who they say they are. For example, motorists identify themselves to police by presenting a driver's license. Police compare the photo and description on the driver's license with the motorist to authenticate identity. All forms of authentication are based on something you know, something you have, or something you are.
An user claiming to be authenticated, need to present 2 things: An user's identity and a credential:
User identity is basically all the information that drives to identify an user.
i.e. The most typical user identity in a web application is the login or username. It also often used the email as user identity.
Credentials is all the information that help to bear out that the user is who he say he is.
i.e. The most typical user credential in a web application is the password, but it could be a digital sign, a smart card, ...
So, the user identity is a class implementing the __IUserIdentity while the credentials is a class implementing the __ICredentials.
Once the user has an user identity and a credential, he is able to call to the __AuthenticationManager in order to perform the logon
The __AuthenticationManager is not the one who will perform the authentication, but delegates in a set of classes implementing the __IAuthenticator.
The authentication process will finish once an authenticator has accept the authentication, it is, has check that the user is the one who he say he is.
Each __IAuthenticator gives both the user identity and the credential and perform the following tasks:
Call to the related user loader in order to load the user that corresponds with the given credentials
Once the user is loaded, the authenticator check that the provided credentials are the same that the loaded user has.
If the credential checking has success, the authenticator returns the user instance reference, otherwise it returns a null.
Once the first authenticator has return an user, the __AuthenticationManager stores the user as authenticated. This user can be retrieved whenever we want by calling to the __AuthenticationManager::getAuthenticatedUser() method.
In the other hand, the __AuthenticationManager delegates on the authenticated user in order to activate roles in the __UserSession instance. Remember that just the active roles will be the one used for authorization tasks.
Last step is to inform to the caller if the authentication has success. Simple: the __AuthenticationManager::logon() method is a boolean method, it is: true if the user has been authenticated.
Configuring the authentication
Authenticators can be configured declarativelly as well as the rest of the classes involved in the authentication. It can be done by modifying the app/config/context.xml file that allows to define instances and inject dependencies:
To read more information regarding dependency injection in Lion, please see the Lion.DependencyInjection.pkg section
In this example, we are defining an instance authenticationManager being from __AuthenticationManager class as well as setting just one authenticator.
The authenticator is the instance authenticator being from __Authenticator class. We are also setting the user loader as a reference to the userLoader instance.
Last, we are defining the userLoader as an instance of the __UserLoader class.
In this example, we are ussing classes out of the box, but it becomes pretty interesting when we can alter the configuration by adding our own implementations.
The most critical class here is the one implementing the __IUserLoader.
Why? this is the one which receives an user identity and load the corresponding user. So, it's the most sensible to be customized depending on the logic used to retrieve the user from.
Loading users
i.e. imagine a system where users are stored in a database and identified by logins. It's simple to understand that we need to provide our own class implementing the __IUserLoader.
In that sense, we need to create a class implementing the __IUserLoader and configure the authentication in order to use this class.
Let's see it in an example:
<?php
/**
* Our custom user loader, just a DAO implementing the
* __UserLoader.
*
*/
class UserDao implements __IUserLoader {
/**
* This method expects a __UsernameIdentity to retrieve
* the username and call to the model to get the user.
*
*/
public function &loadUser(__IUserIdentity $user_identity) {
In this example we are implementing the __IUserLoader by the class UserDao. This class exposes the loadUser method (implementing the one from __IUserLoader. This method expects a __UsernameIdentity instance as input argument.
Once it receives a __UsernameIdentity, it retrieves the username and delegates to the loadUserByUsername method.
This other method call to the database by performing a search by the primary key (the username).
Last, we have to define the user class created by the user loader. i.e.:
In this example, we have just extends the __User class by adding the setPassword method in order to store the expected credentials once the password has been setted.
Take into account that once the user is returned to the authenticator, the authenticator will get the user's credential in order to compare with the given one, so, let your user class returns the expected credentials to be compared to.
Now let's modify the app/config/context.xml in order to put our new class:
Since the user's permissions are checked taking into account just active roles stored in the __UserSession, it's not necessary to support the figure of the anonymous user in most of the Lion applications.
If case there are not authenticated users in session, the __UserSession won't have active roles and therefore any system resource requiring permissions won't be accessible.
However, some applications require to grant some permissions to anonymous users, i.e. to embed the login form in a page just if the user has a given permission.
To cover this kind of situations, Lion supports the anonymous figure and provide 2 special classes for that purpose: The __AnonymousIdentity and the __AnonymousCredentials representing the identity and credentials for anonymous users.
It's an authenticator task to distinguish between the anonymous authentication request and the regular authentication request in order to create an anonymous user or not.
Following with our previous example, let's update the UserDao class in order to support the anonymous user:
<?php
/**
* Our custom user loader, just a DAO implementing the
* __UserLoader.
*
*/
class UserDao implements __IUserLoader {
/**
* This method expects a __UsernameIdentity to retrieve
* the username and call to the model to get the user.
*
*/
public function &loadUser(__IUserIdentity $user_identity) {
The anonymous user will be claimed by authenticators if there is not any authenticated user in session. If an authenticator returns the anonymous user, the __AuthenticationManager will set it as the authenticated user and also activate his roles.