vendor/symfony/security-http/Firewall/BasicAuthenticationListener.php line 25

Open in your IDE?
  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien@symfony.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Symfony\Component\Security\Http\Firewall;
  11. use Psr\Log\LoggerInterface;
  12. use Symfony\Component\HttpFoundation\Request;
  13. use Symfony\Component\HttpKernel\Event\RequestEvent;
  14. use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
  15. use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
  16. use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
  17. use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
  18. use Symfony\Component\Security\Core\Exception\AuthenticationException;
  19. use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface;
  20. use Symfony\Component\Security\Http\Session\SessionAuthenticationStrategyInterface;
  21. trigger_deprecation('symfony/security-http', '5.3', 'The "%s" class is deprecated, use the new authenticator system instead.', AnonymousAuthenticationListener::class);
  22. /**
  23. * BasicAuthenticationListener implements Basic HTTP authentication.
  24. *
  25. * @author Fabien Potencier <fabien@symfony.com>
  26. *
  27. * @final
  28. *
  29. * @deprecated since Symfony 5.3, use the new authenticator system instead
  30. */
  31. class BasicAuthenticationListener extends AbstractListener
  32. {
  33. private $tokenStorage;
  34. private $authenticationManager;
  35. private $providerKey;
  36. private $authenticationEntryPoint;
  37. private $logger;
  38. private $ignoreFailure;
  39. private $sessionStrategy;
  40. public function __construct(TokenStorageInterface $tokenStorage, AuthenticationManagerInterface $authenticationManager, string $providerKey, AuthenticationEntryPointInterface $authenticationEntryPoint, ?LoggerInterface $logger = null)
  41. {
  42. if (empty($providerKey)) {
  43. throw new \InvalidArgumentException('$providerKey must not be empty.');
  44. }
  45. $this->tokenStorage = $tokenStorage;
  46. $this->authenticationManager = $authenticationManager;
  47. $this->providerKey = $providerKey;
  48. $this->authenticationEntryPoint = $authenticationEntryPoint;
  49. $this->logger = $logger;
  50. $this->ignoreFailure = false;
  51. }
  52. /**
  53. * {@inheritdoc}
  54. */
  55. public function supports(Request $request): ?bool
  56. {
  57. return null !== $request->headers->get('PHP_AUTH_USER');
  58. }
  59. /**
  60. * Handles basic authentication.
  61. */
  62. public function authenticate(RequestEvent $event)
  63. {
  64. $request = $event->getRequest();
  65. if (null === $username = $request->headers->get('PHP_AUTH_USER')) {
  66. return;
  67. }
  68. if (null !== $token = $this->tokenStorage->getToken()) {
  69. // @deprecated since Symfony 5.3, change to $token->getUserIdentifier() in 6.0
  70. if ($token instanceof UsernamePasswordToken && $token->isAuthenticated(false) && (method_exists($token, 'getUserIdentifier') ? $token->getUserIdentifier() : $token->getUsername()) === $username) {
  71. return;
  72. }
  73. }
  74. if (null !== $this->logger) {
  75. $this->logger->info('Basic authentication Authorization header found for user.', ['username' => $username]);
  76. }
  77. try {
  78. $previousToken = $token;
  79. $token = $this->authenticationManager->authenticate(new UsernamePasswordToken($username, $request->headers->get('PHP_AUTH_PW'), $this->providerKey));
  80. $this->migrateSession($request, $token, $previousToken);
  81. $this->tokenStorage->setToken($token);
  82. } catch (AuthenticationException $e) {
  83. $token = $this->tokenStorage->getToken();
  84. if ($token instanceof UsernamePasswordToken && $this->providerKey === $token->getFirewallName()) {
  85. $this->tokenStorage->setToken(null);
  86. }
  87. if (null !== $this->logger) {
  88. $this->logger->info('Basic authentication failed for user.', ['username' => $username, 'exception' => $e]);
  89. }
  90. if ($this->ignoreFailure) {
  91. return;
  92. }
  93. $event->setResponse($this->authenticationEntryPoint->start($request, $e));
  94. }
  95. }
  96. /**
  97. * Call this method if your authentication token is stored to a session.
  98. *
  99. * @final
  100. */
  101. public function setSessionAuthenticationStrategy(SessionAuthenticationStrategyInterface $sessionStrategy)
  102. {
  103. $this->sessionStrategy = $sessionStrategy;
  104. }
  105. private function migrateSession(Request $request, TokenInterface $token, ?TokenInterface $previousToken)
  106. {
  107. if (!$this->sessionStrategy || !$request->hasSession() || !$request->hasPreviousSession()) {
  108. return;
  109. }
  110. if ($previousToken) {
  111. $user = method_exists($token, 'getUserIdentifier') ? $token->getUserIdentifier() : $token->getUsername();
  112. $previousUser = method_exists($previousToken, 'getUserIdentifier') ? $previousToken->getUserIdentifier() : $previousToken->getUsername();
  113. if ('' !== ($user ?? '') && $user === $previousUser) {
  114. return;
  115. }
  116. }
  117. $this->sessionStrategy->onAuthentication($request, $token);
  118. }
  119. }