LoginLinkAuthenticator.php 3.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  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\Authenticator;
  11. use Symfony\Component\HttpFoundation\Request;
  12. use Symfony\Component\HttpFoundation\Response;
  13. use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
  14. use Symfony\Component\Security\Core\Exception\AuthenticationException;
  15. use Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface;
  16. use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface;
  17. use Symfony\Component\Security\Http\Authenticator\Passport\Badge\RememberMeBadge;
  18. use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
  19. use Symfony\Component\Security\Http\Authenticator\Passport\PassportInterface;
  20. use Symfony\Component\Security\Http\Authenticator\Passport\SelfValidatingPassport;
  21. use Symfony\Component\Security\Http\HttpUtils;
  22. use Symfony\Component\Security\Http\LoginLink\Exception\InvalidLoginLinkAuthenticationException;
  23. use Symfony\Component\Security\Http\LoginLink\Exception\InvalidLoginLinkExceptionInterface;
  24. use Symfony\Component\Security\Http\LoginLink\LoginLinkHandlerInterface;
  25. /**
  26. * @author Ryan Weaver <ryan@symfonycasts.com>
  27. * @experimental in 5.2
  28. */
  29. final class LoginLinkAuthenticator extends AbstractAuthenticator implements InteractiveAuthenticatorInterface
  30. {
  31. private $loginLinkHandler;
  32. private $httpUtils;
  33. private $successHandler;
  34. private $failureHandler;
  35. private $options;
  36. public function __construct(LoginLinkHandlerInterface $loginLinkHandler, HttpUtils $httpUtils, AuthenticationSuccessHandlerInterface $successHandler, AuthenticationFailureHandlerInterface $failureHandler, array $options)
  37. {
  38. $this->loginLinkHandler = $loginLinkHandler;
  39. $this->httpUtils = $httpUtils;
  40. $this->successHandler = $successHandler;
  41. $this->failureHandler = $failureHandler;
  42. $this->options = $options + ['check_post_only' => false];
  43. }
  44. public function supports(Request $request): ?bool
  45. {
  46. return ($this->options['check_post_only'] ? $request->isMethod('POST') : true)
  47. && $this->httpUtils->checkRequestPath($request, $this->options['check_route']);
  48. }
  49. public function authenticate(Request $request): PassportInterface
  50. {
  51. $username = $request->get('user');
  52. if (!$username) {
  53. throw new InvalidLoginLinkAuthenticationException('Missing user from link.');
  54. }
  55. return new SelfValidatingPassport(
  56. new UserBadge($username, function () use ($request) {
  57. try {
  58. $user = $this->loginLinkHandler->consumeLoginLink($request);
  59. } catch (InvalidLoginLinkExceptionInterface $e) {
  60. throw new InvalidLoginLinkAuthenticationException('Login link could not be validated.', 0, $e);
  61. }
  62. return $user;
  63. }),
  64. [new RememberMeBadge()]
  65. );
  66. }
  67. public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response
  68. {
  69. return $this->successHandler->onAuthenticationSuccess($request, $token);
  70. }
  71. public function onAuthenticationFailure(Request $request, AuthenticationException $exception): Response
  72. {
  73. return $this->failureHandler->onAuthenticationFailure($request, $exception);
  74. }
  75. public function isInteractive(): bool
  76. {
  77. return true;
  78. }
  79. }