/**
* Login authentication function.
*
* Username and encoded password are passed the onUserLogin event which
* is responsible for the user validation. A successful validation updates
* the current session record with the user's details.
*
* Username and encoded password are sent as credentials (along with other
* possibilities) to each observer (authentication plugin) for user
* validation. Successful validation will update the current session with
* the user details.
*
* @param array $credentials Array('username' => string, 'password' => string)
* @param array $options Array('remember' => boolean)
*
* @return boolean|\Exception True on success, false if failed or silent handling is configured, or a \Exception object on authentication error.
*
* @since 3.2
*/
public function login($credentials, $options = array())
{
// Get the global Authentication object.
$authenticate = Authentication::getInstance($this->authenticationPluginType);
$response = $authenticate->authenticate($credentials, $options);
// Import the user plugin group.
PluginHelper::importPlugin('user');
if ($response->status === Authentication::STATUS_SUCCESS) {
/*
* Validate that the user should be able to login (different to being authenticated).
* This permits authentication plugins blocking the user.
*/
$authorisations = $authenticate->authorise($response, $options);
$denied_states = Authentication::STATUS_EXPIRED | Authentication::STATUS_DENIED;
foreach ($authorisations as $authorisation) {
if ((int) $authorisation->status & $denied_states) {
// Trigger onUserAuthorisationFailure Event.
$this->triggerEvent('onUserAuthorisationFailure', array((array) $authorisation));
// If silent is set, just return false.
if (isset($options['silent']) && $options['silent']) {
return false;
}
// Return the error.
switch ($authorisation->status) {
case Authentication::STATUS_EXPIRED:
Factory::getApplication()->enqueueMessage(Text::_('JLIB_LOGIN_EXPIRED'), 'error');
return false;
case Authentication::STATUS_DENIED:
Factory::getApplication()->enqueueMessage(Text::_('JLIB_LOGIN_DENIED'), 'error');
return false;
default:
Factory::getApplication()->enqueueMessage(Text::_('JLIB_LOGIN_AUTHORISATION'), 'error');
return false;
}
}
}
// OK, the credentials are authenticated and user is authorised. Let's fire the onLogin event.
$results = $this->triggerEvent('onUserLogin', array((array) $response, $options));
/*
* If any of the user plugins did not successfully complete the login routine
* then the whole method fails.
*
* Any errors raised should be done in the plugin as this provides the ability
* to provide much more information about why the routine may have failed.
*/
$user = Factory::getUser();
if ($response->type === 'Cookie') {
$user->set('cookieLogin', true);
}
if (\in_array(false, $results, true) == false) {
$options['user'] = $user;
$options['responseType'] = $response->type;
// The user is successfully logged in. Run the after login events
$this->triggerEvent('onUserAfterLogin', array($options));
return true;
}
}
// Trigger onUserLoginFailure Event.
$this->triggerEvent('onUserLoginFailure', array((array) $response));
// If silent is set, just return false.
if (isset($options['silent']) && $options['silent']) {
return false;
}
// If status is success, any error will have been raised by the user plugin
if ($response->status !== Authentication::STATUS_SUCCESS) {
$this->getLogger()->warning($response->error_message, array('category' => 'jerror'));
}
return false;
}