-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
IBX-8323: Reworked RepositoryAuthenticationProvider and moved its log…
…ic to a dedicated subscriber (#396) For more details see https://issues.ibexa.co/browse/IBX-8323 and #396 Key changes: * Reworked RepositoryAuthenticationProvider and moved its logic to a dedicated subscriber
- Loading branch information
1 parent
9fa21c3
commit e26e65e
Showing
9 changed files
with
271 additions
and
671 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
112 changes: 112 additions & 0 deletions
112
...ymfony/Security/Authentication/EventSubscriber/RepositoryUserAuthenticationSubscriber.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
<?php | ||
|
||
/** | ||
* @copyright Copyright (C) Ibexa AS. All rights reserved. | ||
* @license For full copyright and license information view LICENSE file distributed with this source code. | ||
*/ | ||
declare(strict_types=1); | ||
|
||
namespace Ibexa\Core\MVC\Symfony\Security\Authentication\EventSubscriber; | ||
|
||
use Exception; | ||
use Ibexa\Contracts\Core\Repository\Exceptions\PasswordInUnsupportedFormatException; | ||
use Ibexa\Contracts\Core\Repository\UserService; | ||
use Ibexa\Core\MVC\Symfony\Security\UserInterface as IbexaUserInterface; | ||
use Ibexa\Core\Repository\User\Exception\UnsupportedPasswordHashType; | ||
use Psr\Log\LoggerAwareTrait; | ||
use Psr\Log\LoggerInterface; | ||
use Psr\Log\NullLogger; | ||
use Symfony\Component\EventDispatcher\EventSubscriberInterface; | ||
use Symfony\Component\HttpFoundation\RequestStack; | ||
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge; | ||
use Symfony\Component\Security\Http\Event\CheckPassportEvent; | ||
|
||
final class RepositoryUserAuthenticationSubscriber implements EventSubscriberInterface | ||
{ | ||
use LoggerAwareTrait; | ||
|
||
public const string CONSTANT_AUTH_TIME_SETTING = 'ibexa.security.authentication.constant_auth_time'; | ||
|
||
private const int USLEEP_MULTIPLIER = 1000000; | ||
|
||
public function __construct( | ||
private readonly RequestStack $requestStack, | ||
private readonly UserService $userService, | ||
private readonly float $constantAuthTime, | ||
?LoggerInterface $logger = null | ||
) { | ||
$this->logger = $logger ?? new NullLogger(); | ||
} | ||
|
||
public static function getSubscribedEvents(): array | ||
{ | ||
return [ | ||
CheckPassportEvent::class => ['validateRepositoryUser'], | ||
]; | ||
} | ||
|
||
public function validateRepositoryUser(CheckPassportEvent $event): void | ||
{ | ||
$request = $this->requestStack->getCurrentRequest(); | ||
if ($request === null) { | ||
return; | ||
} | ||
|
||
$badge = $event->getPassport()->getBadge(UserBadge::class); | ||
if (!$badge instanceof UserBadge) { | ||
return; | ||
} | ||
|
||
$user = $badge->getUser(); | ||
if (!$user instanceof IbexaUserInterface) { | ||
return; | ||
} | ||
|
||
$startTime = $this->startConstantTimer(); | ||
try { | ||
$this->userService->checkUserCredentials( | ||
$user->getAPIUser(), | ||
$user->getPassword() ?? '' | ||
); | ||
|
||
$event->getAuthenticator()->authenticate($request); | ||
} catch (UnsupportedPasswordHashType $exception) { | ||
$this->sleepUsingConstantTimer($startTime); | ||
|
||
throw new PasswordInUnsupportedFormatException($exception); | ||
} catch (Exception $e) { | ||
$this->sleepUsingConstantTimer($startTime); | ||
|
||
throw $e; | ||
} | ||
|
||
$this->sleepUsingConstantTimer($startTime); | ||
} | ||
|
||
private function startConstantTimer(): float | ||
{ | ||
return microtime(true); | ||
} | ||
|
||
private function sleepUsingConstantTimer(float $startTime): void | ||
{ | ||
if ($this->constantAuthTime <= 0.0) { | ||
return; | ||
} | ||
|
||
$remainingTime = $this->constantAuthTime - (microtime(true) - $startTime); | ||
if ($remainingTime > 0) { | ||
$microseconds = $remainingTime * self::USLEEP_MULTIPLIER; | ||
|
||
usleep((int)$microseconds); | ||
} elseif ($this->logger) { | ||
$this->logger->warning( | ||
sprintf( | ||
'Authentication took longer than the configured constant time. Consider increasing the value of %s', | ||
self::CONSTANT_AUTH_TIME_SETTING | ||
), | ||
[__CLASS__] | ||
); | ||
} | ||
} | ||
} |
44 changes: 0 additions & 44 deletions
44
src/lib/MVC/Symfony/Security/Authentication/RememberMeRepositoryAuthenticationProvider.php
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.