Skip to content

Commit f851d43

Browse files
authored
IBX-8656: Skipped credentials check for SelfValidatingPassport (#411)
* IBX-8656: Skipped credentials check for `SelfValidatingPassport` * removed duplicated authentication
1 parent 2715e7d commit f851d43

File tree

6 files changed

+41
-130
lines changed

6 files changed

+41
-130
lines changed

phpstan-baseline.neon

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11570,11 +11570,6 @@ parameters:
1157011570
count: 1
1157111571
path: src/lib/MVC/Symfony/Event/ContentCacheClearEvent.php
1157211572

11573-
-
11574-
message: "#^Property Ibexa\\\\Core\\\\MVC\\\\Symfony\\\\Event\\\\InteractiveLoginEvent\\:\\:\\$apiUser \\(Ibexa\\\\Contracts\\\\Core\\\\Repository\\\\Values\\\\User\\\\User\\) in isset\\(\\) is not nullable\\.$#"
11575-
count: 1
11576-
path: src/lib/MVC/Symfony/Event/InteractiveLoginEvent.php
11577-
1157811573
-
1157911574
message: "#^Method Ibexa\\\\Core\\\\MVC\\\\Symfony\\\\Event\\\\PostSiteAccessMatchEvent\\:\\:__construct\\(\\) has parameter \\$requestType with no type specified\\.$#"
1158011575
count: 1
@@ -45915,11 +45910,6 @@ parameters:
4591545910
count: 1
4591645911
path: tests/lib/MVC/Symfony/Event/ContentCacheClearEventTest.php
4591745912

45918-
-
45919-
message: "#^Method Ibexa\\\\Tests\\\\Core\\\\MVC\\\\Symfony\\\\Event\\\\InteractiveLoginEventTest\\:\\:testGetSetAPIUser\\(\\) has no return type specified\\.$#"
45920-
count: 1
45921-
path: tests/lib/MVC/Symfony/Event/InteractiveLoginEventTest.php
45922-
4592345913
-
4592445914
message: "#^Method Ibexa\\\\Tests\\\\Core\\\\MVC\\\\Symfony\\\\Event\\\\RouteReferenceGenerationEventTest\\:\\:testConstruct\\(\\) has no return type specified\\.$#"
4592545915
count: 1

src/lib/MVC/Symfony/Event/InteractiveLoginEvent.php

Lines changed: 0 additions & 70 deletions
This file was deleted.

src/lib/MVC/Symfony/MVCEvents.php

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -51,14 +51,6 @@ final class MVCEvents
5151
*/
5252
public const CONFIG_SCOPE_RESTORE = 'ezpublish.config.scope_restore';
5353

54-
/**
55-
* INTERACTIVE_LOGIN event occurs when a user has been authenticated by a foreign user provider.
56-
* Listening to this event gives a chance to retrieve a valid API user to be injected in repository.
57-
*
58-
* The event listener method receives a {@see \Ibexa\Core\MVC\Symfony\Event\InteractiveLoginEvent} instance.
59-
*/
60-
public const INTERACTIVE_LOGIN = 'ezpublish.security.interactive_login';
61-
6254
/**
6355
* ROUTE_REFERENCE_GENERATION event occurs when a RouteReference is generated, and gives an opportunity to
6456
* alter the RouteReference, e.g. by adding parameters.

src/lib/MVC/Symfony/Security/Authentication/EventSubscriber/RepositoryUserAuthenticationSubscriber.php

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
2020
use Symfony\Component\HttpFoundation\RequestStack;
2121
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
22+
use Symfony\Component\Security\Http\Authenticator\Passport\SelfValidatingPassport;
2223
use Symfony\Component\Security\Http\Event\CheckPassportEvent;
2324

2425
final class RepositoryUserAuthenticationSubscriber implements EventSubscriberInterface
@@ -52,7 +53,14 @@ public function validateRepositoryUser(CheckPassportEvent $event): void
5253
return;
5354
}
5455

55-
$badge = $event->getPassport()->getBadge(UserBadge::class);
56+
$passport = $event->getPassport();
57+
//validating password hash is not needed when SelfValidatingPassport is in use - this implementation is generally
58+
//used when there are no credentials to be checked (e.g. API token authentication).
59+
if ($passport instanceof SelfValidatingPassport) {
60+
return;
61+
}
62+
63+
$badge = $passport->getBadge(UserBadge::class);
5664
if (!$badge instanceof UserBadge) {
5765
return;
5866
}
@@ -68,8 +76,6 @@ public function validateRepositoryUser(CheckPassportEvent $event): void
6876
$user->getAPIUser(),
6977
$user->getPassword() ?? ''
7078
);
71-
72-
$event->getAuthenticator()->authenticate($request);
7379
} catch (UnsupportedPasswordHashType $exception) {
7480
$this->sleepUsingConstantTimer($startTime);
7581

tests/lib/MVC/Symfony/Event/InteractiveLoginEventTest.php

Lines changed: 0 additions & 27 deletions
This file was deleted.

tests/lib/MVC/Symfony/Security/Authentication/EventSubscriber/RepositoryUserAuthenticationSubscriberTest.php

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
2525
use Symfony\Component\Security\Http\Authenticator\Passport\Credentials\PasswordCredentials;
2626
use Symfony\Component\Security\Http\Authenticator\Passport\Passport;
27+
use Symfony\Component\Security\Http\Authenticator\Passport\SelfValidatingPassport;
2728
use Symfony\Component\Security\Http\Event\CheckPassportEvent;
2829
use Symfony\Component\Stopwatch\Stopwatch;
2930

@@ -112,6 +113,21 @@ public function testAuthenticateConstantTimeDisabled(): void
112113
);
113114
}
114115

116+
public function testSkippingRepositoryUserValidationForSelfValidatingPassport(): void
117+
{
118+
$user = $this->createMock(User::class);
119+
$user->expects(self::never())->method('getAPIUser');
120+
121+
$userService = $this->createMock(UserService::class);
122+
$userService->expects(self::never())->method('checkUserCredentials');
123+
124+
$selfValidatingPassport = new SelfValidatingPassport(new UserBadge('foo'));
125+
126+
$this->getSubscriber($userService)->validateRepositoryUser(
127+
$this->getCheckPassportEvent($user, $selfValidatingPassport)
128+
);
129+
}
130+
115131
private function getSubscriber(
116132
?UserService $userService = null,
117133
float $constantAuthTime = 1.0,
@@ -131,22 +147,26 @@ private function getSubscriber(
131147
);
132148
}
133149

134-
private function getCheckPassportEvent(?UserInterface $user = null): CheckPassportEvent
135-
{
150+
private function getCheckPassportEvent(
151+
?UserInterface $user = null,
152+
?Passport $passport = null,
153+
): CheckPassportEvent {
154+
$authenticator = $this->createMock(AuthenticatorInterface::class);
136155
$user = $user ?? $this->createMock(User::class);
137156

138-
$userProvider = $this->createMock(User\APIUserProviderInterface::class);
139-
$userProvider
140-
->expects(self::once())
141-
->method('loadUserByUsername')
142-
->willReturn($user);
157+
if ($passport === null) {
158+
$userProvider = $this->createMock(User\APIUserProviderInterface::class);
159+
$userProvider
160+
->expects(self::once())
161+
->method('loadUserByUsername')
162+
->willReturn($user);
143163

144-
return new CheckPassportEvent(
145-
$this->createMock(AuthenticatorInterface::class),
146-
new Passport(
164+
$passport = new Passport(
147165
new UserBadge($user->getUsername(), [$userProvider, 'loadUserByUsername']),
148166
new PasswordCredentials($user->getPassword() ?? '')
149-
)
150-
);
167+
);
168+
}
169+
170+
return new CheckPassportEvent($authenticator, $passport);
151171
}
152172
}

0 commit comments

Comments
 (0)