Zeta Components - high quality PHP components

eZ Components - AuthenticationDatabaseTiein

Introduction

Description

The purpose of the Authentication component is to provide support for different means of identification and authentication of users using different providers and protocols.

AuthenticationDatabaseTiein provides a Database filter for the Authentication component by using the Database component, and an implementation of a database store (backend) for OpenID authentication.

Class overview

An overview of the most important classes in the Authentication component and this component.

Base classes

ezcAuthentication
Main class of Authentication. It is a container for authentication filters, which will be run in sequence. The method run() returns true or false depending on the success of the authentication filters. Implemented in Authentication.
ezcAuthenticationCredentials
Structure which holds user credentials. Types are id credentials (ezcAuthenticationIdCredentials) and id + password credentials (ezcAuthenticationPasswordCredentials). Implemented in Authentication.

Authentication filters

ezcAuthenticationDatabaseFilter
Filter to authenticate against a database. Uses a database instance provided by the Database component (via the ezcDbInstance::get() function).

Stores

OpenID uses a store to hold the generated nonces and the associations (in "smart" mode). If there is no store specified, then nonces are not checked.

ezcAuthenticationOpenidStore
Abstract class from which the different stores inherit. Implemented in Authentication.
ezcAuthenticationOpenidFileStore
Uses file storage. Nonces are stored in files named after the nonce itself, and associations are stored in files named after the OpenID provider with which the association is made. Implemented in Authentication.
ezcAuthenticationOpenidDbStore
Database storage. Nonces and associations are stored in two tables, with names defined as options in ezcAuthenticationOpenidDbStoreOptions.

Authentication filters

Database

The following example shows how to authenticate against a database.

  1. <?php
  2. require_once 'tutorial_autoload.php';
  3. $credentials = new ezcAuthenticationPasswordCredentials'jan.modaal''b1b3773a05c0ed0176787a4f1574ff0075f7521e' );
  4. $database = new ezcAuthenticationDatabaseInfoezcDbInstance::get(), 'users', array( 'user''password' ) );
  5. $authentication = new ezcAuthentication$credentials );
  6. $authentication->addFilter( new ezcAuthenticationDatabaseFilter$database ) );
  7. if ( !$authentication->run() )
  8. {
  9.     // authentication did not succeed, so inform the user
  10.     $status $authentication->getStatus();
  11.     $err = array(
  12.              'ezcAuthenticationDatabaseFilter=> array(
  13.                  ezcAuthenticationDatabaseFilter::STATUS_USERNAME_INCORRECT => 'Incorrect username',
  14.                  ezcAuthenticationDatabaseFilter::STATUS_PASSWORD_INCORRECT => 'Incorrect password'
  15.                  )
  16.              );
  17.     foreach ( $status as $line )
  18.     {
  19.         list( $key$value ) = each$line );
  20.         echo $err[$key][$value] . "\n";
  21.     }
  22. }
  23. else
  24. {
  25.     // authentication succeeded, so allow the user to see his content
  26. }
  27. ?>

First, a credentials object is created with username jan.modaal and password 'b1b3773a05c0ed0176787a4f1574ff0075f7521e' (sha1() hash).

An authentication object is created using the credentials object, and a Database filter is added to it. The $database structure specifies the database instance (ezcDbInstance::get()), the table name ('users') and the username and password fields in the table ('user', 'password').

After running the authentication (line 8), if the username and the password do not pass through the Database filter, then the credentials are incorrect and the user must be informed. The getStatus() method is used for this. The values in the status returned must be cycled through and for each value a response is created for the user ("Username incorrect", "Password incorrect").

If run() returned true (line 24) then the user is logged-in and he can see his content.

Fetch extra data during Database authentication

Any value from the table which holds the users can be fetched. The exact column names must be specified. Example:

// $filter is an ezcAuthenticationDatabaseFilter object $filter->registerFetchData( array( 'name', 'country' ) );

After the authentication process is finished (after run()), retrieve the extra data:

// $filter is an ezcAuthenticationDatabaseFilter object $data = $filter->fetchData();

For the previous example, the $data array will be something like this:

array( 'name' => array( 'John Doe' ), 'country' => array( 'US' ) );

OpenID

OpenID "smart" (stateful) mode

The following example shows how to authenticate against OpenID in "smart" (stateful) mode, using a database store.

  1. <?php
  2. require_once 'tutorial_autoload.php';
  3. // no headers should be sent before calling $session->start()
  4. $session = new ezcAuthenticationSession();
  5. $session->start();
  6. $url = isset( $_GET['openid_identifier'] ) ? $_GET['openid_identifier'] : $session->load();
  7. $action = isset( $_GET['action'] ) ? strtolower$_GET['action'] ) : null;
  8. $credentials = new ezcAuthenticationIdCredentials$url );
  9. $authentication = new ezcAuthentication$credentials );
  10. $authentication->session $session;
  11. if ( $action === 'logout' )
  12. {
  13.     $session->destroy();
  14. }
  15. else
  16. {
  17.     $options = new ezcAuthenticationOpenidOptions();
  18.     $options->mode ezcAuthenticationOpenidFilter::MODE_SMART;
  19.     // define a database store by specifying a database instance
  20.     $options->store = new ezcAuthenticationOpenidDbStoreezcDbInstance::get() );
  21.     $filter = new ezcAuthenticationOpenidFilter$options );
  22.     $authentication->addFilter$filter );
  23. }
  24. if ( !$authentication->run() )
  25. {
  26.     // authentication did not succeed, so inform the user
  27.     $status $authentication->getStatus();
  28.     $err = array(
  29.              'ezcAuthenticationOpenidFilter=> array(
  30.                  ezcAuthenticationOpenidFilter::STATUS_SIGNATURE_INCORRECT => 'OpenID said the provided identifier was incorrect',
  31.                  ezcAuthenticationOpenidFilter::STATUS_CANCELLED => 'The OpenID authentication was cancelled',
  32.                  ezcAuthenticationOpenidFilter::STATUS_URL_INCORRECT => 'The identifier you provided is invalid'
  33.                  ),
  34.              'ezcAuthenticationSession=> array(
  35.                  ezcAuthenticationSession::STATUS_EMPTY => '',
  36.                  ezcAuthenticationSession::STATUS_EXPIRED => 'Session expired'
  37.                  )
  38.              );
  39.     foreach ( $status as $line )
  40.     {
  41.         list( $key$value ) = each$line );
  42.         echo $err[$key][$value] . "\n";
  43.     }
  44. ?>
  45. Please login with your OpenID identifier (an URL, eg. www.example.com or http://www.example.com):
  46. <form method="GET" action="">
  47. <input type="hidden" name="action" value="login" />
  48. <img src="http://openid.net/login-bg.gif" /> <input type="text" name="openid_identifier" />
  49. <input type="submit" value="Login" />
  50. </form>
  51. <?php
  52. }
  53. else
  54. {
  55. ?>
  56. You are logged-in as <b><?php echo $url?></b> | <a href="?action=logout">Logout</a>
  57. <?php
  58. }
  59. ?>

A database store is defined at line 25. This store will also hold the nonces which are used to prevent replay attacks.

The database store requires that certain tables are present in the database. To load the .dba definition for these tables into your database you must have the DatabaseSchema component installed. Use the following code to load the schema:

  1. <?php
  2. require_once 'tutorial_autoload.php';
  3. $db ezcDbInstance::get(); // replace if you get your database instance differently
  4. $schema ezcDbSchema::createFromFile'array''openid_db_store_schema.dba' );
  5. $schema->writeToDb$db );
  6. ?>

Securing applications

Securing applications - A guide to improve the security of online applications. It is not exhaustive, but it provides solutions against common attacks.