vendor/symfony/security-guard/GuardAuthenticatorHandler.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\Guard;
  11. use Symfony\Component\HttpFoundation\Request;
  12. use Symfony\Component\HttpFoundation\Response;
  13. use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
  14. use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
  15. use Symfony\Component\Security\Core\Exception\AuthenticationException;
  16. use Symfony\Component\Security\Core\User\UserInterface;
  17. use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
  18. use Symfony\Component\Security\Http\SecurityEvents;
  19. use Symfony\Component\Security\Http\Session\SessionAuthenticationStrategyInterface;
  20. use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
  21. trigger_deprecation('symfony/security-guard', '5.3', 'The "%s" class is deprecated, use the new authenticator system instead.', GuardAuthenticatorHandler::class);
  22. /**
  23. * A utility class that does much of the *work* during the guard authentication process.
  24. *
  25. * By having the logic here instead of the listener, more of the process
  26. * can be called directly (e.g. for manual authentication) or overridden.
  27. *
  28. * @author Ryan Weaver <ryan@knpuniversity.com>
  29. *
  30. * @final
  31. *
  32. * @deprecated since Symfony 5.3, use the new authenticator system instead
  33. */
  34. class GuardAuthenticatorHandler
  35. {
  36. private $tokenStorage;
  37. private $dispatcher;
  38. private $sessionStrategy;
  39. private $statelessProviderKeys;
  40. /**
  41. * @param array $statelessProviderKeys An array of provider/firewall keys that are "stateless" and so do not need the session migrated on success
  42. */
  43. public function __construct(TokenStorageInterface $tokenStorage, ?EventDispatcherInterface $eventDispatcher = null, array $statelessProviderKeys = [])
  44. {
  45. $this->tokenStorage = $tokenStorage;
  46. $this->dispatcher = $eventDispatcher;
  47. $this->statelessProviderKeys = $statelessProviderKeys;
  48. }
  49. /**
  50. * Authenticates the given token in the system.
  51. */
  52. public function authenticateWithToken(TokenInterface $token, Request $request, ?string $providerKey = null, ?TokenInterface $previousToken = null)
  53. {
  54. $this->migrateSession($request, $token, $providerKey, 3 < \func_num_args() ? $previousToken : $this->tokenStorage->getToken());
  55. $this->tokenStorage->setToken($token);
  56. if (null !== $this->dispatcher) {
  57. $loginEvent = new InteractiveLoginEvent($request, $token);
  58. $this->dispatcher->dispatch($loginEvent, SecurityEvents::INTERACTIVE_LOGIN);
  59. }
  60. }
  61. /**
  62. * Returns the "on success" response for the given GuardAuthenticator.
  63. */
  64. public function handleAuthenticationSuccess(TokenInterface $token, Request $request, AuthenticatorInterface $guardAuthenticator, string $providerKey): ?Response
  65. {
  66. $response = $guardAuthenticator->onAuthenticationSuccess($request, $token, $providerKey);
  67. // check that it's a Response or null
  68. if ($response instanceof Response || null === $response) {
  69. return $response;
  70. }
  71. throw new \UnexpectedValueException(sprintf('The "%s::onAuthenticationSuccess()" method must return null or a Response object. You returned "%s".', \get_class($guardAuthenticator), get_debug_type($response)));
  72. }
  73. /**
  74. * Convenience method for authenticating the user and returning the
  75. * Response *if any* for success.
  76. */
  77. public function authenticateUserAndHandleSuccess(UserInterface $user, Request $request, AuthenticatorInterface $authenticator, string $providerKey): ?Response
  78. {
  79. // create an authenticated token for the User
  80. $token = $authenticator->createAuthenticatedToken($user, $providerKey);
  81. // authenticate this in the system
  82. $this->authenticateWithToken($token, $request, $providerKey, $this->tokenStorage->getToken());
  83. // return the success metric
  84. return $this->handleAuthenticationSuccess($token, $request, $authenticator, $providerKey);
  85. }
  86. /**
  87. * Handles an authentication failure and returns the Response for the
  88. * GuardAuthenticator.
  89. */
  90. public function handleAuthenticationFailure(AuthenticationException $authenticationException, Request $request, AuthenticatorInterface $guardAuthenticator, string $providerKey): ?Response
  91. {
  92. $response = $guardAuthenticator->onAuthenticationFailure($request, $authenticationException);
  93. if ($response instanceof Response || null === $response) {
  94. // returning null is ok, it means they want the request to continue
  95. return $response;
  96. }
  97. throw new \UnexpectedValueException(sprintf('The "%s::onAuthenticationFailure()" method must return null or a Response object. You returned "%s".', \get_class($guardAuthenticator), get_debug_type($response)));
  98. }
  99. /**
  100. * Call this method if your authentication token is stored to a session.
  101. *
  102. * @final
  103. */
  104. public function setSessionAuthenticationStrategy(SessionAuthenticationStrategyInterface $sessionStrategy)
  105. {
  106. $this->sessionStrategy = $sessionStrategy;
  107. }
  108. private function migrateSession(Request $request, TokenInterface $token, ?string $providerKey, ?TokenInterface $previousToken)
  109. {
  110. if (\in_array($providerKey, $this->statelessProviderKeys, true) || !$this->sessionStrategy || !$request->hasSession() || !$request->hasPreviousSession()) {
  111. return;
  112. }
  113. if ($previousToken) {
  114. $user = method_exists($token, 'getUserIdentifier') ? $token->getUserIdentifier() : $token->getUsername();
  115. $previousUser = method_exists($previousToken, 'getUserIdentifier') ? $previousToken->getUserIdentifier() : $previousToken->getUsername();
  116. if ('' !== ($user ?? '') && $user === $previousUser) {
  117. return;
  118. }
  119. }
  120. $this->sessionStrategy->onAuthentication($request, $token);
  121. }
  122. }