community.egroupware.org: Community wiki

  
Community wiki
Authentication

Authentication


The following is work in progress. Feel free to add questions and/or comments below the straight line at the bottom of the page or modify the content, in case you know better.

Overview: Basic steps in the authentication process


When a user visits the login page of an eGroupware site for the first time (no prior session etc.), the script login.php is called, the output runs through the templating system and the user sees the login form.

1.    The user fills out the form with his username and password. In a multi-domain installation, he chooses the domain he wants to connect to by selecting an etry in the dropdown box or by adding @domain to his username, depending on site configuration. When he clicks the submit button, the script logon.php is called again to process the request.

2.    In login.php, a call to function session->create of class session initiates session creation.

3.    In function session->create, a call to subroutine auth->authenticate of class auth and its specialized sub-class auth_* (for example, auth_sql) is executed.

4.    In case of successful authentication, function auth->authenticate returns true to session->create, false otherwise.

5.    Session->create returns a session-ID to script login.php.

6.    If no errors occured, login.php executes a redirect to index.php, thus transferring the authenticated user to the eGroupware homepage.

basics of the authentication process


These steps describe the simplest possible case, the successful authentication of a registered user. There are numerous special cases and variants which are not included in this description, for example:

  • session already existing
  • user or ip address blocked
  • user submits wrong password
  • user does not exist, maybe initiation of automatic account creation if so configured


The following chapter describes very roughly what is happening in the scripts that are concerned with the authentication process, as well as indicating the relevant code sections. The relevant scripts are

  • login.php
  • phpgwapi/inc/class.sessions.inc.php
  • phpgwapi/inc/class.auth.inc.php
  • phpgwapi/inc/class.auth_sql.inc.php (oder another, depending on the configured authentication method)
  • phpgwapi/inc/class.egw.inc.php

 

Walking through the authentication scripts

To better understand the following description, it is recommended to open the respective source code files and to search for the code pieces that are cited.


Starting point: the login form (as seen in the browser's "view source" window)

<form name="login_form" method="post" action="/egw_pilote/login.php">
	
	<input type="hidden" name="passwd_type" value="text" />
	<input type="hidden" name="account_type" value="u" />

	Domain: 	<select name="logindomain" > … </select>
	Username: 	<input name="login" />
	Password: 	<input name="passwd" type="password" onChange="this.form.submit()" />
 

	<input type="submit" value="Login" name="submitit" />

</form>
  • The form is submitted to login.php
  • The domain is transmitted either by choosing an item in the selectbox or by entering the username in the format user@domain, depending on the actual site configuration


Script login.php (processing form data)

Here's a rough description of what happens in the script:

  • some preliminary work on variables
  • authentication work starts after comment "Program starts here" (around line 85)
    • Test if auth-type == http, if so, do some work on variables
    • else
      • test if cookie-auth is activated, if so, do some work on variables
      • test if anonymous user login is activated, if so, do some work on variables
    • Test if auth-type == sql with ssl activation, if so, do some work on variables
    • Test if a submit has been transferred
      • if yes: Initiate session creation and authentication process. If authentication is successful, redirect user to egroupware homepage (and exit script login.php at this point)
      • else: do some work on variables in order to prepare a recall of login.php
    • Read GET-Parameters, in case there are some
    • recall login.php and let user have another try

Initiate session creation

  • Test if a submit has been sent (around line 153), if so
    • Test if the username already contains the domain name
      • if yes (user logged in with user@domain): do nothing
      • if no: read domain from POST-Variables and add it to login, so for all further steps, the variable login is in the form user@domain
    • Initiate session creation by calling session->create (around line 197) and go to script phpgwapi/inc/class.session.inc.php
if( isset( $passwd_type) || $_POST['submitit_x'] || $_POST['submitit_y'] || $submit )
{
	…

	$GLOBALS['sessionid'] = $GLOBALS['egw']->session->create( $login,$passwd,$passwd_type,'u');

}


Script phpgwapi/inc/class.sessions.inc.php with
class session

What basically happens in session->create :

  • some preliminary works
  • Test if there are reasons to deny access to eGroupware:
    • too many unsuccessful tries (login_blocked)
    • user blocked (global_denied_users)
    • unsuccessful authentication (at this point, the authentication subroutine auth->authenticate is called, which corresponds to step 3 of the authentication process outlined)
    • login with an egroupware group account (account_type == 'g') instead of a user account
    • if access must be denied:
      • return false, thus going back to login.php: authentication failure
    • if no access denial reason applies:
      • authentication was successful step 4 of overall process)
    • Test if the account already exists and if automatic account creation is activated, if yes, create acount
    • return session ID to login.php (step 5 of overall process)

 

/**
  • eGW's Session Management
  • Baseclass for db- and php-sessions
  • /
class sessions_ { … /** * Create a new session * * @param string $login user login * @param string $passwd user password * @param string $passwd_type type of password being used, ie plaintext, md5, sha1 * @return string session id */ function create($login,$passwd = ,$passwd_type = ) {


Test if access must be denied and initiate authentication
:

if (	$blocked = $this->login_blocked($login,$user_ip) ||       // too many unsuccessful attempts
$GLOBALS['egw_info']['server']['global_denied_users'][$this->account_lid] ||
!$GLOBALS['egw']->auth->authenticate($this->account_lid, $this->passwd, $this->passwd_type) ||
$this->account_id && $GLOBALS['egw']->accounts->get_type($this->account_id) == 'g')
{
$this->reason = $blocked ? 'blocked, too many attempts' : 'bad login or password';
$this->cd_reason = $blocked ? 99 : 5;
$this->log_access($this->reason,$login,$user_ip,0);
// log unsuccessfull login
return False;

}




If the script arrives at this point, authentication was successful (the return false has not been executed). Now automatic account creation can be initiated, and after that, the session ID is returned to login.php.

if (	!$this->account_id && $GLOBALS['egw_info']['server']['auto_create_acct'])
	{
		… 
		$this->account_id = 
		$GLOBALS['egw']->accounts->auto_add($this->account_lid, $passwd);
	}
	… 

return $this->sessionid;
}


Scripts phpgwapi/inc/class.auth.inc.php and class.auth_sql.inc.php with classes auth und auth_sql

What roughly happens in the scripts:

  • Script auth includes auth_sql which is the special class file for the configured authentication method
  • the authentication method of  the special class is called and executed
  • in case of successful authentication, true is returnd to session->create (Step 4 of the overall process)
if(empty($GLOBALS['egw_info']['server']['auth_type']))
{
$GLOBALS['egw_info']['server']['auth_type'] = 'sql';
}
include( EGW_API_INC.'/class.auth_'.$GLOBALS['egw_info']['server']['auth_type'].'.inc.php');


class auth extends auth_



Now continuing in script auth_sql:

class auth_
{
var $db = '';
var $previous_login = -1;

function auth_()
{

}

/**
* password authentication against password stored in sql datababse
*
* @param string $username username of account to authenticate
* @param string $passwd corresponding password
* @param string $passwd_type='text' 'text' for cleartext passwords (default)
* @return boolean true if successfully authenticated, false otherwise
*/

function authenticate($username, $passwd, $passwd_type='text')
{
/* normal web form login */
if($passwd_type == 'text')
{



// if this point is reached, auth was successfull
$this->previous_login = $this->db->f('account_lastlogin');

return true;
}

}





Script login.php with initiation of redirect to eGroupware homepage


Execution continues in script login.php:

  • find target to which the successfully authenticated user will be transferred
  • call to redirect function


Find target for redirect:

$forward = isset($_GET['phpgw_forward']) ? urldecode($_GET['phpgw_forward']) : @$_POST['phpgw_forward'];
if (!$forward)
{
$extra_vars['cd'] = 'yes';
if($GLOBALS['egw']->hooks->single('hasUpdates', 'home'))
{
$extra_vars['hasupdates'] = 'yes';
}
$forward = '/index.php';
}
else
{
list($forward,$extra_vars) = explode('?',$forward,2);

}



Initiate redirect:

// Check for safe passwd
if( $GLOBALS['egw_info']['server']['check_save_passwd']
&& $GLOBALS['egw']->acl->check('changepassword', 1, 'preferences')
&& $unsave_msg = $GLOBALS['egw']->auth->crackcheck($passwd))
{

...
$GLOBALS['egw']->redirect_link( '/index.php', array( 'menuaction' => 'preferences.uipassword.change',
'message' => $message. $unsave_msg. '</font>'));
}
else
{

$GLOBALS['egw']->redirect_link($forward,$extra_vars);




Script phpgwapi/inc/class.egw.inc.php with execution of redirect

redirect_link calls subroutine redirect, which redirects by sending a header-location-directive (step 6 in the overall process):

function redirect_link($url = ,$extravars=)
{
	$this->redirect($this->session->link($url, $extravars));
}


/**
  • Handles redirects under iis and apache, it does NOT return (calls exit)
  • @param string The url ro redirect to
  • /
function redirect($url = '') { /* global $HTTP_ENV_VARS; */ $iis = @strpos($GLOBALS['HTTP_ENV_VARS']['SERVER_SOFTWARE'], 'IIS', 0); if(!$url) { $url = $_SERVER['PHP_SELF']; } if($iis) { echo "\n<HTML>\n<HEAD>\n<TITLE>Redirecting to $url</TITLE>"; echo "\n<META HTTP-EQUIV=REFRESH CONTENT=\"0; URL=$url\">"; echo "\n</HEAD><BODY>"; echo "<H3>Please continue to <a href=\"$url\">this page</a></H3>"; echo "\n</BODY></HTML>"; } else { Header("Location: $url"); print("\n\n"); } exit; }



Comments, Questions

See also : CasAuthentication for CAS SSO

 


Back to DeveloperDocs



You are here