Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 19 additions & 5 deletions plugins/api-authentication/basic/src/Extension/Basic.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@
namespace Joomla\Plugin\ApiAuthentication\Basic\Extension;

use Joomla\CMS\Authentication\Authentication;
use Joomla\CMS\Event\User\AuthenticationEvent;
use Joomla\CMS\Plugin\CMSPlugin;
use Joomla\CMS\User\UserFactoryAwareTrait;
use Joomla\CMS\User\UserHelper;
use Joomla\Database\DatabaseAwareTrait;
use Joomla\Event\SubscriberInterface;

// phpcs:disable PSR1.Files.SideEffects
\defined('_JEXEC') or die;
Expand All @@ -25,24 +27,36 @@
*
* @since 4.0.0
*/
final class Basic extends CMSPlugin
final class Basic extends CMSPlugin implements SubscriberInterface
{
use DatabaseAwareTrait;
use UserFactoryAwareTrait;

/**
* Returns an array of events this subscriber will listen to.
*
* @return array
*
* @since __DEPLOY_VERSION__
*/
public static function getSubscribedEvents(): array
{
return ['onUserAuthenticate' => 'onUserAuthenticate'];
}

/**
* This method should handle any authentication and report back to the subject
*
* @param array $credentials Array holding the user credentials
* @param array $options Array of extra options
* @param object &$response Authentication response object
* @param AuthenticationEvent $event Authentication event
*
* @return void
*
* @since 4.0.0
*/
public function onUserAuthenticate($credentials, $options, &$response)
public function onUserAuthenticate(AuthenticationEvent $event): void
{
$response = $event->getAuthenticationResponse();

$response->type = 'Basic';

$username = $this->getApplication()->getInput()->server->get('PHP_AUTH_USER', '', 'USERNAME');
Expand Down
90 changes: 56 additions & 34 deletions plugins/authentication/cookie/src/Extension/Cookie.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,18 @@
namespace Joomla\Plugin\Authentication\Cookie\Extension;

use Joomla\CMS\Authentication\Authentication;
use Joomla\CMS\Event\Privacy\CollectCapabilitiesEvent;
use Joomla\CMS\Event\User\AfterLoginEvent;
use Joomla\CMS\Event\User\AfterLogoutEvent;
use Joomla\CMS\Event\User\AuthenticationEvent;
use Joomla\CMS\Filter\InputFilter;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Log\Log;
use Joomla\CMS\Plugin\CMSPlugin;
use Joomla\CMS\User\UserFactoryAwareTrait;
use Joomla\CMS\User\UserHelper;
use Joomla\Database\DatabaseAwareTrait;
use Joomla\Event\SubscriberInterface;

// phpcs:disable PSR1.Files.SideEffects
\defined('_JEXEC') or die;
Expand All @@ -30,47 +35,62 @@
* @note Code based on http://jaspan.com/improved_persistent_login_cookie_best_practice
* and http://fishbowl.pastiche.org/2004/01/19/persistent_login_cookie_best_practice/
*/
final class Cookie extends CMSPlugin
final class Cookie extends CMSPlugin implements SubscriberInterface
{
use DatabaseAwareTrait;
use UserFactoryAwareTrait;

/**
* Reports the privacy related capabilities for this plugin to site administrators.
* Returns an array of events this subscriber will listen to.
*
* @return array
*
* @since __DEPLOY_VERSION__
*/
public static function getSubscribedEvents(): array
{
return [
'onPrivacyCollectAdminCapabilities' => 'onPrivacyCollectAdminCapabilities',
'onUserAuthenticate' => 'onUserAuthenticate',
'onUserAfterLogin' => 'onUserAfterLogin',
'onUserAfterLogout' => 'onUserAfterLogout',
];
}

/**
* Reports the privacy related capabilities for this plugin to site administrators.
*
* @return void
*
* @since 3.9.0
*/
public function onPrivacyCollectAdminCapabilities()
public function onPrivacyCollectAdminCapabilities(CollectCapabilitiesEvent $event): void
{
$this->loadLanguage();

return [
$event->addResult([
$this->getApplication()->getLanguage()->_('PLG_AUTHENTICATION_COOKIE') => [
$this->getApplication()->getLanguage()->_('PLG_AUTHENTICATION_COOKIE_PRIVACY_CAPABILITY_COOKIE'),
],
];
]);
}

/**
* This method should handle any authentication and report back to the subject
*
* @param array $credentials Array holding the user credentials
* @param array $options Array of extra options
* @param object &$response Authentication response object
* @param AuthenticationEvent $event Authentication event
*
* @return boolean
* @return void
*
* @since 3.2
*/
public function onUserAuthenticate($credentials, $options, &$response)
public function onUserAuthenticate(AuthenticationEvent $event): void
{
$app = $this->getApplication();

// No remember me for admin
if ($app->isClient('administrator')) {
return false;
return;
}

// Get cookie
Expand All @@ -84,7 +104,7 @@ public function onUserAuthenticate($credentials, $options, &$response)
}

if (!$cookieValue) {
return false;
return;
}

$cookieArray = explode('.', $cookieValue);
Expand All @@ -95,9 +115,10 @@ public function onUserAuthenticate($credentials, $options, &$response)
$app->getInput()->cookie->set($cookieName, '', 1, $app->get('cookie_path', '/'), $app->get('cookie_domain', ''));
Log::add('Invalid cookie detected.', Log::WARNING, 'error');

return false;
return;
}

$response = $event->getAuthenticationResponse();
$response->type = 'Cookie';

// Filter series since we're going to use it in the query
Expand Down Expand Up @@ -133,15 +154,15 @@ public function onUserAuthenticate($credentials, $options, &$response)
} catch (\RuntimeException $e) {
$response->status = Authentication::STATUS_FAILURE;

return false;
return;
}

if (\count($results) !== 1) {
// Destroy the cookie in the browser.
$app->getInput()->cookie->set($cookieName, '', 1, $app->get('cookie_path', '/'), $app->get('cookie_domain', ''));
$response->status = Authentication::STATUS_FAILURE;

return false;
return;
}

// We have a user with one cookie with a valid series and a corresponding record in the database.
Expand Down Expand Up @@ -174,7 +195,7 @@ public function onUserAuthenticate($credentials, $options, &$response)
Log::add(Text::sprintf('PLG_AUTHENTICATION_COOKIE_ERROR_LOG_LOGIN_FAILED', $results[0]->user_id), Log::WARNING, 'security');
$response->status = Authentication::STATUS_FAILURE;

return false;
return;
}

// Make sure there really is a user with this name and get the data for the session.
Expand All @@ -190,7 +211,7 @@ public function onUserAuthenticate($credentials, $options, &$response)
} catch (\RuntimeException $e) {
$response->status = Authentication::STATUS_FAILURE;

return false;
return;
}

if ($result) {
Expand All @@ -207,6 +228,9 @@ public function onUserAuthenticate($credentials, $options, &$response)
// Set response status.
$response->status = Authentication::STATUS_SUCCESS;
$response->error_message = '';

// Stop event propagation when status is STATUS_SUCCESS
$event->stopPropagation();
} else {
$response->status = Authentication::STATUS_FAILURE;
$response->error_message = $app->getLanguage()->_('JGLOBAL_AUTH_NO_USER');
Expand All @@ -218,22 +242,24 @@ public function onUserAuthenticate($credentials, $options, &$response)
* We set a new cookie either for a user with no cookies or one
* where the user used a cookie to authenticate.
*
* @param array $options Array holding options
* @param AfterLoginEvent $event Login event
*
* @return boolean True on success
* @return void
*
* @since 3.2
*/
public function onUserAfterLogin($options)
public function onUserAfterLogin(AfterLoginEvent $event): void
{
$app = $this->getApplication();

// No remember me for admin
if ($app->isClient('administrator')) {
return false;
return;
}

$db = $this->getDatabase();
$db = $this->getDatabase();
$options = $event->getOptions();

if (isset($options['responseType']) && $options['responseType'] === 'Cookie') {
// Logged in using a cookie
$cookieName = 'joomla_remember_me_' . UserHelper::getShortHashedUserAgent();
Expand Down Expand Up @@ -282,12 +308,12 @@ public function onUserAfterLogin($options)

// We'll let this query fail up to 5 times before giving up, there's probably a bigger issue at this point
if ($errorCount === 5) {
return false;
return;
}
}
} while ($unique === false);
} else {
return false;
return;
}

// Get the parameter values
Expand Down Expand Up @@ -345,36 +371,34 @@ public function onUserAfterLogin($options)
try {
$db->setQuery($query)->execute();
} catch (\RuntimeException $e) {
return false;
// We aren't concerned with errors from this query, carry on
}

return true;
}

/**
* This is where we delete any authentication cookie when a user logs out
*
* @param array $options Array holding options (length, timeToExpiration)
* @param AfterLogoutEvent $event Logout event
*
* @return boolean True on success
* @return void
*
* @since 3.2
*/
public function onUserAfterLogout($options)
public function onUserAfterLogout(AfterLogoutEvent $event): void
{
$app = $this->getApplication();

// No remember me for admin
if ($app->isClient('administrator')) {
return false;
return;
}

$cookieName = 'joomla_remember_me_' . UserHelper::getShortHashedUserAgent();
$cookieValue = $app->getInput()->cookie->get($cookieName);

// There are no cookies to delete.
if (!$cookieValue) {
return true;
return;
}

$cookieArray = explode('.', $cookieValue);
Expand All @@ -398,7 +422,5 @@ public function onUserAfterLogout($options)

// Destroy the cookie
$app->getInput()->cookie->set($cookieName, '', 1, $app->get('cookie_path', '/'), $app->get('cookie_domain', ''));

return true;
}
}
2 changes: 1 addition & 1 deletion plugins/authentication/joomla/src/Extension/Joomla.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public static function getSubscribedEvents(): array
*
* @since 1.5
*/
public function onUserAuthenticate(AuthenticationEvent $event)
public function onUserAuthenticate(AuthenticationEvent $event): void
{
$credentials = $event->getCredentials();
$response = $event->getAuthenticationResponse();
Expand Down
Loading