Skip to content

Commit a3b1935

Browse files
committed
Merge branch '5.4' into 6.0
* 5.4: [Mailer] Fix string-cast of exceptions thrown by authenticator in EsmtpTransport [Cache] fix error handling [Security] Fix wrong authenticator class in debug logs 43460: add missing validator component turkish translations Fix generic type for FormErrorIterator
2 parents cab2eee + 8f21e1c commit a3b1935

File tree

3 files changed

+58
-8
lines changed

3 files changed

+58
-8
lines changed

Authentication/AuthenticatorManager.php

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
2626
use Symfony\Component\Security\Core\User\UserInterface;
2727
use Symfony\Component\Security\Http\Authenticator\AuthenticatorInterface;
28+
use Symfony\Component\Security\Http\Authenticator\Debug\TraceableAuthenticator;
2829
use Symfony\Component\Security\Http\Authenticator\InteractiveAuthenticatorInterface;
2930
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\BadgeInterface;
3031
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
@@ -150,7 +151,7 @@ private function executeAuthenticators(array $authenticators, Request $request):
150151
// lazily (after initialization).
151152
if (false === $authenticator->supports($request)) {
152153
if (null !== $this->logger) {
153-
$this->logger->debug('Skipping the "{authenticator}" authenticator as it did not support the request.', ['authenticator' => \get_class($authenticator)]);
154+
$this->logger->debug('Skipping the "{authenticator}" authenticator as it did not support the request.', ['authenticator' => \get_class($authenticator instanceof TraceableAuthenticator ? $authenticator->getAuthenticator() : $authenticator)]);
154155
}
155156

156157
continue;
@@ -159,7 +160,7 @@ private function executeAuthenticators(array $authenticators, Request $request):
159160
$response = $this->executeAuthenticator($authenticator, $request);
160161
if (null !== $response) {
161162
if (null !== $this->logger) {
162-
$this->logger->debug('The "{authenticator}" authenticator set the response. Any later authenticator will not be called', ['authenticator' => \get_class($authenticator)]);
163+
$this->logger->debug('The "{authenticator}" authenticator set the response. Any later authenticator will not be called', ['authenticator' => \get_class($authenticator instanceof TraceableAuthenticator ? $authenticator->getAuthenticator() : $authenticator)]);
163164
}
164165

165166
return $response;
@@ -209,7 +210,7 @@ private function executeAuthenticator(AuthenticatorInterface $authenticator, Req
209210
$this->eventDispatcher->dispatch(new AuthenticationSuccessEvent($authenticatedToken), AuthenticationEvents::AUTHENTICATION_SUCCESS);
210211

211212
if (null !== $this->logger) {
212-
$this->logger->info('Authenticator successful!', ['token' => $authenticatedToken, 'authenticator' => \get_class($authenticator)]);
213+
$this->logger->info('Authenticator successful!', ['token' => $authenticatedToken, 'authenticator' => \get_class($authenticator instanceof TraceableAuthenticator ? $authenticator->getAuthenticator() : $authenticator)]);
213214
}
214215
} catch (AuthenticationException $e) {
215216
// oh no! Authentication failed!
@@ -228,7 +229,7 @@ private function executeAuthenticator(AuthenticatorInterface $authenticator, Req
228229
}
229230

230231
if (null !== $this->logger) {
231-
$this->logger->debug('Authenticator set no success response: request continues.', ['authenticator' => \get_class($authenticator)]);
232+
$this->logger->debug('Authenticator set no success response: request continues.', ['authenticator' => \get_class($authenticator instanceof TraceableAuthenticator ? $authenticator->getAuthenticator() : $authenticator)]);
232233
}
233234

234235
return null;
@@ -255,7 +256,7 @@ private function handleAuthenticationSuccess(TokenInterface $authenticatedToken,
255256
private function handleAuthenticationFailure(AuthenticationException $authenticationException, Request $request, AuthenticatorInterface $authenticator, ?Passport $passport): ?Response
256257
{
257258
if (null !== $this->logger) {
258-
$this->logger->info('Authenticator failed.', ['exception' => $authenticationException, 'authenticator' => \get_class($authenticator)]);
259+
$this->logger->info('Authenticator failed.', ['exception' => $authenticationException, 'authenticator' => \get_class($authenticator instanceof TraceableAuthenticator ? $authenticator->getAuthenticator() : $authenticator)]);
259260
}
260261

261262
// Avoid leaking error details in case of invalid user (e.g. user not found or invalid account status)
@@ -266,7 +267,7 @@ private function handleAuthenticationFailure(AuthenticationException $authentica
266267

267268
$response = $authenticator->onAuthenticationFailure($request, $authenticationException);
268269
if (null !== $response && null !== $this->logger) {
269-
$this->logger->debug('The "{authenticator}" authenticator set the failure response.', ['authenticator' => \get_class($authenticator)]);
270+
$this->logger->debug('The "{authenticator}" authenticator set the failure response.', ['authenticator' => \get_class($authenticator instanceof TraceableAuthenticator ? $authenticator->getAuthenticator() : $authenticator)]);
270271
}
271272

272273
$this->eventDispatcher->dispatch($loginFailureEvent = new LoginFailureEvent($authenticationException, $authenticator, $request, $response, $this->firewallName, $passport));

Authenticator/Debug/TraceableAuthenticator.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,14 @@ public function isInteractive(): bool
9292
return $this->authenticator instanceof InteractiveAuthenticatorInterface && $this->authenticator->isInteractive();
9393
}
9494

95+
/**
96+
* @internal
97+
*/
98+
public function getAuthenticator(): AuthenticatorInterface
99+
{
100+
return $this->authenticator;
101+
}
102+
95103
public function __call($method, $args)
96104
{
97105
return $this->authenticator->{$method}(...$args);

Tests/Authentication/AuthenticatorManagerTest.php

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
namespace Symfony\Component\Security\Http\Tests\Authentication;
1313

1414
use PHPUnit\Framework\TestCase;
15+
use Psr\Log\AbstractLogger;
16+
use Psr\Log\LoggerInterface;
1517
use Symfony\Component\EventDispatcher\EventDispatcher;
1618
use Symfony\Component\HttpFoundation\Request;
1719
use Symfony\Component\HttpFoundation\Response;
@@ -22,6 +24,7 @@
2224
use Symfony\Component\Security\Core\Exception\UserNotFoundException;
2325
use Symfony\Component\Security\Core\User\InMemoryUser;
2426
use Symfony\Component\Security\Http\Authentication\AuthenticatorManager;
27+
use Symfony\Component\Security\Http\Authenticator\Debug\TraceableAuthenticator;
2528
use Symfony\Component\Security\Http\Authenticator\InteractiveAuthenticatorInterface;
2629
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\CsrfTokenBadge;
2730
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
@@ -310,6 +313,44 @@ public function testAuthenticateRequestHidesInvalidUserExceptions()
310313
$this->assertSame($this->response, $response);
311314
}
312315

316+
public function testLogsUseTheDecoratedAuthenticatorWhenItIsTraceable()
317+
{
318+
$authenticator = $this->createMock(TestInteractiveAuthenticator::class);
319+
$authenticator->expects($this->any())->method('isInteractive')->willReturn(true);
320+
$this->request->attributes->set('_security_authenticators', [new TraceableAuthenticator($authenticator)]);
321+
322+
$authenticator->expects($this->any())->method('authenticate')->willReturn(new SelfValidatingPassport(new UserBadge('wouter', function () { return $this->user; })));
323+
$authenticator->expects($this->any())->method('createToken')->willReturn($this->token);
324+
325+
$this->tokenStorage->expects($this->once())->method('setToken')->with($this->token);
326+
327+
$authenticator->expects($this->any())
328+
->method('onAuthenticationSuccess')
329+
->with($this->anything(), $this->token, 'main')
330+
->willReturn($this->response);
331+
332+
$authenticator->expects($this->any())
333+
->method('onAuthenticationSuccess')
334+
->with($this->anything(), $this->token, 'main')
335+
->willReturn($this->response);
336+
337+
$logger = new class() extends AbstractLogger {
338+
public $logContexts = [];
339+
340+
public function log($level, $message, array $context = []): void
341+
{
342+
if ($context['authenticator'] ?? false) {
343+
$this->logContexts[] = $context;
344+
}
345+
}
346+
};
347+
348+
$manager = $this->createManager([$authenticator], 'main', true, [], $logger);
349+
$response = $manager->authenticateRequest($this->request);
350+
$this->assertSame($this->response, $response);
351+
$this->assertStringContainsString('Mock_TestInteractiveAuthenticator', $logger->logContexts[0]['authenticator']);
352+
}
353+
313354
private function createAuthenticator($supports = true)
314355
{
315356
$authenticator = $this->createMock(TestInteractiveAuthenticator::class);
@@ -318,9 +359,9 @@ private function createAuthenticator($supports = true)
318359
return $authenticator;
319360
}
320361

321-
private function createManager($authenticators, $firewallName = 'main', $eraseCredentials = true, array $requiredBadges = [])
362+
private function createManager($authenticators, $firewallName = 'main', $eraseCredentials = true, array $requiredBadges = [], LoggerInterface $logger = null)
322363
{
323-
return new AuthenticatorManager($authenticators, $this->tokenStorage, $this->eventDispatcher, $firewallName, null, $eraseCredentials, true, $requiredBadges);
364+
return new AuthenticatorManager($authenticators, $this->tokenStorage, $this->eventDispatcher, $firewallName, $logger, $eraseCredentials, true, $requiredBadges);
324365
}
325366
}
326367

0 commit comments

Comments
 (0)