Chapter: jAuth : authentication system
« jUrl: automatic urls | ^ Jelix components | jAcl2 : rights management » |
− Table of content
The Jelix authentication system handles only one thing: logins, passwords, and users.
Relying on drivers to access user data, you can use a database, a LDAP directory, or any other way to access data. As for now, there is a database driver, an LDS directory based driver, an LDAP directory based driver, and a driver for an external class.
The authentication system relies on several things :
- a plugin for the jelix coordinator,
auth
, verifying if authentication is done for the actions when it is necessary - a
jAuth
class, allowing to do different operations on authentication and logins handling. This class implements a driver system. - a
jauth
module offering a controller and some default templates. It is not mandatory and you can define your own authentication module. - a session object, containing information about the user. It is provided by the driver. This can be a DAO object, a simple class, and so on.
To use the authentication system, you must install at least the plugin for the jelix coordinator, and configure it.
The role of the Auth plugin:
- Check authentication
- Control session timeout (optional)
- Control authentication persistance (optional)
- Specify which driver to use
- Specify parameters for the driver (dao for jAuthDb, cn/sn/uid for ldap driver etc)
- Indicates what to do if not authenticated
Plugin installation ¶
To activate it, if you want to use ressources of the module jauth
(controllers, zones...), install the module, else install the plugin by hand.
By installing the module jauth ¶
Use the command installmodule of jelix to install the module :
$ cd lib/jelix-scripts/
$ php jelix.php --myapp installmodule jauth
It will activate the module, and create a new file var/config/index/auth.coord.ini.php
, which is the configuration of the plugin auth
.
By hand ¶
Copy the file lib/jelix-modules/jauth/install/var/config/auth.coord.ini/php
into the configuration directory of your entry point, for instance var/config/index/auth.coord.ini.php
.
You should then add this line to "coordplugins"" section of your application configuration file:
[coordplugins]
auth = "index/auth.coord.ini.php"
You can learn more about plugins here.
Authentication core configuration ¶
To configure the authentication system, edit the file var/config/index/auth.coord.ini.php
.
Selecting a driver ¶
You must assign the driver
option with a driver name and fill a section containing the driver parameters.
Read the jAuth drivers documentation to know which driver you can use and how to activate it.
Function to hash password ¶
Since Jelix 1.2.10 (and 1.3.4, 1.4.1), there are two hashing system to hash your password in the storage. Jelix 1.2.10 and higher provide indeed a more secured method, using the new password API of PHP 5.5. A pure PHP implementation is provided in Jelix to use this API in previous PHP version.
Old hashing system ¶
By default, the function to hash password is sha1
, (in jelix 1.1
and lower, it was md5
) but it's possible to use an other function which
accepts a string in parameter, and returns the corresponding hashed string.
Note that nowadays, sha1
and md5
are not considered secured
because of the power of computers. If possible use better hashing methods
like provided by the new hashing system of Jelix 1.2.10.
To indicate the hash function, indicates its name into the password_crypt_function
option, in the section of the driver.
The function could accepts other parameters, like a salt value. To indicates that the function accepts other parameters, you should precede the function name by a number and a ":":
- "1:functionname": the function accepts a salt value as first parameter, and the string to encrypt as second parameter. The salt value should be filled into the
password_salt
option - "2:functionname": the function name accepts an array containing all options of the driver section, and the string to encrypt as second parameter. So the function can deal with any options stored in the configuration.
To create your own function, you can write it into its own php file, and include it into the application.init.php
file of your application.
Here is an example to use the sha1
php function with a salt value. Here is the function (this function is already available in jelix and declared with the plugin):
function sha1WithSalt($salt, $password) {
return sha1($salt.':'.$password);
}
In the configuration of the plugin:
driver=Db
[Db]
dao = "mon_dao"
password_crypt_function = "1:sha1WithSalt"
password_salt = "here_your_salt_value"
New hashing system ¶
This system is provided since Jelix 1.2.10/1.3.4/1.4.1 and use a new PHP 5.5 API. It uses
by default the bcrypt method. A similar API is provided by Jelix to use it in
PHP 5.4 or PHP 5.3. Since it uses the crypt
function with bcrypt, you
should use at least PHP 5.3.7 (or PHP 5.3.3 on an updated Debian Squeeze box).
The configuration is simple. You should have to parameters in the global section
of the jauth configuration (so outside sections like [Db]
):
password_hash_method
: indicates the hash method to use. Only one is possible for the moment, BCRYPT. You should then set it to "1". It the value is "0" or empty, the new hashing system is not used.password_hash_options
: a string containing a list of "key=value;". These are options depends of the hash method. For BCRYPT, you have a "salt" and a "cost" option (But it is recommended to use default values, so to leavepassword_hash_options
empty).
The new hashing system always generates a random salt for each stored password
(unless you indicate one in password_hash_options
, but it is less secure).
And the salt is stored with the password, this is why you need a bigger password
field in your database, than the old hashing system.
Migration ¶
If you want to upgrade an existing application to Jelix 1.2.10/1.3.4/1.4.1, and you would like to use the new hashing system, you should:
- enlarge the password field (
password
) in your database, to 120 characters - modify the corresponding DAO (if you don't use jelixuser of jauthdb module), to indicate this new size.
- set the configuration with
password_hash_method=1
Each user who will authenticate itself, the hash generated with the old
hashing system will be replaced by a new hash. This is why you should
keep the values of password_crypt_function
and password_salt
,
else users couldn't authenticate themselves.
- *Warning: Do not do this migration with a shared database**, used by several application in wich the migration has not been done. Users could not be authenticated, since new hash password are not compatible with the old hashing system (and vice-versa). And you could not return to the old hashing system, unless you made database backup.
- *Do a backup of the user table before the migration**.
Timeout ¶
timeout
option indicates inactivity duration to invalid authentication. Its unit is minutes. If you set it to 0
, there is no timeout. And the authentication session will live throughout the browser session.
Control authentication in each action ¶
Each action can declare if it needs an authentication. It is done through authentication plugin api.
If all actions needs an authentication then just set auth_required
to on
in auth.config.ini.php
file. Whereas an off
specifies the contrary.
auth_required=on
In any case, you'll certainly have to deal with exceptions. Imagine you have an home page which doesn't need authentication but every other page requires one. Those exceptions are declared in controllers using auth plugin parameters.
Example:
class xxxCtrl extends jController {
public $pluginParams = array(
'*'=>array('auth.required'=>true),
'index'=>array('auth.required'=>false)
);
}
Here the auth plugin is configured to check for authentication in every action of this controller (*
rule) except for index
action (possibly your home page).
On the contrary, you can tell auth plugin to check for authentication only for some actions such as index
and secret
. See below:
class xxxCtrl extends jController {
public $pluginParams = array(
'*'=>array('auth.required'=>false),
'index'=>array('auth.required'=>true),
'secret'=>array('auth.required'=>true),
);
}
See coordinator plugins documentation for an in-depth view of $pluginParams usage (remember that auth plugin is a coordinator plugin).
Application behavior if authentication does not succeed ¶
If authentication does not succeed and current action needs it, auth plugin reacts regarding to on_error
option value.
If on_error=1
, auth plugin will generate an error message configured by error_message
option.
If on_error=2
, auth plugin will execute action selected by on_error_action
option. It can be a controller action of auth module (default case) or any action of any other module. Basically this action will ask for login/password couple but you can imagine other scenario.
Authentication persistence ¶
jAuth offers a way to create authentication persistence. In other words, a user will authenticate once and on every other visits, he will be automatically authenticated. This is done by a cookie which stores some user information. Even a part of them are encrypted.
To configure persistence use the parameters below:
persistant_enable
: set it toon
to activate authentication persistencepersistant_crypt_key
: this one is mandatory. You must replace its default value ! It is a string composed of arbitrary chars (its length should over 10). It will be used as an encrypt key for cookie datas. If you change key value, be aware that all users will have to re-authenticate to benefit of persistence.
Other less important parameters:
persistant_cookie_name
: cookie name. Default :"jelixAuthentificationCookie"
.persistant_duration
: validity time (in days) of persistence. Default is one day.persistant_cookie_path
: cookie path. Default empty : cookie will be stored with basePath general config value.
jAuth module: default controllers ¶
The jAuth module implements generic controllers. You can use them to control login, logout step. Alternatively, jAuth module offers also zones and templates. The latter is useful if you need to add login/logout option to one or more of your own controllers.
If you want other features, like registering and clearing account forms, changing passwords or lost password forms, you may use the jcommunity module. See jCommunity.
Classic configuration ¶
When using the jAuth module, one can add/modify options to suit his neeeds.
An example of auth.plugin.ini.php
file:
on_error_action = "jauth~login:out"
after_login = "myapp~default:index"
after_logout = "jauth~login:form"
on_error_sleep = 3
The parameter on_error_sleep
defines defines a duration. This is the amount of time in seconds, where authentication form is inactivated if user has not succeeded it. after_login
and after_logout
, watch below.
Templates of the module jAuth can be easily customized if you overload them. Just copy and edit them in var/themes/default/jauth/
. More on overloading here.
Redirection options ¶
Auth plugin defines a bunch of config options to specify redirections on login/logout steps, used by the jauth module.
after_login
(required): action selector. effective redirection if login succeedsafter_logout
(required): action selector. effective redirection if logout succeedsenable_after_login_override
(optional):on
oroff
. flag for exceptional redirections after loginenable_after_logout_override
(optional):on
oroff
. flag for exceptional redirections after logout
Exceptions : In a case where you don't want a login step to end up in the action selected by after_login
parameter, you'll have to put an hidden auth_url_return
parameter in your login form. It will contain an url, the one you want the user to be redirected to. This only works if enable_after_login_override
is set to on
.
Of course, same apply to logout step and enable_after_logout_override
.
Setup of URLS significants ¶
if you use the significant urls engine, you will have to add in the file
var/config/urls.xml
the line
<url pathinfo="/auth" module="jauth" include="urls.xml"/>
to get the urls dedicated to the module.
Using your own controller ¶
Authentication can be done using your own controllers of course. You'll have to dive in jAuth API et call its static methods to check users login/password, and connect or disconnect them.
In this case, of course, you may not install the jauth module...
jAuth class ¶
jAuth
is the main class for authentication. All its methods are static. It manages users, connect or disconnect them. Its methods must be called to authenticate either by jAuth module or in your own controllers. Read its reference description.
Some methods needs a user object as an argument. jAuth
itself provides it to you. It contains user datas and has no defined class. Its type depends on the driver used. (In a Db driver, users object and datas will certainly be structured by a DAO). The only requirement on this user object is that it must have a login
and a password
field.
jAuth shouldn't be derived from. Its driver based system should cover all authentication formats.
Connecting / Disconnecting a user ¶
To login/logout a user, you should call the methods login()
et logout()
:
// login
$ok = jAuth::login('the_login', 'the_password');
// logout
jAuth::logout();
After calling login()
and if this is a success, jAuth stores some informations about the user in the session. These informations are in an object, that you can retrieve with getUserSession()
:
$user = jAuth::getUserSession();
The class of this object depends of the driver. For the "db" driver, this will be a DAO record, from the DAO indicated in the configuration of jAuth.
You can know if a user is connected with the method isConnected()
:
if (jAuth::isConnected()) {
// ok, a user is connected
}
To login the user in a persistant manner (he will be recognized automatically when he go on your application, even if his session has been destroyed),
you have to add the true
value as third parameter, when calling the login()
method.
You can also just verify a login/password, without "connecting" a user :
$ok = jAuth::verifyPassword('the_login', 'the_password');
Read the reference documentation of jAuth to know about other methods.
Creating a user ¶
To manage user, you have to call jAuth too. To create a user, you need to retrieve an object for the new user, to fill it with some informations if needed, then to ask jAuth to save it.
// retrieve a new object for the new user
$newUser = jAuth::createUserObject ('the_login', 'the_password');
//add some information, for example the birthday date.
$newUser->birthday = '1980-01-01';
// let's register the new user
$ok = jAuth:saveNewUser($newUser);
Modifying a user ¶
To modify informations of a user, you have to retrieve the object corresponding to the user, to modify it, then to ask jAuth to save it.
$user = jAuth::getUserSession()
// or
$user = jAuth::getUser('his_login');
// modification example
$user->birthday = '1980-01-02';
// save
jAuth::updateUser($user);
Notice: if the modified user is the current connected user, then informations in sessions are also updated.
Don't use this process to modify the password! Because you don't really know how the password is encrypted, or how it is stored. It depends of the jAuth configuration and of the driver. So, to change the password, use the method changePassword()
:
jAuth::changePassword('the_login', 'the_new_password');
You can use the method jAuth::getRandomPassword()
to generate a random password.
Other methods ¶
To delete a user, use jAuth::removeUser()
:
jAuth::removeUser('his_login');
To retrieve a list of users, use jAuth::getUserList()
:
$list = jAuth::getUserList();
The result is an iterator over a list of objects, each objects representing a user (like the object you retrieve with getUser()
).
Events ¶
About every jAuth
methods emit events. As a result, modules can be aware of authentication status and do some specific action related to user.
- AuthNewUser : a new user has been created
- AuthCanRemoveUser : ask if deletion of a user is allowed
- AuthRemoveUser : a user has been removed
- AuthUpdateUser : current user has been updated
- AuthCanLogin : ask if user can connect
- AuthLogin : a user has logged in
- AuthLogout : a user has logged out
- AuthErrorLogin : a user authentication has failed
- AuthBeforeLogin : apply some process before a user authentication