Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 1c810d5

Browse filesBrowse files
committed
Added support for lazy firewalls
1 parent 7859977 commit 1c810d5
Copy full SHA for 1c810d5

File tree

7 files changed

+87
-65
lines changed
Filter options

7 files changed

+87
-65
lines changed

‎src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php
-1Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -453,7 +453,6 @@ private function createFirewall(ContainerBuilder $container, string $id, array $
453453
->setDefinition('security.firewall.authenticator.'.$id, new ChildDefinition('security.firewall.authenticator'))
454454
->replaceArgument(2, new Reference('security.firewall.authenticator.'.$id.'.locator'))
455455
->replaceArgument(3, $id)
456-
->addTag('kernel.event_listener', ['event' => KernelEvents::REQUEST])
457456
;
458457

459458
$listeners[] = new Reference('security.firewall.authenticator.'.$id);

‎src/Symfony/Bundle/SecurityBundle/EventListener/LazyAuthenticatorManagerListener.php

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/SecurityBundle/EventListener/LazyAuthenticatorManagerListener.php
+13-11Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -26,37 +26,39 @@
2626
*/
2727
class LazyAuthenticatorManagerListener extends AuthenticatorManagerListener
2828
{
29-
private $guardLocator;
29+
private $authenticatorLocator;
3030

3131
public function __construct(
3232
AuthenticationManagerInterface $authenticationManager,
3333
AuthenticatorHandler $authenticatorHandler,
34-
ServiceLocator $guardLocator,
34+
ServiceLocator $authenticatorLocator,
3535
string $providerKey,
3636
EventDispatcherInterface $eventDispatcher,
3737
?LoggerInterface $logger = null
3838
) {
3939
parent::__construct($authenticationManager, $authenticatorHandler, [], $providerKey, $eventDispatcher, $logger);
4040

41-
$this->guardLocator = $guardLocator;
41+
$this->authenticatorLocator = $authenticatorLocator;
4242
}
4343

4444
protected function getSupportingAuthenticators(Request $request): array
4545
{
46-
$guardAuthenticators = [];
47-
foreach ($this->guardLocator->getProvidedServices() as $key => $type) {
48-
$guardAuthenticator = $this->guardLocator->get($key);
46+
$authenticators = [];
47+
$lazy = true;
48+
foreach ($this->authenticatorLocator->getProvidedServices() as $key => $type) {
49+
$authenticator = $this->authenticatorLocator->get($key);
4950
if (null !== $this->logger) {
50-
$this->logger->debug('Checking support on guard authenticator.', ['firewall_key' => $this->providerKey, 'authenticator' => \get_class($guardAuthenticator)]);
51+
$this->logger->debug('Checking support on guard authenticator.', ['firewall_key' => $this->providerKey, 'authenticator' => \get_class($authenticator)]);
5152
}
5253

53-
if ($guardAuthenticator->supports($request)) {
54-
$guardAuthenticators[$key] = $guardAuthenticator;
54+
if (false !== $supports = $authenticator->supports($request)) {
55+
$authenticators[$key] = $authenticator;
56+
$lazy = $lazy && null === $supports;
5557
} elseif (null !== $this->logger) {
56-
$this->logger->debug('Guard authenticator does not support the request.', ['firewall_key' => $this->providerKey, 'authenticator' => \get_class($guardAuthenticator)]);
58+
$this->logger->debug('Guard authenticator does not support the request.', ['firewall_key' => $this->providerKey, 'authenticator' => \get_class($authenticator)]);
5759
}
5860
}
5961

60-
return $guardAuthenticators;
62+
return [$authenticators, $lazy];
6163
}
6264
}

‎src/Symfony/Bundle/SecurityBundle/Resources/config/authenticators.xml

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/SecurityBundle/Resources/config/authenticators.xml
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@
8080
class="Symfony\Component\Security\Http\Authenticator\AnonymousAuthenticator"
8181
abstract="true">
8282
<argument type="abstract">secret</argument>
83-
<argument type="service" id="security.token_storage" />
83+
<argument type="service" id="security.untracked_token_storage" />
8484
</service>
8585
</services>
8686
</container>

‎src/Symfony/Component/Security/Guard/Firewall/GuardAuthenticationListener.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Security/Guard/Firewall/GuardAuthenticationListener.php
+13-3Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,6 @@
3434
*/
3535
class GuardAuthenticationListener extends AbstractListener
3636
{
37-
use AuthenticatorManagerListenerTrait;
38-
3937
private $guardHandler;
4038
private $authenticationManager;
4139
private $providerKey;
@@ -75,7 +73,19 @@ public function supports(Request $request): ?bool
7573
$this->logger->debug('Checking for guard authentication credentials.', $context);
7674
}
7775

78-
$guardAuthenticators = $this->getSupportingAuthenticators($request);
76+
$guardAuthenticators = [];
77+
foreach ($this->authenticators as $key => $authenticator) {
78+
if (null !== $this->logger) {
79+
$this->logger->debug('Checking support on authenticator.', ['firewall_key' => $this->providerKey, 'authenticator' => \get_class($authenticator)]);
80+
}
81+
82+
if ($authenticator->supports($request)) {
83+
$guardAuthenticators[$key] = $authenticator;
84+
} elseif (null !== $this->logger) {
85+
$this->logger->debug('Authenticator does not support the request.', ['firewall_key' => $this->providerKey, 'authenticator' => \get_class($authenticator)]);
86+
}
87+
}
88+
7989
if (!$guardAuthenticators) {
8090
return false;
8191
}

‎src/Symfony/Component/Security/Http/Authenticator/AnonymousAuthenticator.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Security/Http/Authenticator/AnonymousAuthenticator.php
+2-1Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@ public function __construct(string $secret, TokenStorageInterface $tokenStorage)
4141
public function supports(Request $request): ?bool
4242
{
4343
// do not overwrite already stored tokens (i.e. from the session)
44-
return null === $this->tokenStorage->getToken();
44+
// the `null` return value indicates that this authenticator supports lazy firewalls
45+
return null === $this->tokenStorage->getToken() ? null : false;
4546
}
4647

4748
public function getCredentials(Request $request)

‎src/Symfony/Component/Security/Http/Firewall/AuthenticatorManagerListener.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Security/Http/Firewall/AuthenticatorManagerListener.php
+58-7Lines changed: 58 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
use Psr\Log\LoggerInterface;
1515
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
16+
use Symfony\Component\HttpFoundation\Request;
1617
use Symfony\Component\HttpFoundation\Response;
1718
use Symfony\Component\HttpKernel\Event\RequestEvent;
1819
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
@@ -30,10 +31,8 @@
3031
*
3132
* @experimental in 5.1
3233
*/
33-
class AuthenticatorManagerListener
34+
class AuthenticatorManagerListener extends AbstractListener
3435
{
35-
use AuthenticatorManagerListenerTrait;
36-
3736
private $authenticationManager;
3837
private $authenticatorHandler;
3938
private $authenticators;
@@ -54,15 +53,58 @@ public function __construct(AuthenticationManagerInterface $authenticationManage
5453
$this->eventDispatcher = $eventDispatcher;
5554
}
5655

57-
public function __invoke(RequestEvent $requestEvent)
56+
public function supports(Request $request): ?bool
5857
{
59-
$request = $requestEvent->getRequest();
60-
$authenticators = $this->getSupportingAuthenticators($request);
58+
if (null !== $this->logger) {
59+
$context = ['firewall_key' => $this->providerKey];
60+
61+
if ($this->authenticators instanceof \Countable || \is_array($this->authenticators)) {
62+
$context['authenticators'] = \count($this->authenticators);
63+
}
64+
65+
$this->logger->debug('Checking for guard authentication credentials.', $context);
66+
}
67+
68+
[$authenticators, $lazy] = $this->getSupportingAuthenticators($request);
69+
if (!$authenticators) {
70+
return false;
71+
}
72+
73+
$request->attributes->set('_guard_authenticators', $authenticators);
74+
75+
return $lazy ? null : true;
76+
}
77+
78+
public function authenticate(RequestEvent $event)
79+
{
80+
$request = $event->getRequest();
81+
$authenticators = $request->attributes->get('_guard_authenticators');
82+
$request->attributes->remove('_guard_authenticators');
6183
if (!$authenticators) {
6284
return;
6385
}
6486

65-
$this->executeAuthenticators($authenticators, $requestEvent);
87+
$this->executeAuthenticators($authenticators, $event);
88+
}
89+
90+
protected function getSupportingAuthenticators(Request $request): array
91+
{
92+
$authenticators = [];
93+
$lazy = true;
94+
foreach ($this->authenticators as $key => $authenticator) {
95+
if (null !== $this->logger) {
96+
$this->logger->debug('Checking support on authenticator.', ['firewall_key' => $this->providerKey, 'authenticator' => \get_class($authenticator)]);
97+
}
98+
99+
if (false !== $supports = $authenticator->supports($request)) {
100+
$authenticators[$key] = $authenticator;
101+
$lazy = $lazy && null === $supports;
102+
} elseif (null !== $this->logger) {
103+
$this->logger->debug('Authenticator does not support the request.', ['firewall_key' => $this->providerKey, 'authenticator' => \get_class($authenticator)]);
104+
}
105+
}
106+
107+
return [$authenticators, $lazy];
66108
}
67109

68110
/**
@@ -71,6 +113,15 @@ public function __invoke(RequestEvent $requestEvent)
71113
protected function executeAuthenticators(array $authenticators, RequestEvent $event): void
72114
{
73115
foreach ($authenticators as $key => $authenticator) {
116+
// recheck if the authenticator still supports the listener. support() is called
117+
// eagerly (before token storage is initialized), whereas authenticate() is called
118+
// lazily (after initialization). This is important for e.g. the AnonymousAuthenticator
119+
// as its support is relying on the (initialized) token in the TokenStorage.
120+
if (false === $authenticator->supports($event->getRequest())) {
121+
$this->logger->debug('Skipping the "{authenticator}" authenticator as it did not support the request.', ['authenticator' => \get_class($authenticator)]);
122+
continue;
123+
}
124+
74125
$this->executeAuthenticator($key, $authenticator, $event);
75126

76127
if ($event->hasResponse()) {

‎src/Symfony/Component/Security/Http/Firewall/AuthenticatorManagerListenerTrait.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Security/Http/Firewall/AuthenticatorManagerListenerTrait.php
-41Lines changed: 0 additions & 41 deletions
This file was deleted.

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.