8000 [Security] Display authenticators in the profiler even if they are al… · MatTheCat/symfony@2a2174e · GitHub
[go: up one dir, main page]

Skip to content

Commit 2a2174e

Browse files
committed
[Security] Display authenticators in the profiler even if they are all skipped
1 parent c852b8b commit 2a2174e

File tree

8 files changed

+56
-47
lines changed

8 files changed

+56
-47
lines changed

src/Symfony/Bundle/SecurityBundle/Command/DebugFirewallCommand.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
use Symfony\Component\Console\Style\SymfonyStyle;
2626
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
2727
use Symfony\Component\Security\Http\Authenticator\AuthenticatorInterface;
28+
use Symfony\Component\Security\Http\Authenticator\Debug\TraceableAuthenticator;
2829

2930
/**
3031
* @author Timo Bakx <timobakx@gmail.com>
@@ -210,7 +211,7 @@ private function displayAuthenticators(string $name, SymfonyStyle $io): void
210211
$io->table(
211212
['Classname'],
212213
array_map(
213-
fn ($authenticator) => [$authenticator::class],
214+
fn ($authenticator) => [($authenticator instanceof TraceableAuthenticator ? $authenticator->getAuthenticator() : $authenticator)::class],
214215
$authenticators
215216
)
216217
);

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
use Symfony\Component\Security\Core\User\ChainUserProvider;
5959
use Symfony\Component\Security\Core\User\UserCheckerInterface;
6060
use Symfony\Component\Security\Core\User\UserProviderInterface;
61+
use Symfony\Component\Security\Http\Authenticator\Debug\TraceableAuthenticator;
6162
use Symfony\Component\Security\Http\Authenticator\Debug\TraceableAuthenticatorManagerListener;
6263
use Symfony\Component\Security\Http\Event\CheckPassportEvent;
6364
use Symfony\Flex\Command\InstallRecipesCommand;
@@ -638,6 +639,15 @@ private function createAuthenticationListeners(ContainerBuilder $container, stri
638639
}
639640
}
640641

642+
if ($container->hasDefinition('debug.security.firewall')) {
643+
foreach ($authenticationProviders as $authenticatorId) {
644+
$container->register('debug.'.$authenticatorId, TraceableAuthenticator::class)
645+
->setDecoratedService($authenticatorId)
646+
->setArguments([new Reference('debug.'.$authenticatorId.'.inner')])
647+
;
648+
}
649+
}
650+
641651
// the actual entry point is configured by the RegisterEntryPointPass
642652
$container->setParameter('security.'.$id.'._indexed_authenticators', $entryPoints);
643653

src/Symfony/Bundle/SecurityBundle/Resources/views/Collector/security.html.twig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -360,7 +360,7 @@
360360

361361
<tr>
362362
<td class="font-normal">{{ profiler_dump(authenticator.stub) }}</td>
363-
<td class="no-wrap">{{ source('@WebProfiler/Icon/' ~ (authenticator.supports ? 'yes' : 'no') ~ '.svg') }}</td>
363+
<td class="no-wrap">{{ source('@WebProfiler/Icon/' ~ (authenticator.supports is same as (false) ? 'no' : 'yes') ~ '.svg') }}</td>
364364
<td class="no-wrap">{{ authenticator.authenticated is not null ? source('@WebProfiler/Icon/' ~ (authenticator.authenticated ? 'yes' : 'no') ~ '.svg') : '' }}</td>
365365
<td class="no-wrap">{{ authenticator.duration is null ? '(none)' : '%0.2f ms'|format(authenticator.duration * 1000) }}</td>
366366
<td class="font-normal">{{ authenticator.passport ? profiler_dump(authenticator.passport) : '(none)' }}</td>

src/Symfony/Bundle/SecurityBundle/Tests/Debug/TraceableFirewallListenerTest.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
2323
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
2424
use Symfony\Component\Security\Http\Authentication\AuthenticatorManager;
25+
use Symfony\Component\Security\Http\Authenticator\Debug\TraceableAuthenticator;
2526
use Symfony\Component\Security\Http\Authenticator\Debug\TraceableAuthenticatorManagerListener;
2627
use Symfony\Component\Security\Http\Authenticator\InteractiveAuthenticatorInterface;
2728
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
@@ -99,7 +100,7 @@ public function testOnKernelRequestRecordsAuthenticatorsInfo()
99100
$tokenStorage = $this->createMock(TokenStorageInterface::class);
100101
$dispatcher = new EventDispatcher();
101102
$authenticatorManager = new AuthenticatorManager(
102-
[$notSupportingAuthenticator, $supportingAuthenticator],
103+
[new TraceableAuthenticator($notSupportingAuthenticator), new TraceableAuthenticator($supportingAuthenticator)],
103104
$tokenStorage,
104105
$dispatcher,
105106
'main'

src/Symfony/Component/Security/Http/Authentication/AuthenticatorManager.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,13 +108,13 @@ public function supports(Request $request): ?bool
108108
}
109109
}
110110

111+
$request->attributes->set('_security_skipped_authenticators', $skippedAuthenticators);
112+
$request->attributes->set('_security_authenticators', $authenticators);
113+
111114
if (!$authenticators) {
112115
return false;
113116
}
114117

115-
$request->attributes->set('_security_authenticators', $authenticators);
116-
$request->attributes->set('_security_skipped_authenticators', $skippedAuthenticators);
117-
118118
return $lazy ? null : true;
119119
}
120120

src/Symfony/Component/Security/Http/Authenticator/Debug/TraceableAuthenticator.php

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
*/
3131
final class TraceableAuthenticator implements AuthenticatorInterface, InteractiveAuthenticatorInterface, AuthenticationEntryPointInterface
3232
{
33+
private ?bool $supports;
3334
private ?Passport $passport = null;
3435
private ?float $duration = null;
3536
private ClassStub|string $stub;
@@ -42,7 +43,7 @@ public function __construct(private AuthenticatorInterface $authenticator)
4243
public function getInfo(): array
4344
{
4445
return [
45-
'supports' => true,
46+
'supports' => $this->supports,
4647
'passport' => $this->passport,
4748
'duration' => $this->duration,
4849
'stub' => $this->stub ??= class_exists(ClassStub::class) ? new ClassStub($this->authenticator::class) : $this->authenticator::class,
@@ -61,14 +62,17 @@ static function (BadgeInterface $badge): array {
6162

6263
public function supports(Request $request): ?bool
6364
{
64-
return $this->authenticator->supports($request);
65+
return $this->supports = $this->authenticator->supports($request);
6566
}
6667

6768
public function authenticate(Request $request): Passport
6869
{
6970
$startTime = microtime(true);
70-
$this->passport = $this->authenticator->authenticate($request);
71-
$this->duration = microtime(true) - $startTime;
71+
try {
72+
$this->passport = $this->authenticator->authenticate($request);
73+
} finally {
74+
$this->duration = microtime(true) - $startTime;
75+
}
7276

7377
return $this->passport;
7478
}

src/Symfony/Component/Security/Http/Authenticator/Debug/TraceableAuthenticatorManagerListener.php

Lines changed: 17 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
use Symfony\Component\HttpKernel\Event\RequestEvent;
1616
use Symfony\Component\Security\Http\Firewall\AbstractListener;
1717
use Symfony\Component\Security\Http\Firewall\AuthenticatorManagerListener;
18-
use Symfony\Component\VarDumper\Caster\ClassStub;
1918
use Symfony\Contracts\Service\ResetInterface;
2019

2120
/**
@@ -25,50 +24,28 @@
2524
*/
2625
final class TraceableAuthenticatorManagerListener extends AbstractListener implements ResetInterface
2726
{
28-
private array $authenticatorsInfo = [];
29-
private bool $hasVardumper;
27+
private array $authenticators = [];
3028

31-
public function __construct(
32-
private AuthenticatorManagerListener $authenticationManagerListener,
33-
) {
34-
$this->hasVardumper = class_exists(ClassStub::class);
35-
}
36-
37-
public function supports(Request $request): ?bool
29+
public function __construct(private AuthenticatorManagerListener $authenticationManagerListener)
3830
{
39-
return $this->authenticationManagerListener->supports($request);
4031
}
4132

42-
public function authenticate(RequestEvent $event): void
33+
public function supports(Request $request): ?bool
4334
{
44-
$request = $event->getRequest();
45-
46-
if (!$authenticators = $request->attributes->get('_security_authenticators')) {
47-
return;
48-
}
35+
$supports = $this->authenticationManagerListener->supports($request);
4936

50-
foreach ($request->attributes->get('_security_skipped_authenticators') as $skippedAuthenticator) {
51-
$this->authenticatorsInfo[] = [
52-
'supports' => false,
53-
'stub' => $this->hasVardumper ? new ClassStub($skippedAuthenticator::class) : $skippedAuthenticator::class,
54-
'passport' => null,
55-
'duration' => 0,
56-
'authenticated' => null,
57-
'badges' => [],
58-
];
37+
foreach (array_merge($request->attributes->get('_security_skipped_authenticators'), $request->attributes->get('_security_authenticators')) as $authenticator) {
38+
if ($authenticator instanceof TraceableAuthenticator) {
39+
$this->authenticators[] = $authenticator;
40+
}
5941
}
6042

61-
foreach ($authenticators as $key => $authenticator) {
62-
$authenticators[$key] = new TraceableAuthenticator($authenticator);
63-
}
64-
65-
$request->attributes->set('_security_authenticators', $authenticators);
43+
return $supports;
44+
}
6645

46+
public function authenticate(RequestEvent $event): void
47+
{
6748
$this->authenticationManagerListener->authenticate($event);
68-
69-
foreach ($authenticators as $authenticator) {
70-
$this->authenticatorsInfo[] = $authenticator->getInfo();
71-
}
7249
}
7350

7451
public function getAuthenticatorManagerListener(): AuthenticatorManagerListener
@@ -78,11 +55,14 @@ public function getAuthenticatorManagerListener(): AuthenticatorManagerListener
7855

7956
public function getAuthenticatorsInfo(): array
8057
{
81-
return $this->authenticatorsInfo;
58+
return array_map(
59+
static fn (TraceableAuthenticator $authenticator) => $authenticator->getInfo(),
60+
$this->authenticators
61+
);
8262
}
8363

8464
public function reset(): void
8565
{
86-
$this->authenticatorsInfo = [];
66+
$this->authenticators = [];
8767
}
8868
}

src/Symfony/Component/Security/Http/Tests/Authenticator/Debug/TraceableAuthenticatorTest.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,22 +26,35 @@ public function testGetInfo()
2626
$passport = new SelfValidatingPassport(new UserBadge('robin', function () {}));
2727

2828
$authenticator = $this->createMock(AuthenticatorInterface::class);
29+
$authenticator->expects($this->once())
30+
->method('supports')
31+
->with($request)
32+
->willReturn(true);
33+
2934
$authenticator
3035
->expects($this->once())
3136
->method('authenticate')
3237
->with($request)
3338
->willReturn($passport);
3439

3540
$traceable = new TraceableAuthenticator($authenticator);
41+
$this->assertTrue($traceable->supports($request));
3642
$this->assertSame($passport, $traceable->authenticate($request));
3743
$this->assertSame($passport, $traceable->getInfo()['passport']);
3844
}
3945

4046
public function testGetInfoWithoutAuth()
4147
{
48+
$request = new Request();
49+
4250
$authenticator = $this->createMock(AuthenticatorInterface::class);
51+
$authenticator->expects($this->once())
52+
->method('supports')
53+
->with($request)
54+
->willReturn(false);
4355

4456
$traceable = new TraceableAuthenticator($authenticator);
57+
$this->assertFalse($traceable->supports($request));
4558
$this->assertNull($traceable->getInfo()['passport']);
4659
$this->assertIsArray($traceable->getInfo()['badges']);
4760
$this->assertSame([], $traceable->getInfo()['badges']);

0 commit comments

Comments
 (0)
0