login consent app sql
This commit is contained in:
49
vendor/symfony/security-http/AccessMap.php
vendored
Normal file
49
vendor/symfony/security-http/AccessMap.php
vendored
Normal file
@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\RequestMatcherInterface;
|
||||
|
||||
/**
|
||||
* AccessMap allows configuration of different access control rules for
|
||||
* specific parts of the website.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class AccessMap implements AccessMapInterface
|
||||
{
|
||||
private $map = [];
|
||||
|
||||
/**
|
||||
* @param array $attributes An array of attributes to pass to the access decision manager (like roles)
|
||||
* @param string|null $channel The channel to enforce (http, https, or null)
|
||||
*/
|
||||
public function add(RequestMatcherInterface $requestMatcher, array $attributes = [], string $channel = null)
|
||||
{
|
||||
$this->map[] = [$requestMatcher, $attributes, $channel];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getPatterns(Request $request)
|
||||
{
|
||||
foreach ($this->map as $elements) {
|
||||
if (null === $elements[0] || $elements[0]->matches($request)) {
|
||||
return [$elements[1], $elements[2]];
|
||||
}
|
||||
}
|
||||
|
||||
return [null, null];
|
||||
}
|
||||
}
|
31
vendor/symfony/security-http/AccessMapInterface.php
vendored
Normal file
31
vendor/symfony/security-http/AccessMapInterface.php
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
/**
|
||||
* AccessMap allows configuration of different access control rules for
|
||||
* specific parts of the website.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Kris Wallsmith <kris@symfony.com>
|
||||
*/
|
||||
interface AccessMapInterface
|
||||
{
|
||||
/**
|
||||
* Returns security attributes and required channel for the supplied request.
|
||||
*
|
||||
* @return array{0: array|null, 1: string|null} A tuple of security attributes and the required channel
|
||||
*/
|
||||
public function getPatterns(Request $request);
|
||||
}
|
20
vendor/symfony/security-http/Attribute/CurrentUser.php
vendored
Normal file
20
vendor/symfony/security-http/Attribute/CurrentUser.php
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\Attribute;
|
||||
|
||||
/**
|
||||
* Indicates that a controller argument should receive the current logged user.
|
||||
*/
|
||||
#[\Attribute(\Attribute::TARGET_PARAMETER)]
|
||||
class CurrentUser
|
||||
{
|
||||
}
|
37
vendor/symfony/security-http/Authentication/AuthenticationFailureHandlerInterface.php
vendored
Normal file
37
vendor/symfony/security-http/Authentication/AuthenticationFailureHandlerInterface.php
vendored
Normal file
@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\Authentication;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Security\Core\Exception\AuthenticationException;
|
||||
|
||||
/**
|
||||
* Interface for custom authentication failure handlers.
|
||||
*
|
||||
* If you want to customize the failure handling process, instead of
|
||||
* overwriting the respective listener globally, you can set a custom failure
|
||||
* handler which implements this interface.
|
||||
*
|
||||
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
|
||||
*/
|
||||
interface AuthenticationFailureHandlerInterface
|
||||
{
|
||||
/**
|
||||
* This is called when an interactive authentication attempt fails. This is
|
||||
* called by authentication listeners inheriting from
|
||||
* AbstractAuthenticationListener.
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function onAuthenticationFailure(Request $request, AuthenticationException $exception);
|
||||
}
|
37
vendor/symfony/security-http/Authentication/AuthenticationSuccessHandlerInterface.php
vendored
Normal file
37
vendor/symfony/security-http/Authentication/AuthenticationSuccessHandlerInterface.php
vendored
Normal file
@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\Authentication;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||
|
||||
/**
|
||||
* Interface for a custom authentication success handler.
|
||||
*
|
||||
* If you want to customize the success handling process, instead of
|
||||
* overwriting the respective listener globally, you can set a custom success
|
||||
* handler which implements this interface.
|
||||
*
|
||||
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
|
||||
*/
|
||||
interface AuthenticationSuccessHandlerInterface
|
||||
{
|
||||
/**
|
||||
* This is called when an interactive authentication attempt succeeds. This
|
||||
* is called by authentication listeners inheriting from
|
||||
* AbstractAuthenticationListener.
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function onAuthenticationSuccess(Request $request, TokenInterface $token);
|
||||
}
|
81
vendor/symfony/security-http/Authentication/AuthenticationUtils.php
vendored
Normal file
81
vendor/symfony/security-http/Authentication/AuthenticationUtils.php
vendored
Normal file
@ -0,0 +1,81 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\Authentication;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
use Symfony\Component\Security\Core\Exception\AuthenticationException;
|
||||
use Symfony\Component\Security\Core\Security;
|
||||
|
||||
/**
|
||||
* Extracts Security Errors from Request.
|
||||
*
|
||||
* @author Boris Vujicic <boris.vujicic@gmail.com>
|
||||
*/
|
||||
class AuthenticationUtils
|
||||
{
|
||||
private $requestStack;
|
||||
|
||||
public function __construct(RequestStack $requestStack)
|
||||
{
|
||||
$this->requestStack = $requestStack;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return AuthenticationException|null
|
||||
*/
|
||||
public function getLastAuthenticationError(bool $clearSession = true)
|
||||
{
|
||||
$request = $this->getRequest();
|
||||
$authenticationException = null;
|
||||
|
||||
if ($request->attributes->has(Security::AUTHENTICATION_ERROR)) {
|
||||
$authenticationException = $request->attributes->get(Security::AUTHENTICATION_ERROR);
|
||||
} elseif ($request->hasSession() && ($session = $request->getSession())->has(Security::AUTHENTICATION_ERROR)) {
|
||||
$authenticationException = $session->get(Security::AUTHENTICATION_ERROR);
|
||||
|
||||
if ($clearSession) {
|
||||
$session->remove(Security::AUTHENTICATION_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
return $authenticationException;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getLastUsername()
|
||||
{
|
||||
$request = $this->getRequest();
|
||||
|
||||
if ($request->attributes->has(Security::LAST_USERNAME)) {
|
||||
return $request->attributes->get(Security::LAST_USERNAME, '');
|
||||
}
|
||||
|
||||
return $request->hasSession() ? $request->getSession()->get(Security::LAST_USERNAME, '') : '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \LogicException
|
||||
*/
|
||||
private function getRequest(): Request
|
||||
{
|
||||
$request = $this->requestStack->getCurrentRequest();
|
||||
|
||||
if (null === $request) {
|
||||
throw new \LogicException('Request should exist so it can be processed for error.');
|
||||
}
|
||||
|
||||
return $request;
|
||||
}
|
||||
}
|
285
vendor/symfony/security-http/Authentication/AuthenticatorManager.php
vendored
Normal file
285
vendor/symfony/security-http/Authentication/AuthenticatorManager.php
vendored
Normal file
@ -0,0 +1,285 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\Authentication;
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||
use Symfony\Component\Security\Core\AuthenticationEvents;
|
||||
use Symfony\Component\Security\Core\Event\AuthenticationSuccessEvent;
|
||||
use Symfony\Component\Security\Core\Exception\AccountStatusException;
|
||||
use Symfony\Component\Security\Core\Exception\AuthenticationException;
|
||||
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
|
||||
use Symfony\Component\Security\Core\Exception\CustomUserMessageAccountStatusException;
|
||||
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
|
||||
use Symfony\Component\Security\Core\User\UserInterface;
|
||||
use Symfony\Component\Security\Http\Authenticator\AuthenticatorInterface;
|
||||
use Symfony\Component\Security\Http\Authenticator\Debug\TraceableAuthenticator;
|
||||
use Symfony\Component\Security\Http\Authenticator\InteractiveAuthenticatorInterface;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\BadgeInterface;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\PassportInterface;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\SelfValidatingPassport;
|
||||
use Symfony\Component\Security\Http\Event\AuthenticationTokenCreatedEvent;
|
||||
use Symfony\Component\Security\Http\Event\CheckPassportEvent;
|
||||
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
|
||||
use Symfony\Component\Security\Http\Event\LoginFailureEvent;
|
||||
use Symfony\Component\Security\Http\Event\LoginSuccessEvent;
|
||||
use Symfony\Component\Security\Http\SecurityEvents;
|
||||
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
|
||||
|
||||
/**
|
||||
* @author Wouter de Jong <wouter@wouterj.nl>
|
||||
* @author Ryan Weaver <ryan@symfonycasts.com>
|
||||
* @author Amaury Leroux de Lens <amaury@lerouxdelens.com>
|
||||
*/
|
||||
class AuthenticatorManager implements AuthenticatorManagerInterface, UserAuthenticatorInterface
|
||||
{
|
||||
private $authenticators;
|
||||
private $tokenStorage;
|
||||
private $eventDispatcher;
|
||||
private $eraseCredentials;
|
||||
private $logger;
|
||||
private $firewallName;
|
||||
private $hideUserNotFoundExceptions;
|
||||
private $requiredBadges;
|
||||
|
||||
/**
|
||||
* @param iterable<mixed, AuthenticatorInterface> $authenticators
|
||||
*/
|
||||
public function __construct(iterable $authenticators, TokenStorageInterface $tokenStorage, EventDispatcherInterface $eventDispatcher, string $firewallName, LoggerInterface $logger = null, bool $eraseCredentials = true, bool $hideUserNotFoundExceptions = true, array $requiredBadges = [])
|
||||
{
|
||||
$this->authenticators = $authenticators;
|
||||
$this->tokenStorage = $tokenStorage;
|
||||
$this->eventDispatcher = $eventDispatcher;
|
||||
$this->firewallName = $firewallName;
|
||||
$this->logger = $logger;
|
||||
$this->eraseCredentials = $eraseCredentials;
|
||||
$this->hideUserNotFoundExceptions = $hideUserNotFoundExceptions;
|
||||
$this->requiredBadges = $requiredBadges;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param BadgeInterface[] $badges Optionally, pass some Passport badges to use for the manual login
|
||||
*/
|
||||
public function authenticateUser(UserInterface $user, AuthenticatorInterface $authenticator, Request $request, array $badges = []): ?Response
|
||||
{
|
||||
// create an authentication token for the User
|
||||
// @deprecated since Symfony 5.3, change to $user->getUserIdentifier() in 6.0
|
||||
$passport = new SelfValidatingPassport(new UserBadge(method_exists($user, 'getUserIdentifier') ? $user->getUserIdentifier() : $user->getUsername(), function () use ($user) { return $user; }), $badges);
|
||||
$token = method_exists($authenticator, 'createToken') ? $authenticator->createToken($passport, $this->firewallName) : $authenticator->createAuthenticatedToken($passport, $this->firewallName);
|
||||
|
||||
// announce the authentication token
|
||||
$token = $this->eventDispatcher->dispatch(new AuthenticationTokenCreatedEvent($token, $passport))->getAuthenticatedToken();
|
||||
|
||||
// authenticate this in the system
|
||||
return $this->handleAuthenticationSuccess($token, $passport, $request, $authenticator);
|
||||
}
|
||||
|
||||
public function supports(Request $request): ?bool
|
||||
{
|
||||
if (null !== $this->logger) {
|
||||
$context = ['firewall_name' => $this->firewallName];
|
||||
|
||||
if ($this->authenticators instanceof \Countable || \is_array($this->authenticators)) {
|
||||
$context['authenticators'] = \count($this->authenticators);
|
||||
}
|
||||
|
||||
$this->logger->debug('Checking for authenticator support.', $context);
|
||||
}
|
||||
|
||||
$authenticators = [];
|
||||
$skippedAuthenticators = [];
|
||||
$lazy = true;
|
||||
foreach ($this->authenticators as $authenticator) {
|
||||
if (null !== $this->logger) {
|
||||
$this->logger->debug('Checking support on authenticator.', ['firewall_name' => $this->firewallName, 'authenticator' => \get_class($authenticator)]);
|
||||
}
|
||||
|
||||
if (false !== $supports = $authenticator->supports($request)) {
|
||||
$authenticators[] = $authenticator;
|
||||
$lazy = $lazy && null === $supports;
|
||||
} else {
|
||||
if (null !== $this->logger) {
|
||||
$this->logger->debug('Authenticator does not support the request.', ['firewall_name' => $this->firewallName, 'authenticator' => \get_class($authenticator)]);
|
||||
}
|
||||
$skippedAuthenticators[] = $authenticator;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$authenticators) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$request->attributes->set('_security_authenticators', $authenticators);
|
||||
$request->attributes->set('_security_skipped_authenticators', $skippedAuthenticators);
|
||||
|
||||
return $lazy ? null : true;
|
||||
}
|
||||
|
||||
public function authenticateRequest(Request $request): ?Response
|
||||
{
|
||||
$authenticators = $request->attributes->get('_security_authenticators');
|
||||
$request->attributes->remove('_security_authenticators');
|
||||
$request->attributes->remove('_security_skipped_authenticators');
|
||||
|
||||
if (!$authenticators) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this->executeAuthenticators($authenticators, $request);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param AuthenticatorInterface[] $authenticators
|
||||
*/
|
||||
private function executeAuthenticators(array $authenticators, Request $request): ?Response
|
||||
{
|
||||
foreach ($authenticators as $authenticator) {
|
||||
// recheck if the authenticator still supports the listener. supports() is called
|
||||
// eagerly (before token storage is initialized), whereas authenticate() is called
|
||||
// lazily (after initialization).
|
||||
if (false === $authenticator->supports($request)) {
|
||||
if (null !== $this->logger) {
|
||||
$this->logger->debug('Skipping the "{authenticator}" authenticator as it did not support the request.', ['authenticator' => \get_class($authenticator instanceof TraceableAuthenticator ? $authenticator->getAuthenticator() : $authenticator)]);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
$response = $this->executeAuthenticator($authenticator, $request);
|
||||
if (null !== $response) {
|
||||
if (null !== $this->logger) {
|
||||
$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)]);
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private function executeAuthenticator(AuthenticatorInterface $authenticator, Request $request): ?Response
|
||||
{
|
||||
$passport = null;
|
||||
|
||||
try {
|
||||
// get the passport from the Authenticator
|
||||
$passport = $authenticator->authenticate($request);
|
||||
|
||||
// check the passport (e.g. password checking)
|
||||
$event = new CheckPassportEvent($authenticator, $passport);
|
||||
$this->eventDispatcher->dispatch($event);
|
||||
|
||||
// check if all badges are resolved
|
||||
$resolvedBadges = [];
|
||||
foreach ($passport->getBadges() as $badge) {
|
||||
if (!$badge->isResolved()) {
|
||||
throw new BadCredentialsException(sprintf('Authentication failed: Security badge "%s" is not resolved, did you forget to register the correct listeners?', get_debug_type($badge)));
|
||||
}
|
||||
|
||||
$resolvedBadges[] = \get_class($badge);
|
||||
}
|
||||
|
||||
$missingRequiredBadges = array_diff($this->requiredBadges, $resolvedBadges);
|
||||
if ($missingRequiredBadges) {
|
||||
throw new BadCredentialsException(sprintf('Authentication failed; Some badges marked as required by the firewall config are not available on the passport: "%s".', implode('", "', $missingRequiredBadges)));
|
||||
}
|
||||
|
||||
// create the authentication token
|
||||
$authenticatedToken = method_exists($authenticator, 'createToken') ? $authenticator->createToken($passport, $this->firewallName) : $authenticator->createAuthenticatedToken($passport, $this->firewallName);
|
||||
|
||||
// announce the authentication token
|
||||
$authenticatedToken = $this->eventDispatcher->dispatch(new AuthenticationTokenCreatedEvent($authenticatedToken, $passport))->getAuthenticatedToken();
|
||||
|
||||
if (true === $this->eraseCredentials) {
|
||||
$authenticatedToken->eraseCredentials();
|
||||
}
|
||||
|
||||
$this->eventDispatcher->dispatch(new AuthenticationSuccessEvent($authenticatedToken), AuthenticationEvents::AUTHENTICATION_SUCCESS);
|
||||
|
||||
if (null !== $this->logger) {
|
||||
$this->logger->info('Authenticator successful!', ['token' => $authenticatedToken, 'authenticator' => \get_class($authenticator instanceof TraceableAuthenticator ? $authenticator->getAuthenticator() : $authenticator)]);
|
||||
}
|
||||
} catch (AuthenticationException $e) {
|
||||
// oh no! Authentication failed!
|
||||
$response = $this->handleAuthenticationFailure($e, $request, $authenticator, $passport);
|
||||
if ($response instanceof Response) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// success! (sets the token on the token storage, etc)
|
||||
$response = $this->handleAuthenticationSuccess($authenticatedToken, $passport, $request, $authenticator);
|
||||
if ($response instanceof Response) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
if (null !== $this->logger) {
|
||||
$this->logger->debug('Authenticator set no success response: request continues.', ['authenticator' => \get_class($authenticator instanceof TraceableAuthenticator ? $authenticator->getAuthenticator() : $authenticator)]);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private function handleAuthenticationSuccess(TokenInterface $authenticatedToken, PassportInterface $passport, Request $request, AuthenticatorInterface $authenticator): ?Response
|
||||
{
|
||||
// @deprecated since Symfony 5.3
|
||||
$user = $authenticatedToken->getUser();
|
||||
if ($user instanceof UserInterface && !method_exists($user, 'getUserIdentifier')) {
|
||||
trigger_deprecation('symfony/security-core', '5.3', 'Not implementing method "getUserIdentifier(): string" in user class "%s" is deprecated. This method will replace "getUsername()" in Symfony 6.0.', get_debug_type($authenticatedToken->getUser()));
|
||||
}
|
||||
|
||||
$this->tokenStorage->setToken($authenticatedToken);
|
||||
|
||||
$response = $authenticator->onAuthenticationSuccess($request, $authenticatedToken, $this->firewallName);
|
||||
if ($authenticator instanceof InteractiveAuthenticatorInterface && $authenticator->isInteractive()) {
|
||||
$loginEvent = new InteractiveLoginEvent($request, $authenticatedToken);
|
||||
$this->eventDispatcher->dispatch($loginEvent, SecurityEvents::INTERACTIVE_LOGIN);
|
||||
}
|
||||
|
||||
$this->eventDispatcher->dispatch($loginSuccessEvent = new LoginSuccessEvent($authenticator, $passport, $authenticatedToken, $request, $response, $this->firewallName));
|
||||
|
||||
return $loginSuccessEvent->getResponse();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles an authentication failure and returns the Response for the authenticator.
|
||||
*/
|
||||
private function handleAuthenticationFailure(AuthenticationException $authenticationException, Request $request, AuthenticatorInterface $authenticator, ?PassportInterface $passport): ?Response
|
||||
{
|
||||
if (null !== $this->logger) {
|
||||
$this->logger->info('Authenticator failed.', ['exception' => $authenticationException, 'authenticator' => \get_class($authenticator instanceof TraceableAuthenticator ? $authenticator->getAuthenticator() : $authenticator)]);
|
||||
}
|
||||
|
||||
// Avoid leaking error details in case of invalid user (e.g. user not found or invalid account status)
|
||||
// to prevent user enumeration via response content comparison
|
||||
if ($this->hideUserNotFoundExceptions && ($authenticationException instanceof UsernameNotFoundException || ($authenticationException instanceof AccountStatusException && !$authenticationException instanceof CustomUserMessageAccountStatusException))) {
|
||||
$authenticationException = new BadCredentialsException('Bad credentials.', 0, $authenticationException);
|
||||
}
|
||||
|
||||
$response = $authenticator->onAuthenticationFailure($request, $authenticationException);
|
||||
if (null !== $response && null !== $this->logger) {
|
||||
$this->logger->debug('The "{authenticator}" authenticator set the failure response.', ['authenticator' => \get_class($authenticator instanceof TraceableAuthenticator ? $authenticator->getAuthenticator() : $authenticator)]);
|
||||
}
|
||||
|
||||
$this->eventDispatcher->dispatch($loginFailureEvent = new LoginFailureEvent($authenticationException, $authenticator, $request, $response, $this->firewallName, $passport));
|
||||
|
||||
// returning null is ok, it means they want the request to continue
|
||||
return $loginFailureEvent->getResponse();
|
||||
}
|
||||
}
|
35
vendor/symfony/security-http/Authentication/AuthenticatorManagerInterface.php
vendored
Normal file
35
vendor/symfony/security-http/Authentication/AuthenticatorManagerInterface.php
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\Authentication;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Security\Http\Firewall\FirewallListenerInterface;
|
||||
|
||||
/**
|
||||
* @author Wouter de Jong <wouter@wouterj.nl>
|
||||
* @author Ryan Weaver <ryan@symfonycasts.com>
|
||||
*/
|
||||
interface AuthenticatorManagerInterface
|
||||
{
|
||||
/**
|
||||
* Called to see if authentication should be attempted on this request.
|
||||
*
|
||||
* @see FirewallListenerInterface::supports()
|
||||
*/
|
||||
public function supports(Request $request): ?bool;
|
||||
|
||||
/**
|
||||
* Tries to authenticate the request and returns a response - if any authenticator set one.
|
||||
*/
|
||||
public function authenticateRequest(Request $request): ?Response;
|
||||
}
|
42
vendor/symfony/security-http/Authentication/CustomAuthenticationFailureHandler.php
vendored
Normal file
42
vendor/symfony/security-http/Authentication/CustomAuthenticationFailureHandler.php
vendored
Normal file
@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\Authentication;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\Security\Core\Exception\AuthenticationException;
|
||||
|
||||
/**
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class CustomAuthenticationFailureHandler implements AuthenticationFailureHandlerInterface
|
||||
{
|
||||
private $handler;
|
||||
|
||||
/**
|
||||
* @param array $options Options for processing a successful authentication attempt
|
||||
*/
|
||||
public function __construct(AuthenticationFailureHandlerInterface $handler, array $options)
|
||||
{
|
||||
$this->handler = $handler;
|
||||
if (method_exists($handler, 'setOptions')) {
|
||||
$this->handler->setOptions($options);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function onAuthenticationFailure(Request $request, AuthenticationException $exception)
|
||||
{
|
||||
return $this->handler->onAuthenticationFailure($request, $exception);
|
||||
}
|
||||
}
|
50
vendor/symfony/security-http/Authentication/CustomAuthenticationSuccessHandler.php
vendored
Normal file
50
vendor/symfony/security-http/Authentication/CustomAuthenticationSuccessHandler.php
vendored
Normal file
@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\Authentication;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||
|
||||
/**
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class CustomAuthenticationSuccessHandler implements AuthenticationSuccessHandlerInterface
|
||||
{
|
||||
private $handler;
|
||||
|
||||
/**
|
||||
* @param array $options Options for processing a successful authentication attempt
|
||||
*/
|
||||
public function __construct(AuthenticationSuccessHandlerInterface $handler, array $options, string $firewallName)
|
||||
{
|
||||
$this->handler = $handler;
|
||||
if (method_exists($handler, 'setOptions')) {
|
||||
$this->handler->setOptions($options);
|
||||
}
|
||||
|
||||
if (method_exists($handler, 'setFirewallName')) {
|
||||
$this->handler->setFirewallName($firewallName);
|
||||
} elseif (method_exists($handler, 'setProviderKey')) {
|
||||
trigger_deprecation('symfony/security-http', '5.2', 'Method "%s::setProviderKey()" is deprecated, rename the method to "setFirewallName()" instead.', \get_class($handler));
|
||||
|
||||
$this->handler->setProviderKey($firewallName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function onAuthenticationSuccess(Request $request, TokenInterface $token)
|
||||
{
|
||||
return $this->handler->onAuthenticationSuccess($request, $token);
|
||||
}
|
||||
}
|
100
vendor/symfony/security-http/Authentication/DefaultAuthenticationFailureHandler.php
vendored
Normal file
100
vendor/symfony/security-http/Authentication/DefaultAuthenticationFailureHandler.php
vendored
Normal file
@ -0,0 +1,100 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\Authentication;
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\HttpKernelInterface;
|
||||
use Symfony\Component\Security\Core\Exception\AuthenticationException;
|
||||
use Symfony\Component\Security\Core\Security;
|
||||
use Symfony\Component\Security\Http\HttpUtils;
|
||||
use Symfony\Component\Security\Http\ParameterBagUtils;
|
||||
|
||||
/**
|
||||
* Class with the default authentication failure handling logic.
|
||||
*
|
||||
* Can be optionally be extended from by the developer to alter the behavior
|
||||
* while keeping the default behavior.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
|
||||
* @author Alexander <iam.asm89@gmail.com>
|
||||
*/
|
||||
class DefaultAuthenticationFailureHandler implements AuthenticationFailureHandlerInterface
|
||||
{
|
||||
protected $httpKernel;
|
||||
protected $httpUtils;
|
||||
protected $logger;
|
||||
protected $options;
|
||||
protected $defaultOptions = [
|
||||
'failure_path' => null,
|
||||
'failure_forward' => false,
|
||||
'login_path' => '/login',
|
||||
'failure_path_parameter' => '_failure_path',
|
||||
];
|
||||
|
||||
public function __construct(HttpKernelInterface $httpKernel, HttpUtils $httpUtils, array $options = [], LoggerInterface $logger = null)
|
||||
{
|
||||
$this->httpKernel = $httpKernel;
|
||||
$this->httpUtils = $httpUtils;
|
||||
$this->logger = $logger;
|
||||
$this->setOptions($options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the options.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getOptions()
|
||||
{
|
||||
return $this->options;
|
||||
}
|
||||
|
||||
public function setOptions(array $options)
|
||||
{
|
||||
$this->options = array_merge($this->defaultOptions, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function onAuthenticationFailure(Request $request, AuthenticationException $exception)
|
||||
{
|
||||
if ($failureUrl = ParameterBagUtils::getRequestParameterValue($request, $this->options['failure_path_parameter'])) {
|
||||
$this->options['failure_path'] = $failureUrl;
|
||||
}
|
||||
|
||||
if (null === $this->options['failure_path']) {
|
||||
$this->options['failure_path'] = $this->options['login_path'];
|
||||
}
|
||||
|
||||
if ($this->options['failure_forward']) {
|
||||
if (null !== $this->logger) {
|
||||
$this->logger->debug('Authentication failure, forward triggered.', ['failure_path' => $this->options['failure_path']]);
|
||||
}
|
||||
|
||||
$subRequest = $this->httpUtils->createRequest($request, $this->options['failure_path']);
|
||||
$subRequest->attributes->set(Security::AUTHENTICATION_ERROR, $exception);
|
||||
|
||||
return $this->httpKernel->handle($subRequest, HttpKernelInterface::SUB_REQUEST);
|
||||
}
|
||||
|
||||
if (null !== $this->logger) {
|
||||
$this->logger->debug('Authentication failure, redirect triggered.', ['failure_path' => $this->options['failure_path']]);
|
||||
}
|
||||
|
||||
$request->getSession()->set(Security::AUTHENTICATION_ERROR, $exception);
|
||||
|
||||
return $this->httpUtils->createRedirectResponse($request, $this->options['failure_path']);
|
||||
}
|
||||
}
|
152
vendor/symfony/security-http/Authentication/DefaultAuthenticationSuccessHandler.php
vendored
Normal file
152
vendor/symfony/security-http/Authentication/DefaultAuthenticationSuccessHandler.php
vendored
Normal file
@ -0,0 +1,152 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\Authentication;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||
use Symfony\Component\Security\Http\HttpUtils;
|
||||
use Symfony\Component\Security\Http\ParameterBagUtils;
|
||||
use Symfony\Component\Security\Http\Util\TargetPathTrait;
|
||||
|
||||
/**
|
||||
* Class with the default authentication success handling logic.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
|
||||
* @author Alexander <iam.asm89@gmail.com>
|
||||
*/
|
||||
class DefaultAuthenticationSuccessHandler implements AuthenticationSuccessHandlerInterface
|
||||
{
|
||||
use TargetPathTrait;
|
||||
|
||||
protected $httpUtils;
|
||||
protected $options;
|
||||
/** @deprecated since Symfony 5.2, use $firewallName instead */
|
||||
protected $providerKey;
|
||||
protected $firewallName;
|
||||
protected $defaultOptions = [
|
||||
'always_use_default_target_path' => false,
|
||||
'default_target_path' => '/',
|
||||
'login_path' => '/login',
|
||||
'target_path_parameter' => '_target_path',
|
||||
'use_referer' => false,
|
||||
];
|
||||
|
||||
/**
|
||||
* @param array $options Options for processing a successful authentication attempt
|
||||
*/
|
||||
public function __construct(HttpUtils $httpUtils, array $options = [])
|
||||
{
|
||||
$this->httpUtils = $httpUtils;
|
||||
$this->setOptions($options);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function onAuthenticationSuccess(Request $request, TokenInterface $token)
|
||||
{
|
||||
return $this->httpUtils->createRedirectResponse($request, $this->determineTargetUrl($request));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the options.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getOptions()
|
||||
{
|
||||
return $this->options;
|
||||
}
|
||||
|
||||
public function setOptions(array $options)
|
||||
{
|
||||
$this->options = array_merge($this->defaultOptions, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the provider key.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @deprecated since Symfony 5.2, use getFirewallName() instead
|
||||
*/
|
||||
public function getProviderKey()
|
||||
{
|
||||
if (1 !== \func_num_args() || true !== func_get_arg(0)) {
|
||||
trigger_deprecation('symfony/security-core', '5.2', 'Method "%s()" is deprecated, use "getFirewallName()" instead.', __METHOD__);
|
||||
}
|
||||
|
||||
if ($this->providerKey !== $this->firewallName) {
|
||||
trigger_deprecation('symfony/security-core', '5.2', 'The "%1$s::$providerKey" property is deprecated, use "%1$s::$firewallName" instead.', __CLASS__);
|
||||
|
||||
return $this->providerKey;
|
||||
}
|
||||
|
||||
return $this->firewallName;
|
||||
}
|
||||
|
||||
public function setProviderKey(string $providerKey)
|
||||
{
|
||||
if (2 !== \func_num_args() || true !== func_get_arg(1)) {
|
||||
trigger_deprecation('symfony/security-http', '5.2', 'Method "%s" is deprecated, use "setFirewallName()" instead.', __METHOD__);
|
||||
}
|
||||
|
||||
$this->providerKey = $providerKey;
|
||||
}
|
||||
|
||||
public function getFirewallName(): ?string
|
||||
{
|
||||
return $this->getProviderKey(true);
|
||||
}
|
||||
|
||||
public function setFirewallName(string $firewallName): void
|
||||
{
|
||||
$this->setProviderKey($firewallName, true);
|
||||
|
||||
$this->firewallName = $firewallName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the target URL according to the defined options.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function determineTargetUrl(Request $request)
|
||||
{
|
||||
if ($this->options['always_use_default_target_path']) {
|
||||
return $this->options['default_target_path'];
|
||||
}
|
||||
|
||||
if ($targetUrl = ParameterBagUtils::getRequestParameterValue($request, $this->options['target_path_parameter'])) {
|
||||
return $targetUrl;
|
||||
}
|
||||
|
||||
$firewallName = $this->getFirewallName();
|
||||
if (null !== $firewallName && $targetUrl = $this->getTargetPath($request->getSession(), $firewallName)) {
|
||||
$this->removeTargetPath($request->getSession(), $firewallName);
|
||||
|
||||
return $targetUrl;
|
||||
}
|
||||
|
||||
if ($this->options['use_referer'] && $targetUrl = $request->headers->get('Referer')) {
|
||||
if (false !== $pos = strpos($targetUrl, '?')) {
|
||||
$targetUrl = substr($targetUrl, 0, $pos);
|
||||
}
|
||||
if ($targetUrl && $targetUrl !== $this->httpUtils->generateUri($request, $this->options['login_path'])) {
|
||||
return $targetUrl;
|
||||
}
|
||||
}
|
||||
|
||||
return $this->options['default_target_path'];
|
||||
}
|
||||
}
|
33
vendor/symfony/security-http/Authentication/NoopAuthenticationManager.php
vendored
Normal file
33
vendor/symfony/security-http/Authentication/NoopAuthenticationManager.php
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\Authentication;
|
||||
|
||||
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||
|
||||
/**
|
||||
* This class is used when the authenticator system is activated.
|
||||
*
|
||||
* This is used to not break AuthenticationChecker and ContextListener when
|
||||
* using the authenticator system.
|
||||
*
|
||||
* @author Wouter de Jong <wouter@wouterj.nl>
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class NoopAuthenticationManager implements AuthenticationManagerInterface
|
||||
{
|
||||
public function authenticate(TokenInterface $token): TokenInterface
|
||||
{
|
||||
return $token;
|
||||
}
|
||||
}
|
32
vendor/symfony/security-http/Authentication/UserAuthenticatorInterface.php
vendored
Normal file
32
vendor/symfony/security-http/Authentication/UserAuthenticatorInterface.php
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\Authentication;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Security\Core\User\UserInterface;
|
||||
use Symfony\Component\Security\Http\Authenticator\AuthenticatorInterface;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\BadgeInterface;
|
||||
|
||||
/**
|
||||
* @author Wouter de Jong <wouter@wouterj.nl>
|
||||
*/
|
||||
interface UserAuthenticatorInterface
|
||||
{
|
||||
/**
|
||||
* Convenience method to programmatically login a user and return a
|
||||
* Response *if any* for success.
|
||||
*
|
||||
* @param BadgeInterface[] $badges Optionally, pass some Passport badges to use for the manual login
|
||||
*/
|
||||
public function authenticateUser(UserInterface $user, AuthenticatorInterface $authenticator, Request $request, array $badges = []): ?Response;
|
||||
}
|
55
vendor/symfony/security-http/Authenticator/AbstractAuthenticator.php
vendored
Normal file
55
vendor/symfony/security-http/Authenticator/AbstractAuthenticator.php
vendored
Normal file
@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\Authenticator;
|
||||
|
||||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||
use Symfony\Component\Security\Core\Exception\LogicException;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\Passport;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\PassportInterface;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\UserPassportInterface;
|
||||
use Symfony\Component\Security\Http\Authenticator\Token\PostAuthenticationToken;
|
||||
|
||||
/**
|
||||
* An optional base class that creates the necessary tokens for you.
|
||||
*
|
||||
* @author Ryan Weaver <ryan@symfonycasts.com>
|
||||
*/
|
||||
abstract class AbstractAuthenticator implements AuthenticatorInterface
|
||||
{
|
||||
/**
|
||||
* Shortcut to create a PostAuthenticationToken for you, if you don't really
|
||||
* care about which authenticated token you're using.
|
||||
*/
|
||||
public function createToken(Passport $passport, string $firewallName): TokenInterface
|
||||
{
|
||||
if (self::class !== (new \ReflectionMethod($this, 'createAuthenticatedToken'))->getDeclaringClass()->getName() && self::class === (new \ReflectionMethod($this, 'createToken'))->getDeclaringClass()->getName()) {
|
||||
return $this->createAuthenticatedToken($passport, $firewallName);
|
||||
}
|
||||
|
||||
return new PostAuthenticationToken($passport->getUser(), $firewallName, $passport->getUser()->getRoles());
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated since Symfony 5.4, use {@link createToken()} instead
|
||||
*/
|
||||
public function createAuthenticatedToken(PassportInterface $passport, string $firewallName): TokenInterface
|
||||
{
|
||||
// @deprecated since Symfony 5.4
|
||||
if (!$passport instanceof UserPassportInterface) {
|
||||
throw new LogicException(sprintf('Passport does not contain a user, overwrite "createToken()" in "%s" to create a custom authentication token.', static::class));
|
||||
}
|
||||
|
||||
trigger_deprecation('symfony/security-http', '5.4', 'Method "%s()" is deprecated, use "%s::createToken()" instead.', __METHOD__, __CLASS__);
|
||||
|
||||
return new PostAuthenticationToken($passport->getUser(), $firewallName, $passport->getUser()->getRoles());
|
||||
}
|
||||
}
|
76
vendor/symfony/security-http/Authenticator/AbstractLoginFormAuthenticator.php
vendored
Normal file
76
vendor/symfony/security-http/Authenticator/AbstractLoginFormAuthenticator.php
vendored
Normal file
@ -0,0 +1,76 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\Authenticator;
|
||||
|
||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Security\Core\Exception\AuthenticationException;
|
||||
use Symfony\Component\Security\Core\Security;
|
||||
use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface;
|
||||
|
||||
/**
|
||||
* A base class to make form login authentication easier!
|
||||
*
|
||||
* @author Ryan Weaver <ryan@symfonycasts.com>
|
||||
*/
|
||||
abstract class AbstractLoginFormAuthenticator extends AbstractAuthenticator implements AuthenticationEntryPointInterface, InteractiveAuthenticatorInterface
|
||||
{
|
||||
/**
|
||||
* Return the URL to the login page.
|
||||
*/
|
||||
abstract protected function getLoginUrl(Request $request): string;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* Override to change the request conditions that have to be
|
||||
* matched in order to handle the login form submit.
|
||||
*
|
||||
* This default implementation handles all POST requests to the
|
||||
* login path (@see getLoginUrl()).
|
||||
*/
|
||||
public function supports(Request $request): bool
|
||||
{
|
||||
return $request->isMethod('POST') && $this->getLoginUrl($request) === $request->getPathInfo();
|
||||
}
|
||||
|
||||
/**
|
||||
* Override to change what happens after a bad username/password is submitted.
|
||||
*/
|
||||
public function onAuthenticationFailure(Request $request, AuthenticationException $exception): Response
|
||||
{
|
||||
if ($request->hasSession()) {
|
||||
$request->getSession()->set(Security::AUTHENTICATION_ERROR, $exception);
|
||||
}
|
||||
|
||||
$url = $this->getLoginUrl($request);
|
||||
|
||||
return new RedirectResponse($url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Override to control what happens when the user hits a secure page
|
||||
* but isn't logged in yet.
|
||||
*/
|
||||
public function start(Request $request, AuthenticationException $authException = null): Response
|
||||
{
|
||||
$url = $this->getLoginUrl($request);
|
||||
|
||||
return new RedirectResponse($url);
|
||||
}
|
||||
|
||||
public function isInteractive(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
158
vendor/symfony/security-http/Authenticator/AbstractPreAuthenticatedAuthenticator.php
vendored
Normal file
158
vendor/symfony/security-http/Authenticator/AbstractPreAuthenticatedAuthenticator.php
vendored
Normal file
@ -0,0 +1,158 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\Authenticator;
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\PreAuthenticatedToken;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||
use Symfony\Component\Security\Core\Exception\AuthenticationException;
|
||||
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
|
||||
use Symfony\Component\Security\Core\User\UserProviderInterface;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\PreAuthenticatedUserBadge;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\Passport;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\PassportInterface;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\SelfValidatingPassport;
|
||||
|
||||
/**
|
||||
* The base authenticator for authenticators to use pre-authenticated
|
||||
* requests (e.g. using certificates).
|
||||
*
|
||||
* @author Wouter de Jong <wouter@wouterj.nl>
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
abstract class AbstractPreAuthenticatedAuthenticator implements InteractiveAuthenticatorInterface
|
||||
{
|
||||
private $userProvider;
|
||||
private $tokenStorage;
|
||||
private $firewallName;
|
||||
private $logger;
|
||||
|
||||
public function __construct(UserProviderInterface $userProvider, TokenStorageInterface $tokenStorage, string $firewallName, LoggerInterface $logger = null)
|
||||
{
|
||||
$this->userProvider = $userProvider;
|
||||
$this->tokenStorage = $tokenStorage;
|
||||
$this->firewallName = $firewallName;
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the username of the pre-authenticated user.
|
||||
*
|
||||
* This authenticator is skipped if null is returned or a custom
|
||||
* BadCredentialsException is thrown.
|
||||
*/
|
||||
abstract protected function extractUsername(Request $request): ?string;
|
||||
|
||||
public function supports(Request $request): ?bool
|
||||
{
|
||||
try {
|
||||
$username = $this->extractUsername($request);
|
||||
} catch (BadCredentialsException $e) {
|
||||
$this->clearToken($e);
|
||||
|
||||
if (null !== $this->logger) {
|
||||
$this->logger->debug('Skipping pre-authenticated authenticator as a BadCredentialsException is thrown.', ['exception' => $e, 'authenticator' => static::class]);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (null === $username) {
|
||||
if (null !== $this->logger) {
|
||||
$this->logger->debug('Skipping pre-authenticated authenticator no username could be extracted.', ['authenticator' => static::class]);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// do not overwrite already stored tokens from the same user (i.e. from the session)
|
||||
$token = $this->tokenStorage->getToken();
|
||||
|
||||
if ($token instanceof PreAuthenticatedToken && $this->firewallName === $token->getFirewallName() && $token->getUserIdentifier() === $username) {
|
||||
if (null !== $this->logger) {
|
||||
$this->logger->debug('Skipping pre-authenticated authenticator as the user already has an existing session.', ['authenticator' => static::class]);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$request->attributes->set('_pre_authenticated_username', $username);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function authenticate(Request $request): Passport
|
||||
{
|
||||
// @deprecated since Symfony 5.3, change to $this->userProvider->loadUserByIdentifier() in 6.0
|
||||
$method = 'loadUserByIdentifier';
|
||||
if (!method_exists($this->userProvider, 'loadUserByIdentifier')) {
|
||||
trigger_deprecation('symfony/security-core', '5.3', 'Not implementing method "loadUserByIdentifier()" in user provider "%s" is deprecated. This method will replace "loadUserByUsername()" in Symfony 6.0.', get_debug_type($this->userProvider));
|
||||
|
||||
$method = 'loadUserByUsername';
|
||||
}
|
||||
|
||||
return new SelfValidatingPassport(
|
||||
new UserBadge($request->attributes->get('_pre_authenticated_username'), [$this->userProvider, $method]),
|
||||
[new PreAuthenticatedUserBadge()]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated since Symfony 5.4, use {@link createToken()} instead
|
||||
*/
|
||||
public function createAuthenticatedToken(PassportInterface $passport, string $firewallName): TokenInterface
|
||||
{
|
||||
trigger_deprecation('symfony/security-http', '5.4', 'Method "%s()" is deprecated, use "%s::createToken()" instead.', __METHOD__, __CLASS__);
|
||||
|
||||
return $this->createToken($passport, $firewallName);
|
||||
}
|
||||
|
||||
public function createToken(Passport $passport, string $firewallName): TokenInterface
|
||||
{
|
||||
return new PreAuthenticatedToken($passport->getUser(), $firewallName, $passport->getUser()->getRoles());
|
||||
}
|
||||
|
||||
public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response
|
||||
{
|
||||
return null; // let the original request continue
|
||||
}
|
||||
|
||||
public function onAuthenticationFailure(Request $request, AuthenticationException $exception): ?Response
|
||||
{
|
||||
$this->clearToken($exception);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function isInteractive(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
private function clearToken(AuthenticationException $exception): void
|
||||
{
|
||||
$token = $this->tokenStorage->getToken();
|
||||
if ($token instanceof PreAuthenticatedToken && $this->firewallName === $token->getFirewallName()) {
|
||||
$this->tokenStorage->setToken(null);
|
||||
|
||||
if (null !== $this->logger) {
|
||||
$this->logger->info('Cleared pre-authenticated token due to an exception.', ['exception' => $exception]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
96
vendor/symfony/security-http/Authenticator/AuthenticatorInterface.php
vendored
Normal file
96
vendor/symfony/security-http/Authenticator/AuthenticatorInterface.php
vendored
Normal file
@ -0,0 +1,96 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\Authenticator;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||
use Symfony\Component\Security\Core\Exception\AuthenticationException;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\Passport;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\PassportInterface;
|
||||
|
||||
/**
|
||||
* The interface for all authenticators.
|
||||
*
|
||||
* @author Ryan Weaver <ryan@symfonycasts.com>
|
||||
* @author Amaury Leroux de Lens <amaury@lerouxdelens.com>
|
||||
* @author Wouter de Jong <wouter@wouterj.nl>
|
||||
*
|
||||
* @method TokenInterface createToken(Passport $passport, string $firewallName) Creates a token for the given user.
|
||||
* If you don't care about which token class is used, you can skip this method by extending
|
||||
* the AbstractAuthenticator class from your authenticator.
|
||||
*/
|
||||
interface AuthenticatorInterface
|
||||
{
|
||||
/**
|
||||
* Does the authenticator support the given Request?
|
||||
*
|
||||
* If this returns true, authenticate() will be called. If false, the authenticator will be skipped.
|
||||
*
|
||||
* Returning null means authenticate() can be called lazily when accessing the token storage.
|
||||
*/
|
||||
public function supports(Request $request): ?bool;
|
||||
|
||||
/**
|
||||
* Create a passport for the current request.
|
||||
*
|
||||
* The passport contains the user, credentials and any additional information
|
||||
* that has to be checked by the Symfony Security system. For example, a login
|
||||
* form authenticator will probably return a passport containing the user, the
|
||||
* presented password and the CSRF token value.
|
||||
*
|
||||
* You may throw any AuthenticationException in this method in case of error (e.g.
|
||||
* a UserNotFoundException when the user cannot be found).
|
||||
*
|
||||
* @throws AuthenticationException
|
||||
*
|
||||
* @return Passport
|
||||
*/
|
||||
public function authenticate(Request $request); /*: Passport;*/
|
||||
|
||||
/**
|
||||
* Create an authenticated token for the given user.
|
||||
*
|
||||
* If you don't care about which token class is used or don't really
|
||||
* understand what a "token" is, you can skip this method by extending
|
||||
* the AbstractAuthenticator class from your authenticator.
|
||||
*
|
||||
* @see AbstractAuthenticator
|
||||
*
|
||||
* @param PassportInterface $passport The passport returned from authenticate()
|
||||
*
|
||||
* @deprecated since Symfony 5.4, use {@link createToken()} instead
|
||||
*/
|
||||
public function createAuthenticatedToken(PassportInterface $passport, string $firewallName): TokenInterface;
|
||||
|
||||
/**
|
||||
* Called when authentication executed and was successful!
|
||||
*
|
||||
* This should return the Response sent back to the user, like a
|
||||
* RedirectResponse to the last page they visited.
|
||||
*
|
||||
* If you return null, the current request will continue, and the user
|
||||
* will be authenticated. This makes sense, for example, with an API.
|
||||
*/
|
||||
public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response;
|
||||
|
||||
/**
|
||||
* Called when authentication executed, but failed (e.g. wrong username password).
|
||||
*
|
||||
* This should return the Response sent back to the user, like a
|
||||
* RedirectResponse to the login page or a 403 response.
|
||||
*
|
||||
* If you return null, the request will continue, but the user will
|
||||
* not be authenticated. This is probably not what you want to do.
|
||||
*/
|
||||
public function onAuthenticationFailure(Request $request, AuthenticationException $exception): ?Response;
|
||||
}
|
115
vendor/symfony/security-http/Authenticator/Debug/TraceableAuthenticator.php
vendored
Normal file
115
vendor/symfony/security-http/Authenticator/Debug/TraceableAuthenticator.php
vendored
Normal file
@ -0,0 +1,115 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\Authenticator\Debug;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||
use Symfony\Component\Security\Core\Exception\AuthenticationException;
|
||||
use Symfony\Component\Security\Guard\Authenticator\GuardBridgeAuthenticator;
|
||||
use Symfony\Component\Security\Http\Authenticator\AuthenticatorInterface;
|
||||
use Symfony\Component\Security\Http\Authenticator\InteractiveAuthenticatorInterface;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\PassportInterface;
|
||||
use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface;
|
||||
use Symfony\Component\Security\Http\EntryPoint\Exception\NotAnEntryPointException;
|
||||
use Symfony\Component\VarDumper\Caster\ClassStub;
|
||||
|
||||
/**
|
||||
* Collects info about an authenticator for debugging purposes.
|
||||
*
|
||||
* @author Robin Chalas <robin.chalas@gmail.com>
|
||||
*/
|
||||
final class TraceableAuthenticator implements AuthenticatorInterface, InteractiveAuthenticatorInterface, AuthenticationEntryPointInterface
|
||||
{
|
||||
private $authenticator;
|
||||
private $passport;
|
||||
private $duration;
|
||||
private $stub;
|
||||
|
||||
public function __construct(AuthenticatorInterface $authenticator)
|
||||
{
|
||||
$this->authenticator = $authenticator;
|
||||
}
|
||||
|
||||
public function getInfo(): array
|
||||
{
|
||||
$class = \get_class($this->authenticator instanceof GuardBridgeAuthenticator ? $this->authenticator->getGuardAuthenticator() : $this->authenticator);
|
||||
|
||||
return [
|
||||
'supports' => true,
|
||||
'passport' => $this->passport,
|
||||
'duration' => $this->duration,
|
||||
'stub' => $this->stub ?? $this->stub = class_exists(ClassStub::class) ? new ClassStub($class) : $class,
|
||||
];
|
||||
}
|
||||
|
||||
public function supports(Request $request): ?bool
|
||||
{
|
||||
return $this->authenticator->supports($request);
|
||||
}
|
||||
|
||||
public function authenticate(Request $request): PassportInterface
|
||||
{
|
||||
$startTime = microtime(true);
|
||||
$this->passport = $this->authenticator->authenticate($request);
|
||||
$this->duration = microtime(true) - $startTime;
|
||||
|
||||
return $this->passport;
|
||||
}
|
||||
|
||||
public function createToken(PassportInterface $passport, string $firewallName): TokenInterface
|
||||
{
|
||||
return method_exists($this->authenticator, 'createToken') ? $this->authenticator->createToken($passport, $firewallName) : $this->authenticator->createAuthenticatedToken($passport, $firewallName);
|
||||
}
|
||||
|
||||
public function createAuthenticatedToken(PassportInterface $passport, string $firewallName): TokenInterface
|
||||
{
|
||||
return $this->authenticator->createAuthenticatedToken($passport, $firewallName);
|
||||
}
|
||||
|
||||
public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response
|
||||
{
|
||||
return $this->authenticator->onAuthenticationSuccess($request, $token, $firewallName);
|
||||
}
|
||||
|
||||
public function onAuthenticationFailure(Request $request, AuthenticationException $exception): ?Response
|
||||
{
|
||||
return $this->authenticator->onAuthenticationFailure($request, $exception);
|
||||
}
|
||||
|
||||
public function start(Request $request, AuthenticationException $authException = null): Response
|
||||
{
|
||||
if (!$this->authenticator instanceof AuthenticationEntryPointInterface) {
|
||||
throw new NotAnEntryPointException();
|
||||
}
|
||||
|
||||
return $this->authenticator->start($request, $authException);
|
||||
}
|
||||
|
||||
public function isInteractive(): bool
|
||||
{
|
||||
return $this->authenticator instanceof InteractiveAuthenticatorInterface && $this->authenticator->isInteractive();
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
public function getAuthenticator(): AuthenticatorInterface
|
||||
{
|
||||
return $this->authenticator;
|
||||
}
|
||||
|
||||
public function __call($method, $args)
|
||||
{
|
||||
return $this->authenticator->{$method}(...$args);
|
||||
}
|
||||
}
|
81
vendor/symfony/security-http/Authenticator/Debug/TraceableAuthenticatorManagerListener.php
vendored
Normal file
81
vendor/symfony/security-http/Authenticator/Debug/TraceableAuthenticatorManagerListener.php
vendored
Normal file
@ -0,0 +1,81 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\Authenticator\Debug;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\Event\RequestEvent;
|
||||
use Symfony\Component\Security\Http\Firewall\AbstractListener;
|
||||
use Symfony\Component\Security\Http\Firewall\AuthenticatorManagerListener;
|
||||
use Symfony\Component\VarDumper\Caster\ClassStub;
|
||||
|
||||
/**
|
||||
* Decorates the AuthenticatorManagerListener to collect information about security authenticators.
|
||||
*
|
||||
* @author Robin Chalas <robin.chalas@gmail.com>
|
||||
*/
|
||||
final class TraceableAuthenticatorManagerListener extends AbstractListener
|
||||
{
|
||||
private $authenticationManagerListener;
|
||||
private $authenticatorsInfo = [];
|
||||
private $hasVardumper;
|
||||
|
||||
public function __construct(AuthenticatorManagerListener $authenticationManagerListener)
|
||||
{
|
||||
$this->authenticationManagerListener = $authenticationManagerListener;
|
||||
$this->hasVardumper = class_exists(ClassStub::class);
|
||||
}
|
||||
|
||||
public function supports(Request $request): ?bool
|
||||
{
|
||||
return $this->authenticationManagerListener->supports($request);
|
||||
}
|
||||
|
||||
public function authenticate(RequestEvent $event): void
|
||||
{
|
||||
$request = $event->getRequest();
|
||||
|
||||
if (!$authenticators = $request->attributes->get('_security_authenticators')) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($request->attributes->get('_security_skipped_authenticators') as $skippedAuthenticator) {
|
||||
$this->authenticatorsInfo[] = [
|
||||
'supports' => false,
|
||||
'stub' => $this->hasVardumper ? new ClassStub(\get_class($skippedAuthenticator)) : \get_class($skippedAuthenticator),
|
||||
'passport' => null,
|
||||
'duration' => 0,
|
||||
];
|
||||
}
|
||||
|
||||
foreach ($authenticators as $key => $authenticator) {
|
||||
$authenticators[$key] = new TraceableAuthenticator($authenticator);
|
||||
}
|
||||
|
||||
$request->attributes->set('_security_authenticators', $authenticators);
|
||||
|
||||
$this->authenticationManagerListener->authenticate($event);
|
||||
|
||||
foreach ($authenticators as $authenticator) {
|
||||
$this->authenticatorsInfo[] = $authenticator->getInfo();
|
||||
}
|
||||
}
|
||||
|
||||
public function getAuthenticatorManagerListener(): AuthenticatorManagerListener
|
||||
{
|
||||
return $this->authenticationManagerListener;
|
||||
}
|
||||
|
||||
public function getAuthenticatorsInfo(): array
|
||||
{
|
||||
return $this->authenticatorsInfo;
|
||||
}
|
||||
}
|
182
vendor/symfony/security-http/Authenticator/FormLoginAuthenticator.php
vendored
Normal file
182
vendor/symfony/security-http/Authenticator/FormLoginAuthenticator.php
vendored
Normal file
@ -0,0 +1,182 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\Authenticator;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
|
||||
use Symfony\Component\HttpKernel\HttpKernelInterface;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
|
||||
use Symfony\Component\Security\Core\Exception\AuthenticationException;
|
||||
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
|
||||
use Symfony\Component\Security\Core\Security;
|
||||
use Symfony\Component\Security\Core\User\PasswordUpgraderInterface;
|
||||
use Symfony\Component\Security\Core\User\UserProviderInterface;
|
||||
use Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface;
|
||||
use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\CsrfTokenBadge;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\PasswordUpgradeBadge;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\RememberMeBadge;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\Credentials\PasswordCredentials;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\Passport;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\PassportInterface;
|
||||
use Symfony\Component\Security\Http\HttpUtils;
|
||||
use Symfony\Component\Security\Http\ParameterBagUtils;
|
||||
|
||||
/**
|
||||
* @author Wouter de Jong <wouter@wouterj.nl>
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
class FormLoginAuthenticator extends AbstractLoginFormAuthenticator
|
||||
{
|
||||
private $httpUtils;
|
||||
private $userProvider;
|
||||
private $successHandler;
|
||||
private $failureHandler;
|
||||
private $options;
|
||||
private $httpKernel;
|
||||
|
||||
public function __construct(HttpUtils $httpUtils, UserProviderInterface $userProvider, AuthenticationSuccessHandlerInterface $successHandler, AuthenticationFailureHandlerInterface $failureHandler, array $options)
|
||||
{
|
||||
$this->httpUtils = $httpUtils;
|
||||
$this->userProvider = $userProvider;
|
||||
$this->successHandler = $successHandler;
|
||||
$this->failureHandler = $failureHandler;
|
||||
$this->options = array_merge([
|
||||
'username_parameter' => '_username',
|
||||
'password_parameter' => '_password',
|
||||
'check_path' => '/login_check',
|
||||
'post_only' => true,
|
||||
'form_only' => false,
|
||||
'enable_csrf' => false,
|
||||
'csrf_parameter' => '_csrf_token',
|
||||
'csrf_token_id' => 'authenticate',
|
||||
], $options);
|
||||
}
|
||||
|
||||
protected function getLoginUrl(Request $request): string
|
||||
{
|
||||
return $this->httpUtils->generateUri($request, $this->options['login_path']);
|
||||
}
|
||||
|
||||
public function supports(Request $request): bool
|
||||
{
|
||||
return ($this->options['post_only'] ? $request->isMethod('POST') : true)
|
||||
&& $this->httpUtils->checkRequestPath($request, $this->options['check_path'])
|
||||
&& ($this->options['form_only'] ? 'form' === $request->getContentType() : true);
|
||||
}
|
||||
|
||||
public function authenticate(Request $request): Passport
|
||||
{
|
||||
$credentials = $this->getCredentials($request);
|
||||
|
||||
// @deprecated since Symfony 5.3, change to $this->userProvider->loadUserByIdentifier() in 6.0
|
||||
$method = 'loadUserByIdentifier';
|
||||
if (!method_exists($this->userProvider, 'loadUserByIdentifier')) {
|
||||
trigger_deprecation('symfony/security-core', '5.3', 'Not implementing method "loadUserByIdentifier()" in user provider "%s" is deprecated. This method will replace "loadUserByUsername()" in Symfony 6.0.', get_debug_type($this->userProvider));
|
||||
|
||||
$method = 'loadUserByUsername';
|
||||
}
|
||||
|
||||
$passport = new Passport(
|
||||
new UserBadge($credentials['username'], [$this->userProvider, $method]),
|
||||
new PasswordCredentials($credentials['password']),
|
||||
[new RememberMeBadge()]
|
||||
);
|
||||
if ($this->options['enable_csrf']) {
|
||||
$passport->addBadge(new CsrfTokenBadge($this->options['csrf_token_id'], $credentials['csrf_token']));
|
||||
}
|
||||
|
||||
if ($this->userProvider instanceof PasswordUpgraderInterface) {
|
||||
$passport->addBadge(new PasswordUpgradeBadge($credentials['password'], $this->userProvider));
|
||||
}
|
||||
|
||||
return $passport;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated since Symfony 5.4, use {@link createToken()} instead
|
||||
*/
|
||||
public function createAuthenticatedToken(PassportInterface $passport, string $firewallName): TokenInterface
|
||||
{
|
||||
trigger_deprecation('symfony/security-http', '5.4', 'Method "%s()" is deprecated, use "%s::createToken()" instead.', __METHOD__, __CLASS__);
|
||||
|
||||
return $this->createToken($passport, $firewallName);
|
||||
}
|
||||
|
||||
public function createToken(Passport $passport, string $firewallName): TokenInterface
|
||||
{
|
||||
return new UsernamePasswordToken($passport->getUser(), $firewallName, $passport->getUser()->getRoles());
|
||||
}
|
||||
|
||||
public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response
|
||||
{
|
||||
return $this->successHandler->onAuthenticationSuccess($request, $token);
|
||||
}
|
||||
|
||||
public function onAuthenticationFailure(Request $request, AuthenticationException $exception): Response
|
||||
{
|
||||
return $this->failureHandler->onAuthenticationFailure($request, $exception);
|
||||
}
|
||||
|
||||
private function getCredentials(Request $request): array
|
||||
{
|
||||
$credentials = [];
|
||||
$credentials['csrf_token'] = ParameterBagUtils::getRequestParameterValue($request, $this->options['csrf_parameter']);
|
||||
|
||||
if ($this->options['post_only']) {
|
||||
$credentials['username'] = ParameterBagUtils::getParameterBagValue($request->request, $this->options['username_parameter']);
|
||||
$credentials['password'] = ParameterBagUtils::getParameterBagValue($request->request, $this->options['password_parameter']) ?? '';
|
||||
} else {
|
||||
$credentials['username'] = ParameterBagUtils::getRequestParameterValue($request, $this->options['username_parameter']);
|
||||
$credentials['password'] = ParameterBagUtils::getRequestParameterValue($request, $this->options['password_parameter']) ?? '';
|
||||
}
|
||||
|
||||
if (!\is_string($credentials['username']) && (!\is_object($credentials['username']) || !method_exists($credentials['username'], '__toString'))) {
|
||||
throw new BadRequestHttpException(sprintf('The key "%s" must be a string, "%s" given.', $this->options['username_parameter'], \gettype($credentials['username'])));
|
||||
}
|
||||
|
||||
$credentials['username'] = trim($credentials['username']);
|
||||
|
||||
if (\strlen($credentials['username']) > Security::MAX_USERNAME_LENGTH) {
|
||||
throw new BadCredentialsException('Invalid username.');
|
||||
}
|
||||
|
||||
$request->getSession()->set(Security::LAST_USERNAME, $credentials['username']);
|
||||
|
||||
return $credentials;
|
||||
}
|
||||
|
||||
public function setHttpKernel(HttpKernelInterface $httpKernel): void
|
||||
{
|
||||
$this->httpKernel = $httpKernel;
|
||||
}
|
||||
|
||||
public function start(Request $request, AuthenticationException $authException = null): Response
|
||||
{
|
||||
if (!$this->options['use_forward']) {
|
||||
return parent::start($request, $authException);
|
||||
}
|
||||
|
||||
$subRequest = $this->httpUtils->createRequest($request, $this->options['login_path']);
|
||||
$response = $this->httpKernel->handle($subRequest, HttpKernelInterface::SUB_REQUEST);
|
||||
if (200 === $response->getStatusCode()) {
|
||||
$response->setStatusCode(401);
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
}
|
114
vendor/symfony/security-http/Authenticator/HttpBasicAuthenticator.php
vendored
Normal file
114
vendor/symfony/security-http/Authenticator/HttpBasicAuthenticator.php
vendored
Normal file
@ -0,0 +1,114 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\Authenticator;
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
|
||||
use Symfony\Component\Security\Core\Exception\AuthenticationException;
|
||||
use Symfony\Component\Security\Core\User\PasswordUpgraderInterface;
|
||||
use Symfony\Component\Security\Core\User\UserProviderInterface;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\PasswordUpgradeBadge;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\Credentials\PasswordCredentials;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\Passport;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\PassportInterface;
|
||||
use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface;
|
||||
|
||||
/**
|
||||
* @author Wouter de Jong <wouter@wouterj.nl>
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
class HttpBasicAuthenticator implements AuthenticatorInterface, AuthenticationEntryPointInterface
|
||||
{
|
||||
private $realmName;
|
||||
private $userProvider;
|
||||
private $logger;
|
||||
|
||||
public function __construct(string $realmName, UserProviderInterface $userProvider, LoggerInterface $logger = null)
|
||||
{
|
||||
$this->realmName = $realmName;
|
||||
$this->userProvider = $userProvider;
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
public function start(Request $request, AuthenticationException $authException = null): Response
|
||||
{
|
||||
$response = new Response();
|
||||
$response->headers->set('WWW-Authenticate', sprintf('Basic realm="%s"', $this->realmName));
|
||||
$response->setStatusCode(401);
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
public function supports(Request $request): ?bool
|
||||
{
|
||||
return $request->headers->has('PHP_AUTH_USER');
|
||||
}
|
||||
|
||||
public function authenticate(Request $request): PassportInterface
|
||||
{
|
||||
$username = $request->headers->get('PHP_AUTH_USER');
|
||||
$password = $request->headers->get('PHP_AUTH_PW', '');
|
||||
|
||||
// @deprecated since Symfony 5.3, change to $this->userProvider->loadUserByIdentifier() in 6.0
|
||||
$method = 'loadUserByIdentifier';
|
||||
if (!method_exists($this->userProvider, 'loadUserByIdentifier')) {
|
||||
trigger_deprecation('symfony/security-core', '5.3', 'Not implementing method "loadUserByIdentifier()" in user provider "%s" is deprecated. This method will replace "loadUserByUsername()" in Symfony 6.0.', get_debug_type($this->userProvider));
|
||||
|
||||
$method = 'loadUserByUsername';
|
||||
}
|
||||
|
||||
$passport = new Passport(
|
||||
new UserBadge($username, [$this->userProvider, $method]),
|
||||
new PasswordCredentials($password)
|
||||
);
|
||||
if ($this->userProvider instanceof PasswordUpgraderInterface) {
|
||||
$passport->addBadge(new PasswordUpgradeBadge($password, $this->userProvider));
|
||||
}
|
||||
|
||||
return $passport;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated since Symfony 5.4, use {@link createToken()} instead
|
||||
*/
|
||||
public function createAuthenticatedToken(PassportInterface $passport, string $firewallName): TokenInterface
|
||||
{
|
||||
trigger_deprecation('symfony/security-http', '5.4', 'Method "%s()" is deprecated, use "%s::createToken()" instead.', __METHOD__, __CLASS__);
|
||||
|
||||
return $this->createToken($passport, $firewallName);
|
||||
}
|
||||
|
||||
public function createToken(Passport $passport, string $firewallName): TokenInterface
|
||||
{
|
||||
return new UsernamePasswordToken($passport->getUser(), $firewallName, $passport->getUser()->getRoles());
|
||||
}
|
||||
|
||||
public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function onAuthenticationFailure(Request $request, AuthenticationException $exception): ?Response
|
||||
{
|
||||
if (null !== $this->logger) {
|
||||
$this->logger->info('Basic authentication failed for user.', ['username' => $request->headers->get('PHP_AUTH_USER'), 'exception' => $exception]);
|
||||
}
|
||||
|
||||
return $this->start($request, $exception);
|
||||
}
|
||||
}
|
31
vendor/symfony/security-http/Authenticator/InteractiveAuthenticatorInterface.php
vendored
Normal file
31
vendor/symfony/security-http/Authenticator/InteractiveAuthenticatorInterface.php
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\Authenticator;
|
||||
|
||||
/**
|
||||
* This is an extension of the authenticator interface that must
|
||||
* be used by interactive authenticators.
|
||||
*
|
||||
* Interactive login requires explicit user action (e.g. a login
|
||||
* form or HTTP basic authentication). Implementing this interface
|
||||
* will dispatch the InteractiveLoginEvent upon successful login.
|
||||
*
|
||||
* @author Wouter de Jong <wouter@wouterj.nl>
|
||||
*/
|
||||
interface InteractiveAuthenticatorInterface extends AuthenticatorInterface
|
||||
{
|
||||
/**
|
||||
* Should return true to make this authenticator perform
|
||||
* an interactive login.
|
||||
*/
|
||||
public function isInteractive(): bool;
|
||||
}
|
196
vendor/symfony/security-http/Authenticator/JsonLoginAuthenticator.php
vendored
Normal file
196
vendor/symfony/security-http/Authenticator/JsonLoginAuthenticator.php
vendored
Normal file
@ -0,0 +1,196 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\Authenticator;
|
||||
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
|
||||
use Symfony\Component\PropertyAccess\Exception\AccessException;
|
||||
use Symfony\Component\PropertyAccess\PropertyAccess;
|
||||
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
|
||||
use Symfony\Component\Security\Core\Exception\AuthenticationException;
|
||||
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
|
||||
use Symfony\Component\Security\Core\Security;
|
||||
use Symfony\Component\Security\Core\User\PasswordUpgraderInterface;
|
||||
use Symfony\Component\Security\Core\User\UserProviderInterface;
|
||||
use Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface;
|
||||
use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\PasswordUpgradeBadge;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\Credentials\PasswordCredentials;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\Passport;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\PassportInterface;
|
||||
use Symfony\Component\Security\Http\HttpUtils;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
/**
|
||||
* Provides a stateless implementation of an authentication via
|
||||
* a JSON document composed of a username and a password.
|
||||
*
|
||||
* @author Kévin Dunglas <dunglas@gmail.com>
|
||||
* @author Wouter de Jong <wouter@wouterj.nl>
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
class JsonLoginAuthenticator implements InteractiveAuthenticatorInterface
|
||||
{
|
||||
private $options;
|
||||
private $httpUtils;
|
||||
private $userProvider;
|
||||
private $propertyAccessor;
|
||||
private $successHandler;
|
||||
private $failureHandler;
|
||||
|
||||
/**
|
||||
* @var TranslatorInterface|null
|
||||
*/
|
||||
private $translator;
|
||||
|
||||
public function __construct(HttpUtils $httpUtils, UserProviderInterface $userProvider, AuthenticationSuccessHandlerInterface $successHandler = null, AuthenticationFailureHandlerInterface $failureHandler = null, array $options = [], PropertyAccessorInterface $propertyAccessor = null)
|
||||
{
|
||||
$this->options = array_merge(['username_path' => 'username', 'password_path' => 'password'], $options);
|
||||
$this->httpUtils = $httpUtils;
|
||||
$this->successHandler = $successHandler;
|
||||
$this->failureHandler = $failureHandler;
|
||||
$this->userProvider = $userProvider;
|
||||
$this->propertyAccessor = $propertyAccessor ?: PropertyAccess::createPropertyAccessor();
|
||||
}
|
||||
|
||||
public function supports(Request $request): ?bool
|
||||
{
|
||||
if (false === strpos($request->getRequestFormat() ?? '', 'json') && false === strpos($request->getContentType() ?? '', 'json')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isset($this->options['check_path']) && !$this->httpUtils->checkRequestPath($request, $this->options['check_path'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function authenticate(Request $request): PassportInterface
|
||||
{
|
||||
try {
|
||||
$credentials = $this->getCredentials($request);
|
||||
} catch (BadRequestHttpException $e) {
|
||||
$request->setRequestFormat('json');
|
||||
|
||||
throw $e;
|
||||
}
|
||||
|
||||
// @deprecated since Symfony 5.3, change to $this->userProvider->loadUserByIdentifier() in 6.0
|
||||
$method = 'loadUserByIdentifier';
|
||||
if (!method_exists($this->userProvider, 'loadUserByIdentifier')) {
|
||||
trigger_deprecation('symfony/security-core', '5.3', 'Not implementing method "loadUserByIdentifier()" in user provider "%s" is deprecated. This method will replace "loadUserByUsername()" in Symfony 6.0.', get_debug_type($this->userProvider));
|
||||
|
||||
$method = 'loadUserByUsername';
|
||||
}
|
||||
|
||||
$passport = new Passport(
|
||||
new UserBadge($credentials['username'], [$this->userProvider, $method]),
|
||||
new PasswordCredentials($credentials['password'])
|
||||
);
|
||||
if ($this->userProvider instanceof PasswordUpgraderInterface) {
|
||||
$passport->addBadge(new PasswordUpgradeBadge($credentials['password'], $this->userProvider));
|
||||
}
|
||||
|
||||
return $passport;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated since Symfony 5.4, use {@link createToken()} instead
|
||||
*/
|
||||
public function createAuthenticatedToken(PassportInterface $passport, string $firewallName): TokenInterface
|
||||
{
|
||||
trigger_deprecation('symfony/security-http', '5.4', 'Method "%s()" is deprecated, use "%s::createToken()" instead.', __METHOD__, __CLASS__);
|
||||
|
||||
return $this->createToken($passport, $firewallName);
|
||||
}
|
||||
|
||||
public function createToken(Passport $passport, string $firewallName): TokenInterface
|
||||
{
|
||||
return new UsernamePasswordToken($passport->getUser(), $firewallName, $passport->getUser()->getRoles());
|
||||
}
|
||||
|
||||
public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response
|
||||
{
|
||||
if (null === $this->successHandler) {
|
||||
return null; // let the original request continue
|
||||
}
|
||||
|
||||
return $this->successHandler->onAuthenticationSuccess($request, $token);
|
||||
}
|
||||
|
||||
public function onAuthenticationFailure(Request $request, AuthenticationException $exception): ?Response
|
||||
{
|
||||
if (null === $this->failureHandler) {
|
||||
if (null !== $this->translator) {
|
||||
$errorMessage = $this->translator->trans($exception->getMessageKey(), $exception->getMessageData(), 'security');
|
||||
} else {
|
||||
$errorMessage = strtr($exception->getMessageKey(), $exception->getMessageData());
|
||||
}
|
||||
|
||||
return new JsonResponse(['error' => $errorMessage], JsonResponse::HTTP_UNAUTHORIZED);
|
||||
}
|
||||
|
||||
return $this->failureHandler->onAuthenticationFailure($request, $exception);
|
||||
}
|
||||
|
||||
public function isInteractive(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function setTranslator(TranslatorInterface $translator)
|
||||
{
|
||||
$this->translator = $translator;
|
||||
}
|
||||
|
||||
private function getCredentials(Request $request)
|
||||
{
|
||||
$data = json_decode($request->getContent());
|
||||
if (!$data instanceof \stdClass) {
|
||||
throw new BadRequestHttpException('Invalid JSON.');
|
||||
}
|
||||
|
||||
$credentials = [];
|
||||
try {
|
||||
$credentials['username'] = $this->propertyAccessor->getValue($data, $this->options['username_path']);
|
||||
|
||||
if (!\is_string($credentials['username'])) {
|
||||
throw new BadRequestHttpException(sprintf('The key "%s" must be a string.', $this->options['username_path']));
|
||||
}
|
||||
|
||||
if (\strlen($credentials['username']) > Security::MAX_USERNAME_LENGTH) {
|
||||
throw new BadCredentialsException('Invalid username.');
|
||||
}
|
||||
} catch (AccessException $e) {
|
||||
throw new BadRequestHttpException(sprintf('The key "%s" must be provided.', $this->options['username_path']), $e);
|
||||
}
|
||||
|
||||
try {
|
||||
$credentials['password'] = $this->propertyAccessor->getValue($data, $this->options['password_path']);
|
||||
|
||||
if (!\is_string($credentials['password'])) {
|
||||
throw new BadRequestHttpException(sprintf('The key "%s" must be a string.', $this->options['password_path']));
|
||||
}
|
||||
} catch (AccessException $e) {
|
||||
throw new BadRequestHttpException(sprintf('The key "%s" must be provided.', $this->options['password_path']), $e);
|
||||
}
|
||||
|
||||
return $credentials;
|
||||
}
|
||||
}
|
90
vendor/symfony/security-http/Authenticator/LoginLinkAuthenticator.php
vendored
Normal file
90
vendor/symfony/security-http/Authenticator/LoginLinkAuthenticator.php
vendored
Normal file
@ -0,0 +1,90 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\Authenticator;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||
use Symfony\Component\Security\Core\Exception\AuthenticationException;
|
||||
use Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface;
|
||||
use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\RememberMeBadge;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\PassportInterface;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\SelfValidatingPassport;
|
||||
use Symfony\Component\Security\Http\HttpUtils;
|
||||
use Symfony\Component\Security\Http\LoginLink\Exception\InvalidLoginLinkAuthenticationException;
|
||||
use Symfony\Component\Security\Http\LoginLink\Exception\InvalidLoginLinkExceptionInterface;
|
||||
use Symfony\Component\Security\Http\LoginLink\LoginLinkHandlerInterface;
|
||||
|
||||
/**
|
||||
* @author Ryan Weaver <ryan@symfonycasts.com>
|
||||
*/
|
||||
final class LoginLinkAuthenticator extends AbstractAuthenticator implements InteractiveAuthenticatorInterface
|
||||
{
|
||||
private $loginLinkHandler;
|
||||
private $httpUtils;
|
||||
private $successHandler;
|
||||
private $failureHandler;
|
||||
private $options;
|
||||
|
||||
public function __construct(LoginLinkHandlerInterface $loginLinkHandler, HttpUtils $httpUtils, AuthenticationSuccessHandlerInterface $successHandler, AuthenticationFailureHandlerInterface $failureHandler, array $options)
|
||||
{
|
||||
$this->loginLinkHandler = $loginLinkHandler;
|
||||
$this->httpUtils = $httpUtils;
|
||||
$this->successHandler = $successHandler;
|
||||
$this->failureHandler = $failureHandler;
|
||||
$this->options = $options + ['check_post_only' => false];
|
||||
}
|
||||
|
||||
public function supports(Request $request): ?bool
|
||||
{
|
||||
return ($this->options['check_post_only'] ? $request->isMethod('POST') : true)
|
||||
&& $this->httpUtils->checkRequestPath($request, $this->options['check_route']);
|
||||
}
|
||||
|
||||
public function authenticate(Request $request): PassportInterface
|
||||
{
|
||||
$username = $request->get('user');
|
||||
if (!$username) {
|
||||
throw new InvalidLoginLinkAuthenticationException('Missing user from link.');
|
||||
}
|
||||
|
||||
return new SelfValidatingPassport(
|
||||
new UserBadge($username, function () use ($request) {
|
||||
try {
|
||||
$user = $this->loginLinkHandler->consumeLoginLink($request);
|
||||
} catch (InvalidLoginLinkExceptionInterface $e) {
|
||||
throw new InvalidLoginLinkAuthenticationException('Login link could not be validated.', 0, $e);
|
||||
}
|
||||
|
||||
return $user;
|
||||
}),
|
||||
[new RememberMeBadge()]
|
||||
);
|
||||
}
|
||||
|
||||
public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response
|
||||
{
|
||||
return $this->successHandler->onAuthenticationSuccess($request, $token);
|
||||
}
|
||||
|
||||
public function onAuthenticationFailure(Request $request, AuthenticationException $exception): Response
|
||||
{
|
||||
return $this->failureHandler->onAuthenticationFailure($request, $exception);
|
||||
}
|
||||
|
||||
public function isInteractive(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
28
vendor/symfony/security-http/Authenticator/Passport/Badge/BadgeInterface.php
vendored
Normal file
28
vendor/symfony/security-http/Authenticator/Passport/Badge/BadgeInterface.php
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\Authenticator\Passport\Badge;
|
||||
|
||||
/**
|
||||
* Passport badges allow to add more information to a passport (e.g. a CSRF token).
|
||||
*
|
||||
* @author Wouter de Jong <wouter@wouterj.nl>
|
||||
*/
|
||||
interface BadgeInterface
|
||||
{
|
||||
/**
|
||||
* Checks if this badge is resolved by the security system.
|
||||
*
|
||||
* After authentication, all badges must return `true` in this method in order
|
||||
* for the authentication to succeed.
|
||||
*/
|
||||
public function isResolved(): bool;
|
||||
}
|
64
vendor/symfony/security-http/Authenticator/Passport/Badge/CsrfTokenBadge.php
vendored
Normal file
64
vendor/symfony/security-http/Authenticator/Passport/Badge/CsrfTokenBadge.php
vendored
Normal file
@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\Authenticator\Passport\Badge;
|
||||
|
||||
use Symfony\Component\Security\Http\EventListener\CsrfProtectionListener;
|
||||
|
||||
/**
|
||||
* Adds automatic CSRF tokens checking capabilities to this authenticator.
|
||||
*
|
||||
* @see CsrfProtectionListener
|
||||
*
|
||||
* @author Wouter de Jong <wouter@wouterj.nl>
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
class CsrfTokenBadge implements BadgeInterface
|
||||
{
|
||||
private $resolved = false;
|
||||
private $csrfTokenId;
|
||||
private $csrfToken;
|
||||
|
||||
/**
|
||||
* @param string $csrfTokenId An arbitrary string used to generate the value of the CSRF token.
|
||||
* Using a different string for each authenticator improves its security.
|
||||
* @param string|null $csrfToken The CSRF token presented in the request, if any
|
||||
*/
|
||||
public function __construct(string $csrfTokenId, ?string $csrfToken)
|
||||
{
|
||||
$this->csrfTokenId = $csrfTokenId;
|
||||
$this->csrfToken = $csrfToken;
|
||||
}
|
||||
|
||||
public function getCsrfTokenId(): string
|
||||
{
|
||||
return $this->csrfTokenId;
|
||||
}
|
||||
|
||||
public function getCsrfToken(): ?string
|
||||
{
|
||||
return $this->csrfToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
public function markResolved(): void
|
||||
{
|
||||
$this->resolved = true;
|
||||
}
|
||||
|
||||
public function isResolved(): bool
|
||||
{
|
||||
return $this->resolved;
|
||||
}
|
||||
}
|
62
vendor/symfony/security-http/Authenticator/Passport/Badge/PasswordUpgradeBadge.php
vendored
Normal file
62
vendor/symfony/security-http/Authenticator/Passport/Badge/PasswordUpgradeBadge.php
vendored
Normal file
@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\Authenticator\Passport\Badge;
|
||||
|
||||
use Symfony\Component\Security\Core\Exception\LogicException;
|
||||
use Symfony\Component\Security\Core\User\PasswordUpgraderInterface;
|
||||
|
||||
/**
|
||||
* Adds automatic password migration, if enabled and required in the password encoder.
|
||||
*
|
||||
* @see PasswordUpgraderInterface
|
||||
*
|
||||
* @author Wouter de Jong <wouter@wouterj.nl>
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
class PasswordUpgradeBadge implements BadgeInterface
|
||||
{
|
||||
private $plaintextPassword;
|
||||
private $passwordUpgrader;
|
||||
|
||||
/**
|
||||
* @param string $plaintextPassword The presented password, used in the rehash
|
||||
* @param PasswordUpgraderInterface|null $passwordUpgrader The password upgrader, defaults to the UserProvider if null
|
||||
*/
|
||||
public function __construct(string $plaintextPassword, PasswordUpgraderInterface $passwordUpgrader = null)
|
||||
{
|
||||
$this->plaintextPassword = $plaintextPassword;
|
||||
$this->passwordUpgrader = $passwordUpgrader;
|
||||
}
|
||||
|
||||
public function getAndErasePlaintextPassword(): string
|
||||
{
|
||||
$password = $this->plaintextPassword;
|
||||
if (null === $password) {
|
||||
throw new LogicException('The password is erased as another listener already used this badge.');
|
||||
}
|
||||
|
||||
$this->plaintextPassword = null;
|
||||
|
||||
return $password;
|
||||
}
|
||||
|
||||
public function getPasswordUpgrader(): ?PasswordUpgraderInterface
|
||||
{
|
||||
return $this->passwordUpgrader;
|
||||
}
|
||||
|
||||
public function isResolved(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
33
vendor/symfony/security-http/Authenticator/Passport/Badge/PreAuthenticatedUserBadge.php
vendored
Normal file
33
vendor/symfony/security-http/Authenticator/Passport/Badge/PreAuthenticatedUserBadge.php
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\Authenticator\Passport\Badge;
|
||||
|
||||
use Symfony\Component\Security\Http\Authenticator\AbstractPreAuthenticatedAuthenticator;
|
||||
|
||||
/**
|
||||
* Marks the authentication as being pre-authenticated.
|
||||
*
|
||||
* This disables pre-authentication user checkers.
|
||||
*
|
||||
* @see AbstractPreAuthenticatedAuthenticator
|
||||
*
|
||||
* @author Wouter de Jong <wouter@wouterj.nl>
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
class PreAuthenticatedUserBadge implements BadgeInterface
|
||||
{
|
||||
public function isResolved(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
71
vendor/symfony/security-http/Authenticator/Passport/Badge/RememberMeBadge.php
vendored
Normal file
71
vendor/symfony/security-http/Authenticator/Passport/Badge/RememberMeBadge.php
vendored
Normal file
@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\Authenticator\Passport\Badge;
|
||||
|
||||
use Symfony\Component\Security\Http\EventListener\CheckRememberMeConditionsListener;
|
||||
|
||||
/**
|
||||
* Adds support for remember me to this authenticator.
|
||||
*
|
||||
* The presence of this badge doesn't create the remember-me cookie. The actual
|
||||
* cookie is only created if this badge is enabled. By default, this is done
|
||||
* by the {@see CheckRememberMeConditionsListener} if all conditions are met.
|
||||
*
|
||||
* @author Wouter de Jong <wouter@wouterj.nl>
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
class RememberMeBadge implements BadgeInterface
|
||||
{
|
||||
private $enabled = false;
|
||||
|
||||
/**
|
||||
* Enables remember-me cookie creation.
|
||||
*
|
||||
* In most cases, {@see CheckRememberMeConditionsListener} enables this
|
||||
* automatically if always_remember_me is true or the remember_me_parameter
|
||||
* exists in the request.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function enable(): self
|
||||
{
|
||||
$this->enabled = true;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables remember-me cookie creation.
|
||||
*
|
||||
* The default is disabled, this can be called to suppress creation
|
||||
* after it was enabled.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function disable(): self
|
||||
{
|
||||
$this->enabled = false;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function isEnabled(): bool
|
||||
{
|
||||
return $this->enabled;
|
||||
}
|
||||
|
||||
public function isResolved(): bool
|
||||
{
|
||||
return true; // remember me does not need to be explicitly resolved
|
||||
}
|
||||
}
|
102
vendor/symfony/security-http/Authenticator/Passport/Badge/UserBadge.php
vendored
Normal file
102
vendor/symfony/security-http/Authenticator/Passport/Badge/UserBadge.php
vendored
Normal file
@ -0,0 +1,102 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\Authenticator\Passport\Badge;
|
||||
|
||||
use Symfony\Component\Security\Core\Exception\AuthenticationException;
|
||||
use Symfony\Component\Security\Core\Exception\AuthenticationServiceException;
|
||||
use Symfony\Component\Security\Core\Exception\UserNotFoundException;
|
||||
use Symfony\Component\Security\Core\User\UserInterface;
|
||||
use Symfony\Component\Security\Http\EventListener\UserProviderListener;
|
||||
|
||||
/**
|
||||
* Represents the user in the authentication process.
|
||||
*
|
||||
* It uses an identifier (e.g. email, or username) and
|
||||
* "user loader" to load the related User object.
|
||||
*
|
||||
* @author Wouter de Jong <wouter@wouterj.nl>
|
||||
*/
|
||||
class UserBadge implements BadgeInterface
|
||||
{
|
||||
private $userIdentifier;
|
||||
private $userLoader;
|
||||
private $user;
|
||||
|
||||
/**
|
||||
* Initializes the user badge.
|
||||
*
|
||||
* You must provide a $userIdentifier. This is a unique string representing the
|
||||
* user for this authentication (e.g. the email if authentication is done using
|
||||
* email + password; or a string combining email+company if authentication is done
|
||||
* based on email *and* company name). This string can be used for e.g. login throttling.
|
||||
*
|
||||
* Optionally, you may pass a user loader. This callable receives the $userIdentifier
|
||||
* as argument and must return a UserInterface object (otherwise an AuthenticationServiceException
|
||||
* is thrown). If this is not set, the default user provider will be used with
|
||||
* $userIdentifier as username.
|
||||
*/
|
||||
public function __construct(string $userIdentifier, callable $userLoader = null)
|
||||
{
|
||||
$this->userIdentifier = $userIdentifier;
|
||||
$this->userLoader = $userLoader;
|
||||
}
|
||||
|
||||
public function getUserIdentifier(): string
|
||||
{
|
||||
return $this->userIdentifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws AuthenticationException when the user cannot be found
|
||||
*/
|
||||
public function getUser(): UserInterface
|
||||
{
|
||||
if (null !== $this->user) {
|
||||
return $this->user;
|
||||
}
|
||||
|
||||
if (null === $this->userLoader) {
|
||||
throw new \LogicException(sprintf('No user loader is configured, did you forget to register the "%s" listener?', UserProviderListener::class));
|
||||
}
|
||||
|
||||
$user = ($this->userLoader)($this->userIdentifier);
|
||||
|
||||
// No user has been found via the $this->userLoader callback
|
||||
if (null === $user) {
|
||||
$exception = new UserNotFoundException();
|
||||
$exception->setUserIdentifier($this->userIdentifier);
|
||||
|
||||
throw $exception;
|
||||
}
|
||||
|
||||
if (!$user instanceof UserInterface) {
|
||||
throw new AuthenticationServiceException(sprintf('The user provider must return a UserInterface object, "%s" given.', get_debug_type($user)));
|
||||
}
|
||||
|
||||
return $this->user = $user;
|
||||
}
|
||||
|
||||
public function getUserLoader(): ?callable
|
||||
{
|
||||
return $this->userLoader;
|
||||
}
|
||||
|
||||
public function setUserLoader(callable $userLoader): void
|
||||
{
|
||||
$this->userLoader = $userLoader;
|
||||
}
|
||||
|
||||
public function isResolved(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
24
vendor/symfony/security-http/Authenticator/Passport/Credentials/CredentialsInterface.php
vendored
Normal file
24
vendor/symfony/security-http/Authenticator/Passport/Credentials/CredentialsInterface.php
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\Authenticator\Passport\Credentials;
|
||||
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\BadgeInterface;
|
||||
|
||||
/**
|
||||
* Credentials are a special badge used to explicitly mark the
|
||||
* credential check of an authenticator.
|
||||
*
|
||||
* @author Wouter de Jong <wouter@wouterj.nl>
|
||||
*/
|
||||
interface CredentialsInterface extends BadgeInterface
|
||||
{
|
||||
}
|
57
vendor/symfony/security-http/Authenticator/Passport/Credentials/CustomCredentials.php
vendored
Normal file
57
vendor/symfony/security-http/Authenticator/Passport/Credentials/CustomCredentials.php
vendored
Normal file
@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\Authenticator\Passport\Credentials;
|
||||
|
||||
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
|
||||
use Symfony\Component\Security\Core\User\UserInterface;
|
||||
|
||||
/**
|
||||
* Implements credentials checking using a custom checker function.
|
||||
*
|
||||
* @author Wouter de Jong <wouter@wouterj.nl>
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
class CustomCredentials implements CredentialsInterface
|
||||
{
|
||||
private $customCredentialsChecker;
|
||||
private $credentials;
|
||||
private $resolved = false;
|
||||
|
||||
/**
|
||||
* @param callable $customCredentialsChecker the check function. If this function does not return `true`, a
|
||||
* BadCredentialsException is thrown. You may also throw a more
|
||||
* specific exception in the function.
|
||||
* @param mixed $credentials
|
||||
*/
|
||||
public function __construct(callable $customCredentialsChecker, $credentials)
|
||||
{
|
||||
$this->customCredentialsChecker = $customCredentialsChecker;
|
||||
$this->credentials = $credentials;
|
||||
}
|
||||
|
||||
public function executeCustomChecker(UserInterface $user): void
|
||||
{
|
||||
$checker = $this->customCredentialsChecker;
|
||||
|
||||
if (true !== $checker($this->credentials, $user)) {
|
||||
throw new BadCredentialsException('Credentials check failed as the callable passed to CustomCredentials did not return "true".');
|
||||
}
|
||||
|
||||
$this->resolved = true;
|
||||
}
|
||||
|
||||
public function isResolved(): bool
|
||||
{
|
||||
return $this->resolved;
|
||||
}
|
||||
}
|
58
vendor/symfony/security-http/Authenticator/Passport/Credentials/PasswordCredentials.php
vendored
Normal file
58
vendor/symfony/security-http/Authenticator/Passport/Credentials/PasswordCredentials.php
vendored
Normal file
@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\Authenticator\Passport\Credentials;
|
||||
|
||||
use Symfony\Component\Security\Core\Exception\LogicException;
|
||||
|
||||
/**
|
||||
* Implements password credentials.
|
||||
*
|
||||
* These plaintext passwords are checked by the UserPasswordEncoder during
|
||||
* authentication.
|
||||
*
|
||||
* @author Wouter de Jong <wouter@wouterj.nl>
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
class PasswordCredentials implements CredentialsInterface
|
||||
{
|
||||
private $password;
|
||||
private $resolved = false;
|
||||
|
||||
public function __construct(string $password)
|
||||
{
|
||||
$this->password = $password;
|
||||
}
|
||||
|
||||
public function getPassword(): string
|
||||
{
|
||||
if (null === $this->password) {
|
||||
throw new LogicException('The credentials are erased as another listener already verified these credentials.');
|
||||
}
|
||||
|
||||
return $this->password;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
public function markResolved(): void
|
||||
{
|
||||
$this->resolved = true;
|
||||
$this->password = null;
|
||||
}
|
||||
|
||||
public function isResolved(): bool
|
||||
{
|
||||
return $this->resolved;
|
||||
}
|
||||
}
|
111
vendor/symfony/security-http/Authenticator/Passport/Passport.php
vendored
Normal file
111
vendor/symfony/security-http/Authenticator/Passport/Passport.php
vendored
Normal file
@ -0,0 +1,111 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\Authenticator\Passport;
|
||||
|
||||
use Symfony\Component\Security\Core\User\UserInterface;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\BadgeInterface;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\Credentials\CredentialsInterface;
|
||||
|
||||
/**
|
||||
* The default implementation for passports.
|
||||
*
|
||||
* @author Wouter de Jong <wouter@wouterj.nl>
|
||||
*/
|
||||
class Passport implements UserPassportInterface
|
||||
{
|
||||
protected $user;
|
||||
|
||||
private $badges = [];
|
||||
private $attributes = [];
|
||||
|
||||
/**
|
||||
* @param CredentialsInterface $credentials the credentials to check for this authentication, use
|
||||
* SelfValidatingPassport if no credentials should be checked
|
||||
* @param BadgeInterface[] $badges
|
||||
*/
|
||||
public function __construct(UserBadge $userBadge, CredentialsInterface $credentials, array $badges = [])
|
||||
{
|
||||
$this->addBadge($userBadge);
|
||||
$this->addBadge($credentials);
|
||||
foreach ($badges as $badge) {
|
||||
$this->addBadge($badge);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getUser(): UserInterface
|
||||
{
|
||||
if (null === $this->user) {
|
||||
if (!$this->hasBadge(UserBadge::class)) {
|
||||
throw new \LogicException('Cannot get the Security user, no username or UserBadge configured for this passport.');
|
||||
}
|
||||
|
||||
$this->user = $this->getBadge(UserBadge::class)->getUser();
|
||||
}
|
||||
|
||||
return $this->user;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
public function addBadge(BadgeInterface $badge): PassportInterface
|
||||
{
|
||||
$this->badges[\get_class($badge)] = $badge;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function hasBadge(string $badgeFqcn): bool
|
||||
{
|
||||
return isset($this->badges[$badgeFqcn]);
|
||||
}
|
||||
|
||||
public function getBadge(string $badgeFqcn): ?BadgeInterface
|
||||
{
|
||||
return $this->badges[$badgeFqcn] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<class-string<BadgeInterface>, BadgeInterface>
|
||||
*/
|
||||
public function getBadges(): array
|
||||
{
|
||||
return $this->badges;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $value
|
||||
*/
|
||||
public function setAttribute(string $name, $value): void
|
||||
{
|
||||
$this->attributes[$name] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $default
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getAttribute(string $name, $default = null)
|
||||
{
|
||||
return $this->attributes[$name] ?? $default;
|
||||
}
|
||||
|
||||
public function getAttributes(): array
|
||||
{
|
||||
return $this->attributes;
|
||||
}
|
||||
}
|
48
vendor/symfony/security-http/Authenticator/Passport/PassportInterface.php
vendored
Normal file
48
vendor/symfony/security-http/Authenticator/Passport/PassportInterface.php
vendored
Normal file
@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\Authenticator\Passport;
|
||||
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\BadgeInterface;
|
||||
|
||||
/**
|
||||
* A Passport contains all security-related information that needs to be
|
||||
* validated during authentication.
|
||||
*
|
||||
* A passport badge can be used to add any additional information to the
|
||||
* passport.
|
||||
*
|
||||
* @author Wouter de Jong <wouter@wouterj.nl>
|
||||
*
|
||||
* @deprecated since Symfony 5.4, use {@link Passport} instead
|
||||
*/
|
||||
interface PassportInterface
|
||||
{
|
||||
/**
|
||||
* Adds a new security badge.
|
||||
*
|
||||
* A passport can hold only one instance of the same security badge.
|
||||
* This method replaces the current badge if it is already set on this
|
||||
* passport.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function addBadge(BadgeInterface $badge): self;
|
||||
|
||||
public function hasBadge(string $badgeFqcn): bool;
|
||||
|
||||
public function getBadge(string $badgeFqcn): ?BadgeInterface;
|
||||
|
||||
/**
|
||||
* @return array<class-string<BadgeInterface>, BadgeInterface>
|
||||
*/
|
||||
public function getBadges(): array;
|
||||
}
|
54
vendor/symfony/security-http/Authenticator/Passport/PassportTrait.php
vendored
Normal file
54
vendor/symfony/security-http/Authenticator/Passport/PassportTrait.php
vendored
Normal file
@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\Authenticator\Passport;
|
||||
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\BadgeInterface;
|
||||
|
||||
trigger_deprecation('symfony/security-http', '5.4', 'The "%s" trait is deprecated, you must extend from "%s" instead.', PassportTrait::class, Passport::class);
|
||||
|
||||
/**
|
||||
* @author Wouter de Jong <wouter@wouterj.nl>
|
||||
*
|
||||
* @deprecated since Symfony 5.4, use {@see Passport} instead
|
||||
*/
|
||||
trait PassportTrait
|
||||
{
|
||||
private $badges = [];
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
public function addBadge(BadgeInterface $badge): PassportInterface
|
||||
{
|
||||
$this->badges[\get_class($badge)] = $badge;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function hasBadge(string $badgeFqcn): bool
|
||||
{
|
||||
return isset($this->badges[$badgeFqcn]);
|
||||
}
|
||||
|
||||
public function getBadge(string $badgeFqcn): ?BadgeInterface
|
||||
{
|
||||
return $this->badges[$badgeFqcn] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<class-string<BadgeInterface>, BadgeInterface>
|
||||
*/
|
||||
public function getBadges(): array
|
||||
{
|
||||
return $this->badges;
|
||||
}
|
||||
}
|
35
vendor/symfony/security-http/Authenticator/Passport/SelfValidatingPassport.php
vendored
Normal file
35
vendor/symfony/security-http/Authenticator/Passport/SelfValidatingPassport.php
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\Authenticator\Passport;
|
||||
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\BadgeInterface;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
|
||||
|
||||
/**
|
||||
* An implementation used when there are no credentials to be checked (e.g.
|
||||
* API token authentication).
|
||||
*
|
||||
* @author Wouter de Jong <wouter@wouterj.nl>
|
||||
*/
|
||||
class SelfValidatingPassport extends Passport
|
||||
{
|
||||
/**
|
||||
* @param BadgeInterface[] $badges
|
||||
*/
|
||||
public function __construct(UserBadge $userBadge, array $badges = [])
|
||||
{
|
||||
$this->addBadge($userBadge);
|
||||
foreach ($badges as $badge) {
|
||||
$this->addBadge($badge);
|
||||
}
|
||||
}
|
||||
}
|
30
vendor/symfony/security-http/Authenticator/Passport/UserPassportInterface.php
vendored
Normal file
30
vendor/symfony/security-http/Authenticator/Passport/UserPassportInterface.php
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\Authenticator\Passport;
|
||||
|
||||
use Symfony\Component\Security\Core\Exception\AuthenticationException;
|
||||
use Symfony\Component\Security\Core\User\UserInterface;
|
||||
|
||||
/**
|
||||
* Represents a passport for a Security User.
|
||||
*
|
||||
* @author Wouter de Jong <wouter@wouterj.nl>
|
||||
*
|
||||
* @deprecated since Symfony 5.4, use {@link Passport} instead
|
||||
*/
|
||||
interface UserPassportInterface extends PassportInterface
|
||||
{
|
||||
/**
|
||||
* @throws AuthenticationException when the user cannot be found
|
||||
*/
|
||||
public function getUser(): UserInterface;
|
||||
}
|
138
vendor/symfony/security-http/Authenticator/RememberMeAuthenticator.php
vendored
Normal file
138
vendor/symfony/security-http/Authenticator/RememberMeAuthenticator.php
vendored
Normal file
@ -0,0 +1,138 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\Authenticator;
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\RememberMeToken;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||
use Symfony\Component\Security\Core\Exception\AuthenticationException;
|
||||
use Symfony\Component\Security\Core\Exception\CookieTheftException;
|
||||
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
|
||||
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\Passport;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\PassportInterface;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\SelfValidatingPassport;
|
||||
use Symfony\Component\Security\Http\RememberMe\RememberMeDetails;
|
||||
use Symfony\Component\Security\Http\RememberMe\RememberMeHandlerInterface;
|
||||
use Symfony\Component\Security\Http\RememberMe\ResponseListener;
|
||||
|
||||
/**
|
||||
* The RememberMe *Authenticator* performs remember me authentication.
|
||||
*
|
||||
* This authenticator is executed whenever a user's session
|
||||
* expired and a remember-me cookie was found. This authenticator
|
||||
* then "re-authenticates" the user using the information in the
|
||||
* cookie.
|
||||
*
|
||||
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
|
||||
* @author Wouter de Jong <wouter@wouterj.nl>
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
class RememberMeAuthenticator implements InteractiveAuthenticatorInterface
|
||||
{
|
||||
private $rememberMeHandler;
|
||||
private $secret;
|
||||
private $tokenStorage;
|
||||
private $cookieName;
|
||||
private $logger;
|
||||
|
||||
public function __construct(RememberMeHandlerInterface $rememberMeHandler, string $secret, TokenStorageInterface $tokenStorage, string $cookieName, LoggerInterface $logger = null)
|
||||
{
|
||||
$this->rememberMeHandler = $rememberMeHandler;
|
||||
$this->secret = $secret;
|
||||
$this->tokenStorage = $tokenStorage;
|
||||
$this->cookieName = $cookieName;
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
public function supports(Request $request): ?bool
|
||||
{
|
||||
// do not overwrite already stored tokens (i.e. from the session)
|
||||
if (null !== $this->tokenStorage->getToken()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (($cookie = $request->attributes->get(ResponseListener::COOKIE_ATTR_NAME)) && null === $cookie->getValue()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!$request->cookies->has($this->cookieName)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (null !== $this->logger) {
|
||||
$this->logger->debug('Remember-me cookie detected.');
|
||||
}
|
||||
|
||||
// the `null` return value indicates that this authenticator supports lazy firewalls
|
||||
return null;
|
||||
}
|
||||
|
||||
public function authenticate(Request $request): PassportInterface
|
||||
{
|
||||
$rawCookie = $request->cookies->get($this->cookieName);
|
||||
if (!$rawCookie) {
|
||||
throw new \LogicException('No remember-me cookie is found.');
|
||||
}
|
||||
|
||||
$rememberMeCookie = RememberMeDetails::fromRawCookie($rawCookie);
|
||||
|
||||
return new SelfValidatingPassport(new UserBadge($rememberMeCookie->getUserIdentifier(), function () use ($rememberMeCookie) {
|
||||
return $this->rememberMeHandler->consumeRememberMeCookie($rememberMeCookie);
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated since Symfony 5.4, use {@link createToken()} instead
|
||||
*/
|
||||
public function createAuthenticatedToken(PassportInterface $passport, string $firewallName): TokenInterface
|
||||
{
|
||||
trigger_deprecation('symfony/security-http', '5.4', 'Method "%s()" is deprecated, use "%s::createToken()" instead.', __METHOD__, __CLASS__);
|
||||
|
||||
return $this->createToken($passport, $firewallName);
|
||||
}
|
||||
|
||||
public function createToken(Passport $passport, string $firewallName): TokenInterface
|
||||
{
|
||||
return new RememberMeToken($passport->getUser(), $firewallName, $this->secret);
|
||||
}
|
||||
|
||||
public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response
|
||||
{
|
||||
return null; // let the original request continue
|
||||
}
|
||||
|
||||
public function onAuthenticationFailure(Request $request, AuthenticationException $exception): ?Response
|
||||
{
|
||||
if (null !== $this->logger) {
|
||||
if ($exception instanceof UsernameNotFoundException) {
|
||||
$this->logger->info('User for remember-me cookie not found.', ['exception' => $exception]);
|
||||
} elseif ($exception instanceof UnsupportedUserException) {
|
||||
$this->logger->warning('User class for remember-me cookie not supported.', ['exception' => $exception]);
|
||||
} elseif (!$exception instanceof CookieTheftException) {
|
||||
$this->logger->debug('Remember me authentication failed.', ['exception' => $exception]);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function isInteractive(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
50
vendor/symfony/security-http/Authenticator/RemoteUserAuthenticator.php
vendored
Normal file
50
vendor/symfony/security-http/Authenticator/RemoteUserAuthenticator.php
vendored
Normal file
@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\Authenticator;
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
|
||||
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
|
||||
use Symfony\Component\Security\Core\User\UserProviderInterface;
|
||||
|
||||
/**
|
||||
* This authenticator authenticates a remote user.
|
||||
*
|
||||
* @author Wouter de Jong <wouter@wouterj.nl>
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Maxime Douailin <maxime.douailin@gmail.com>
|
||||
*
|
||||
* @final
|
||||
*
|
||||
* @internal in Symfony 5.1
|
||||
*/
|
||||
class RemoteUserAuthenticator extends AbstractPreAuthenticatedAuthenticator
|
||||
{
|
||||
private $userKey;
|
||||
|
||||
public function __construct(UserProviderInterface $userProvider, TokenStorageInterface $tokenStorage, string $firewallName, string $userKey = 'REMOTE_USER', LoggerInterface $logger = null)
|
||||
{
|
||||
parent::__construct($userProvider, $tokenStorage, $firewallName, $logger);
|
||||
|
||||
$this->userKey = $userKey;
|
||||
}
|
||||
|
||||
protected function extractUsername(Request $request): ?string
|
||||
{
|
||||
if (!$request->server->has($this->userKey)) {
|
||||
throw new BadCredentialsException(sprintf('User key was not found: "%s".', $this->userKey));
|
||||
}
|
||||
|
||||
return $request->server->get($this->userKey);
|
||||
}
|
||||
}
|
76
vendor/symfony/security-http/Authenticator/Token/PostAuthenticationToken.php
vendored
Normal file
76
vendor/symfony/security-http/Authenticator/Token/PostAuthenticationToken.php
vendored
Normal file
@ -0,0 +1,76 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\Authenticator\Token;
|
||||
|
||||
use Symfony\Component\Security\Core\Authentication\Token\AbstractToken;
|
||||
use Symfony\Component\Security\Core\User\UserInterface;
|
||||
|
||||
class PostAuthenticationToken extends AbstractToken
|
||||
{
|
||||
private $firewallName;
|
||||
|
||||
/**
|
||||
* @param string[] $roles An array of roles
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function __construct(UserInterface $user, string $firewallName, array $roles)
|
||||
{
|
||||
parent::__construct($roles);
|
||||
|
||||
if ('' === $firewallName) {
|
||||
throw new \InvalidArgumentException('$firewallName must not be empty.');
|
||||
}
|
||||
|
||||
$this->setUser($user);
|
||||
$this->firewallName = $firewallName;
|
||||
|
||||
// @deprecated since Symfony 5.4
|
||||
if (method_exists($this, 'setAuthenticated')) {
|
||||
// this token is meant to be used after authentication success, so it is always authenticated
|
||||
$this->setAuthenticated(true, false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is meant to be only a token, where credentials
|
||||
* have already been used and are thus cleared.
|
||||
*
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCredentials()
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
public function getFirewallName(): string
|
||||
{
|
||||
return $this->firewallName;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function __serialize(): array
|
||||
{
|
||||
return [$this->firewallName, parent::__serialize()];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function __unserialize(array $data): void
|
||||
{
|
||||
[$this->firewallName, $parentData] = $data;
|
||||
parent::__unserialize($parentData);
|
||||
}
|
||||
}
|
60
vendor/symfony/security-http/Authenticator/X509Authenticator.php
vendored
Normal file
60
vendor/symfony/security-http/Authenticator/X509Authenticator.php
vendored
Normal file
@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\Authenticator;
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
|
||||
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
|
||||
use Symfony\Component\Security\Core\User\UserProviderInterface;
|
||||
|
||||
/**
|
||||
* This authenticator authenticates pre-authenticated (by the
|
||||
* webserver) X.509 certificates.
|
||||
*
|
||||
* @author Wouter de Jong <wouter@wouterj.nl>
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
class X509Authenticator extends AbstractPreAuthenticatedAuthenticator
|
||||
{
|
||||
private $userKey;
|
||||
private $credentialsKey;
|
||||
|
||||
public function __construct(UserProviderInterface $userProvider, TokenStorageInterface $tokenStorage, string $firewallName, string $userKey = 'SSL_CLIENT_S_DN_Email', string $credentialsKey = 'SSL_CLIENT_S_DN', LoggerInterface $logger = null)
|
||||
{
|
||||
parent::__construct($userProvider, $tokenStorage, $firewallName, $logger);
|
||||
|
||||
$this->userKey = $userKey;
|
||||
$this->credentialsKey = $credentialsKey;
|
||||
}
|
||||
|
||||
protected function extractUsername(Request $request): string
|
||||
{
|
||||
$username = null;
|
||||
if ($request->server->has($this->userKey)) {
|
||||
$username = $request->server->get($this->userKey);
|
||||
} elseif (
|
||||
$request->server->has($this->credentialsKey)
|
||||
&& preg_match('#emailAddress=([^,/@]++@[^,/]++)#', $request->server->get($this->credentialsKey), $matches)
|
||||
) {
|
||||
$username = $matches[1];
|
||||
}
|
||||
|
||||
if (null === $username) {
|
||||
throw new BadCredentialsException(sprintf('SSL credentials not found: %s, %s', $this->userKey, $this->credentialsKey));
|
||||
}
|
||||
|
||||
return $username;
|
||||
}
|
||||
}
|
32
vendor/symfony/security-http/Authorization/AccessDeniedHandlerInterface.php
vendored
Normal file
32
vendor/symfony/security-http/Authorization/AccessDeniedHandlerInterface.php
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\Authorization;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
|
||||
|
||||
/**
|
||||
* This is used by the ExceptionListener to translate an AccessDeniedException
|
||||
* to a Response object.
|
||||
*
|
||||
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
|
||||
*/
|
||||
interface AccessDeniedHandlerInterface
|
||||
{
|
||||
/**
|
||||
* Handles an access denied failure.
|
||||
*
|
||||
* @return Response|null
|
||||
*/
|
||||
public function handle(Request $request, AccessDeniedException $accessDeniedException);
|
||||
}
|
23
vendor/symfony/security-http/CHANGELOG.md
vendored
Normal file
23
vendor/symfony/security-http/CHANGELOG.md
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
CHANGELOG
|
||||
=========
|
||||
|
||||
5.4
|
||||
---
|
||||
|
||||
* Deprecate the `$authenticationEntryPoint` argument of `ChannelListener`, and add `$httpPort` and `$httpsPort` arguments
|
||||
* Deprecate `RetryAuthenticationEntryPoint`, this code is now inlined in the `ChannelListener`
|
||||
* Deprecate `FormAuthenticationEntryPoint` and `BasicAuthenticationEntryPoint`, in the new system the `FormLoginAuthenticator`
|
||||
and `HttpBasicAuthenticator` should be used instead
|
||||
* Deprecate `AbstractRememberMeServices`, `PersistentTokenBasedRememberMeServices`, `RememberMeServicesInterface`,
|
||||
`TokenBasedRememberMeServices`, use the remember me handler alternatives instead
|
||||
* Deprecate the `$authManager` argument of `AccessListener`
|
||||
* Deprecate not setting the `$exceptionOnNoToken` argument of `AccessListener` to `false`
|
||||
* Deprecate `DeauthenticatedEvent`, use `TokenDeauthenticatedEvent` instead
|
||||
* Deprecate `CookieClearingLogoutHandler`, `SessionLogoutHandler` and `CsrfTokenClearingLogoutHandler`.
|
||||
Use `CookieClearingLogoutListener`, `SessionLogoutListener` and `CsrfTokenClearingLogoutListener` instead
|
||||
* Deprecate `PassportInterface`, `UserPassportInterface` and `PassportTrait`, use `Passport` instead
|
||||
|
||||
5.3
|
||||
---
|
||||
|
||||
The CHANGELOG for version 5.3 and earlier can be found at https://github.com/symfony/symfony/blob/5.3/src/Symfony/Component/Security/CHANGELOG.md
|
60
vendor/symfony/security-http/Controller/UserValueResolver.php
vendored
Normal file
60
vendor/symfony/security-http/Controller/UserValueResolver.php
vendored
Normal file
@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\Controller;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface;
|
||||
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||
use Symfony\Component\Security\Core\User\UserInterface;
|
||||
use Symfony\Component\Security\Http\Attribute\CurrentUser;
|
||||
|
||||
/**
|
||||
* Supports the argument type of {@see UserInterface}.
|
||||
*
|
||||
* @author Iltar van der Berg <kjarli@gmail.com>
|
||||
*/
|
||||
final class UserValueResolver implements ArgumentValueResolverInterface
|
||||
{
|
||||
private $tokenStorage;
|
||||
|
||||
public function __construct(TokenStorageInterface $tokenStorage)
|
||||
{
|
||||
$this->tokenStorage = $tokenStorage;
|
||||
}
|
||||
|
||||
public function supports(Request $request, ArgumentMetadata $argument): bool
|
||||
{
|
||||
// with the attribute, the type can be any UserInterface implementation
|
||||
// otherwise, the type must be UserInterface
|
||||
if (UserInterface::class !== $argument->getType() && !$argument->getAttributes(CurrentUser::class, ArgumentMetadata::IS_INSTANCEOF)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$token = $this->tokenStorage->getToken();
|
||||
if (!$token instanceof TokenInterface) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$user = $token->getUser();
|
||||
|
||||
// in case it's not an object we cannot do anything with it; E.g. "anon."
|
||||
// @deprecated since 5.4
|
||||
return $user instanceof UserInterface;
|
||||
}
|
||||
|
||||
public function resolve(Request $request, ArgumentMetadata $argument): iterable
|
||||
{
|
||||
yield $this->tokenStorage->getToken()->getUser();
|
||||
}
|
||||
}
|
46
vendor/symfony/security-http/EntryPoint/AuthenticationEntryPointInterface.php
vendored
Normal file
46
vendor/symfony/security-http/EntryPoint/AuthenticationEntryPointInterface.php
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\EntryPoint;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Security\Core\Exception\AuthenticationException;
|
||||
|
||||
/**
|
||||
* Implement this interface for any classes that will be called to "start"
|
||||
* the authentication process (see method for more details).
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
interface AuthenticationEntryPointInterface
|
||||
{
|
||||
/**
|
||||
* Returns a response that directs the user to authenticate.
|
||||
*
|
||||
* This is called when an anonymous request accesses a resource that
|
||||
* requires authentication. The job of this method is to return some
|
||||
* response that "helps" the user start into the authentication process.
|
||||
*
|
||||
* Examples:
|
||||
*
|
||||
* - For a form login, you might redirect to the login page
|
||||
*
|
||||
* return new RedirectResponse('/login');
|
||||
*
|
||||
* - For an API token authentication system, you return a 401 response
|
||||
*
|
||||
* return new Response('Auth header required', 401);
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function start(Request $request, AuthenticationException $authException = null);
|
||||
}
|
48
vendor/symfony/security-http/EntryPoint/BasicAuthenticationEntryPoint.php
vendored
Normal file
48
vendor/symfony/security-http/EntryPoint/BasicAuthenticationEntryPoint.php
vendored
Normal file
@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\EntryPoint;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Security\Core\Exception\AuthenticationException;
|
||||
use Symfony\Component\Security\Http\Authenticator\HttpBasicAuthenticator;
|
||||
|
||||
trigger_deprecation('symfony/security-http', '5.4', 'The "%s" class is deprecated, use the new security system with "%s" instead.', BasicAuthenticationEntryPoint::class, HttpBasicAuthenticator::class);
|
||||
|
||||
/**
|
||||
* BasicAuthenticationEntryPoint starts an HTTP Basic authentication.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @deprecated since Symfony 5.4
|
||||
*/
|
||||
class BasicAuthenticationEntryPoint implements AuthenticationEntryPointInterface
|
||||
{
|
||||
private $realmName;
|
||||
|
||||
public function __construct(string $realmName)
|
||||
{
|
||||
$this->realmName = $realmName;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function start(Request $request, AuthenticationException $authException = null)
|
||||
{
|
||||
$response = new Response();
|
||||
$response->headers->set('WWW-Authenticate', sprintf('Basic realm="%s"', $this->realmName));
|
||||
$response->setStatusCode(401);
|
||||
|
||||
return $response;
|
||||
}
|
||||
}
|
22
vendor/symfony/security-http/EntryPoint/Exception/NotAnEntryPointException.php
vendored
Normal file
22
vendor/symfony/security-http/EntryPoint/Exception/NotAnEntryPointException.php
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\EntryPoint\Exception;
|
||||
|
||||
/**
|
||||
* Thrown by generic decorators when a decorated authenticator does not implement
|
||||
* {@see AuthenticationEntryPointInterface}.
|
||||
*
|
||||
* @author Robin Chalas <robin.chalas@gmail.com>
|
||||
*/
|
||||
class NotAnEntryPointException extends \RuntimeException
|
||||
{
|
||||
}
|
66
vendor/symfony/security-http/EntryPoint/FormAuthenticationEntryPoint.php
vendored
Normal file
66
vendor/symfony/security-http/EntryPoint/FormAuthenticationEntryPoint.php
vendored
Normal file
@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\EntryPoint;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\HttpKernelInterface;
|
||||
use Symfony\Component\Security\Core\Exception\AuthenticationException;
|
||||
use Symfony\Component\Security\Http\Authenticator\FormLoginAuthenticator;
|
||||
use Symfony\Component\Security\Http\HttpUtils;
|
||||
|
||||
trigger_deprecation('symfony/security-http', '5.4', 'The "%s" class is deprecated, use the new security system with "%s" instead.', FormAuthenticationEntryPoint::class, FormLoginAuthenticator::class);
|
||||
|
||||
/**
|
||||
* FormAuthenticationEntryPoint starts an authentication via a login form.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @deprecated since Symfony 5.4
|
||||
*/
|
||||
class FormAuthenticationEntryPoint implements AuthenticationEntryPointInterface
|
||||
{
|
||||
private $loginPath;
|
||||
private $useForward;
|
||||
private $httpKernel;
|
||||
private $httpUtils;
|
||||
|
||||
/**
|
||||
* @param string $loginPath The path to the login form
|
||||
* @param bool $useForward Whether to forward or redirect to the login form
|
||||
*/
|
||||
public function __construct(HttpKernelInterface $kernel, HttpUtils $httpUtils, string $loginPath, bool $useForward = false)
|
||||
{
|
||||
$this->httpKernel = $kernel;
|
||||
$this->httpUtils = $httpUtils;
|
||||
$this->loginPath = $loginPath;
|
||||
$this->useForward = $useForward;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function start(Request $request, AuthenticationException $authException = null)
|
||||
{
|
||||
if ($this->useForward) {
|
||||
$subRequest = $this->httpUtils->createRequest($request, $this->loginPath);
|
||||
|
||||
$response = $this->httpKernel->handle($subRequest, HttpKernelInterface::SUB_REQUEST);
|
||||
if (200 === $response->getStatusCode()) {
|
||||
$response->setStatusCode(401);
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
return $this->httpUtils->createRedirectResponse($request, $this->loginPath);
|
||||
}
|
||||
}
|
64
vendor/symfony/security-http/EntryPoint/RetryAuthenticationEntryPoint.php
vendored
Normal file
64
vendor/symfony/security-http/EntryPoint/RetryAuthenticationEntryPoint.php
vendored
Normal file
@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\EntryPoint;
|
||||
|
||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\Security\Core\Exception\AuthenticationException;
|
||||
use Symfony\Component\Security\Http\Firewall\ChannelListener;
|
||||
|
||||
trigger_deprecation('symfony/security-http', '5.4', 'The "%s" class is deprecated, use "%s" directly (and optionally configure the HTTP(s) ports there).', RetryAuthenticationEntryPoint::class, ChannelListener::class);
|
||||
|
||||
/**
|
||||
* RetryAuthenticationEntryPoint redirects URL based on the configured scheme.
|
||||
*
|
||||
* This entry point is not intended to work with HTTP post requests.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @deprecated since Symfony 5.4
|
||||
*/
|
||||
class RetryAuthenticationEntryPoint implements AuthenticationEntryPointInterface
|
||||
{
|
||||
private $httpPort;
|
||||
private $httpsPort;
|
||||
|
||||
public function __construct(int $httpPort = 80, int $httpsPort = 443)
|
||||
{
|
||||
$this->httpPort = $httpPort;
|
||||
$this->httpsPort = $httpsPort;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function start(Request $request, AuthenticationException $authException = null)
|
||||
{
|
||||
$scheme = $request->isSecure() ? 'http' : 'https';
|
||||
if ('http' === $scheme && 80 != $this->httpPort) {
|
||||
$port = ':'.$this->httpPort;
|
||||
} elseif ('https' === $scheme && 443 != $this->httpsPort) {
|
||||
$port = ':'.$this->httpsPort;
|
||||
} else {
|
||||
$port = '';
|
||||
}
|
||||
|
||||
$qs = $request->getQueryString();
|
||||
if (null !== $qs) {
|
||||
$qs = '?'.$qs;
|
||||
}
|
||||
|
||||
$url = $scheme.'://'.$request->getHost().$port.$request->getBaseUrl().$request->getPathInfo().$qs;
|
||||
|
||||
return new RedirectResponse($url, 301);
|
||||
}
|
||||
}
|
56
vendor/symfony/security-http/Event/AuthenticationTokenCreatedEvent.php
vendored
Normal file
56
vendor/symfony/security-http/Event/AuthenticationTokenCreatedEvent.php
vendored
Normal file
@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\Event;
|
||||
|
||||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\Passport;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\PassportInterface;
|
||||
use Symfony\Contracts\EventDispatcher\Event;
|
||||
|
||||
/**
|
||||
* When a newly authenticated security token was created, before it becomes effective in the security system.
|
||||
*
|
||||
* @author Christian Scheb <me@christianscheb.de>
|
||||
*/
|
||||
class AuthenticationTokenCreatedEvent extends Event
|
||||
{
|
||||
private $authenticatedToken;
|
||||
private $passport;
|
||||
|
||||
/**
|
||||
* @param Passport $passport
|
||||
*/
|
||||
public function __construct(TokenInterface $token, PassportInterface $passport)
|
||||
{
|
||||
if (!$passport instanceof Passport) {
|
||||
trigger_deprecation('symfony/security-http', '5.4', 'Not passing an instance of "%s" as "$passport" argument of "%s()" is deprecated, "%s" given.', Passport::class, __METHOD__, get_debug_type($passport));
|
||||
}
|
||||
|
||||
$this->authenticatedToken = $token;
|
||||
$this->passport = $passport;
|
||||
}
|
||||
|
||||
public function getAuthenticatedToken(): TokenInterface
|
||||
{
|
||||
return $this->authenticatedToken;
|
||||
}
|
||||
|
||||
public function setAuthenticatedToken(TokenInterface $authenticatedToken): void
|
||||
{
|
||||
$this->authenticatedToken = $authenticatedToken;
|
||||
}
|
||||
|
||||
public function getPassport(): PassportInterface
|
||||
{
|
||||
return $this->passport;
|
||||
}
|
||||
}
|
55
vendor/symfony/security-http/Event/CheckPassportEvent.php
vendored
Normal file
55
vendor/symfony/security-http/Event/CheckPassportEvent.php
vendored
Normal file
@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\Event;
|
||||
|
||||
use Symfony\Component\Security\Http\Authenticator\AuthenticatorInterface;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\Passport;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\PassportInterface;
|
||||
use Symfony\Contracts\EventDispatcher\Event;
|
||||
|
||||
/**
|
||||
* This event is dispatched when the credentials have to be checked.
|
||||
*
|
||||
* Listeners to this event must validate the user and the
|
||||
* credentials (e.g. default listeners do password verification and
|
||||
* user checking)
|
||||
*
|
||||
* @author Wouter de Jong <wouter@wouterj.nl>
|
||||
*/
|
||||
class CheckPassportEvent extends Event
|
||||
{
|
||||
private $authenticator;
|
||||
private $passport;
|
||||
|
||||
/**
|
||||
* @param Passport $passport
|
||||
*/
|
||||
public function __construct(AuthenticatorInterface $authenticator, PassportInterface $passport)
|
||||
{
|
||||
if (!$passport instanceof Passport) {
|
||||
trigger_deprecation('symfony/security-http', '5.4', 'Not passing an instance of "%s" as "$passport" argument of "%s()" is deprecated, "%s" given.', Passport::class, __METHOD__, get_debug_type($passport));
|
||||
}
|
||||
|
||||
$this->authenticator = $authenticator;
|
||||
$this->passport = $passport;
|
||||
}
|
||||
|
||||
public function getAuthenticator(): AuthenticatorInterface
|
||||
{
|
||||
return $this->authenticator;
|
||||
}
|
||||
|
||||
public function getPassport(): PassportInterface
|
||||
{
|
||||
return $this->passport;
|
||||
}
|
||||
}
|
56
vendor/symfony/security-http/Event/DeauthenticatedEvent.php
vendored
Normal file
56
vendor/symfony/security-http/Event/DeauthenticatedEvent.php
vendored
Normal file
@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\Event;
|
||||
|
||||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||
use Symfony\Contracts\EventDispatcher\Event;
|
||||
|
||||
/**
|
||||
* Deauthentication happens in case the user has changed when trying to
|
||||
* refresh the token.
|
||||
*
|
||||
* Use {@see TokenDeauthenticatedEvent} if you want to cover all cases where
|
||||
* a session is deauthenticated.
|
||||
*
|
||||
* @author Hamza Amrouche <hamza.simperfit@gmail.com>
|
||||
*
|
||||
* @deprecated since Symfony 5.4, use TokenDeauthenticatedEvent instead
|
||||
*/
|
||||
final class DeauthenticatedEvent extends Event
|
||||
{
|
||||
private $originalToken;
|
||||
private $refreshedToken;
|
||||
|
||||
public function __construct(TokenInterface $originalToken, TokenInterface $refreshedToken, bool $triggerDeprecation = true)
|
||||
{
|
||||
if ($triggerDeprecation) {
|
||||
@trigger_deprecation('symfony/security-http', '5.4', 'Class "%s" is deprecated, use "%s" instead.', __CLASS__, TokenDeauthenticatedEvent::class);
|
||||
}
|
||||
|
||||
$this->originalToken = $originalToken;
|
||||
$this->refreshedToken = $refreshedToken;
|
||||
}
|
||||
|
||||
public function getRefreshedToken(): TokenInterface
|
||||
{
|
||||
@trigger_deprecation('symfony/security-http', '5.4', 'Class "%s" is deprecated, use "%s" instead.', __CLASS__, TokenDeauthenticatedEvent::class);
|
||||
|
||||
return $this->refreshedToken;
|
||||
}
|
||||
|
||||
public function getOriginalToken(): TokenInterface
|
||||
{
|
||||
@trigger_deprecation('symfony/security-http', '5.4', 'Class "%s" is deprecated, use "%s" instead.', __CLASS__, TokenDeauthenticatedEvent::class);
|
||||
|
||||
return $this->originalToken;
|
||||
}
|
||||
}
|
41
vendor/symfony/security-http/Event/InteractiveLoginEvent.php
vendored
Normal file
41
vendor/symfony/security-http/Event/InteractiveLoginEvent.php
vendored
Normal file
@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\Event;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||
use Symfony\Contracts\EventDispatcher\Event;
|
||||
|
||||
/**
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
final class InteractiveLoginEvent extends Event
|
||||
{
|
||||
private $request;
|
||||
private $authenticationToken;
|
||||
|
||||
public function __construct(Request $request, TokenInterface $authenticationToken)
|
||||
{
|
||||
$this->request = $request;
|
||||
$this->authenticationToken = $authenticationToken;
|
||||
}
|
||||
|
||||
public function getRequest(): Request
|
||||
{
|
||||
return $this->request;
|
||||
}
|
||||
|
||||
public function getAuthenticationToken(): TokenInterface
|
||||
{
|
||||
return $this->authenticationToken;
|
||||
}
|
||||
}
|
86
vendor/symfony/security-http/Event/LazyResponseEvent.php
vendored
Normal file
86
vendor/symfony/security-http/Event/LazyResponseEvent.php
vendored
Normal file
@ -0,0 +1,86 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\Event;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\Event\RequestEvent;
|
||||
use Symfony\Component\HttpKernel\HttpKernelInterface;
|
||||
use Symfony\Component\Security\Core\Exception\LazyResponseException;
|
||||
|
||||
/**
|
||||
* Wraps a lazily computed response in a signaling exception.
|
||||
*
|
||||
* @author Nicolas Grekas <p@tchwork.com>
|
||||
*/
|
||||
final class LazyResponseEvent extends RequestEvent
|
||||
{
|
||||
private $event;
|
||||
|
||||
public function __construct(parent $event)
|
||||
{
|
||||
$this->event = $event;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setResponse(Response $response)
|
||||
{
|
||||
$this->stopPropagation();
|
||||
$this->event->stopPropagation();
|
||||
|
||||
throw new LazyResponseException($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getKernel(): HttpKernelInterface
|
||||
{
|
||||
return $this->event->getKernel();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getRequest(): Request
|
||||
{
|
||||
return $this->event->getRequest();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getRequestType(): int
|
||||
{
|
||||
return $this->event->getRequestType();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isMainRequest(): bool
|
||||
{
|
||||
return $this->event->isMainRequest();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isMasterRequest(): bool
|
||||
{
|
||||
trigger_deprecation('symfony/security-http', '5.3', '"%s()" is deprecated, use "isMainRequest()" instead.', __METHOD__);
|
||||
|
||||
return $this->event->isMainRequest();
|
||||
}
|
||||
}
|
90
vendor/symfony/security-http/Event/LoginFailureEvent.php
vendored
Normal file
90
vendor/symfony/security-http/Event/LoginFailureEvent.php
vendored
Normal file
@ -0,0 +1,90 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\Event;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Security\Core\Exception\AuthenticationException;
|
||||
use Symfony\Component\Security\Http\Authenticator\AuthenticatorInterface;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\Passport;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\PassportInterface;
|
||||
use Symfony\Contracts\EventDispatcher\Event;
|
||||
|
||||
/**
|
||||
* This event is dispatched after an error during authentication.
|
||||
*
|
||||
* Listeners to this event can change state based on authentication
|
||||
* failure (e.g. to implement login throttling).
|
||||
*
|
||||
* @author Wouter de Jong <wouter@wouterj.nl>
|
||||
*/
|
||||
class LoginFailureEvent extends Event
|
||||
{
|
||||
private $exception;
|
||||
private $authenticator;
|
||||
private $request;
|
||||
private $response;
|
||||
private $firewallName;
|
||||
private $passport;
|
||||
|
||||
/**
|
||||
* @param Passport|null $passport
|
||||
*/
|
||||
public function __construct(AuthenticationException $exception, AuthenticatorInterface $authenticator, Request $request, ?Response $response, string $firewallName, PassportInterface $passport = null)
|
||||
{
|
||||
if (null !== $passport && !$passport instanceof Passport) {
|
||||
trigger_deprecation('symfony/security-http', '5.4', 'Not passing an instance of "%s" or "null" as "$passport" argument of "%s()" is deprecated, "%s" given.', Passport::class, __METHOD__, get_debug_type($passport));
|
||||
}
|
||||
|
||||
$this->exception = $exception;
|
||||
$this->authenticator = $authenticator;
|
||||
$this->request = $request;
|
||||
$this->response = $response;
|
||||
$this->firewallName = $firewallName;
|
||||
$this->passport = $passport;
|
||||
}
|
||||
|
||||
public function getException(): AuthenticationException
|
||||
{
|
||||
return $this->exception;
|
||||
}
|
||||
|
||||
public function getAuthenticator(): AuthenticatorInterface
|
||||
{
|
||||
return $this->authenticator;
|
||||
}
|
||||
|
||||
public function getFirewallName(): string
|
||||
{
|
||||
return $this->firewallName;
|
||||
}
|
||||
|
||||
public function getRequest(): Request
|
||||
{
|
||||
return $this->request;
|
||||
}
|
||||
|
||||
public function setResponse(?Response $response)
|
||||
{
|
||||
$this->response = $response;
|
||||
}
|
||||
|
||||
public function getResponse(): ?Response
|
||||
{
|
||||
return $this->response;
|
||||
}
|
||||
|
||||
public function getPassport(): ?PassportInterface
|
||||
{
|
||||
return $this->passport;
|
||||
}
|
||||
}
|
105
vendor/symfony/security-http/Event/LoginSuccessEvent.php
vendored
Normal file
105
vendor/symfony/security-http/Event/LoginSuccessEvent.php
vendored
Normal file
@ -0,0 +1,105 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\Event;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||
use Symfony\Component\Security\Core\Exception\LogicException;
|
||||
use Symfony\Component\Security\Core\User\UserInterface;
|
||||
use Symfony\Component\Security\Http\Authenticator\AuthenticatorInterface;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\Passport;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\PassportInterface;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\UserPassportInterface;
|
||||
use Symfony\Contracts\EventDispatcher\Event;
|
||||
|
||||
/**
|
||||
* This event is dispatched after authentication has successfully completed.
|
||||
*
|
||||
* At this stage, the authenticator created a token and
|
||||
* generated an authentication success response. Listeners to
|
||||
* this event can do actions related to successful authentication
|
||||
* (such as migrating the password).
|
||||
*
|
||||
* @author Wouter de Jong <wouter@wouterj.nl>
|
||||
*/
|
||||
class LoginSuccessEvent extends Event
|
||||
{
|
||||
private $authenticator;
|
||||
private $passport;
|
||||
private $authenticatedToken;
|
||||
private $request;
|
||||
private $response;
|
||||
private $firewallName;
|
||||
|
||||
/**
|
||||
* @param Passport $passport
|
||||
*/
|
||||
public function __construct(AuthenticatorInterface $authenticator, PassportInterface $passport, TokenInterface $authenticatedToken, Request $request, ?Response $response, string $firewallName)
|
||||
{
|
||||
if (!$passport instanceof Passport) {
|
||||
trigger_deprecation('symfony/security-http', '5.4', 'Not passing an instance of "%s" as "$passport" argument of "%s()" is deprecated, "%s" given.', Passport::class, __METHOD__, get_debug_type($passport));
|
||||
}
|
||||
|
||||
$this->authenticator = $authenticator;
|
||||
$this->passport = $passport;
|
||||
$this->authenticatedToken = $authenticatedToken;
|
||||
$this->request = $request;
|
||||
$this->response = $response;
|
||||
$this->firewallName = $firewallName;
|
||||
}
|
||||
|
||||
public function getAuthenticator(): AuthenticatorInterface
|
||||
{
|
||||
return $this->authenticator;
|
||||
}
|
||||
|
||||
public function getPassport(): PassportInterface
|
||||
{
|
||||
return $this->passport;
|
||||
}
|
||||
|
||||
public function getUser(): UserInterface
|
||||
{
|
||||
// @deprecated since Symfony 5.4, passport will always have a user in 6.0
|
||||
if (!$this->passport instanceof UserPassportInterface) {
|
||||
throw new LogicException(sprintf('Cannot call "%s" as the authenticator ("%s") did not set a user.', __METHOD__, \get_class($this->authenticator)));
|
||||
}
|
||||
|
||||
return $this->passport->getUser();
|
||||
}
|
||||
|
||||
public function getAuthenticatedToken(): TokenInterface
|
||||
{
|
||||
return $this->authenticatedToken;
|
||||
}
|
||||
|
||||
public function getRequest(): Request
|
||||
{
|
||||
return $this->request;
|
||||
}
|
||||
|
||||
public function getFirewallName(): string
|
||||
{
|
||||
return $this->firewallName;
|
||||
}
|
||||
|
||||
public function setResponse(?Response $response): void
|
||||
{
|
||||
$this->response = $response;
|
||||
}
|
||||
|
||||
public function getResponse(): ?Response
|
||||
{
|
||||
return $this->response;
|
||||
}
|
||||
}
|
53
vendor/symfony/security-http/Event/LogoutEvent.php
vendored
Normal file
53
vendor/symfony/security-http/Event/LogoutEvent.php
vendored
Normal file
@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\Event;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||
use Symfony\Contracts\EventDispatcher\Event;
|
||||
|
||||
/**
|
||||
* @author Wouter de Jong <wouter@wouterj.nl>
|
||||
*/
|
||||
class LogoutEvent extends Event
|
||||
{
|
||||
private $request;
|
||||
private $response;
|
||||
private $token;
|
||||
|
||||
public function __construct(Request $request, ?TokenInterface $token)
|
||||
{
|
||||
$this->request = $request;
|
||||
$this->token = $token;
|
||||
}
|
||||
|
||||
public function getRequest(): Request
|
||||
{
|
||||
return $this->request;
|
||||
}
|
||||
|
||||
public function getToken(): ?TokenInterface
|
||||
{
|
||||
return $this->token;
|
||||
}
|
||||
|
||||
public function setResponse(Response $response): void
|
||||
{
|
||||
$this->response = $response;
|
||||
}
|
||||
|
||||
public function getResponse(): ?Response
|
||||
{
|
||||
return $this->response;
|
||||
}
|
||||
}
|
56
vendor/symfony/security-http/Event/SwitchUserEvent.php
vendored
Normal file
56
vendor/symfony/security-http/Event/SwitchUserEvent.php
vendored
Normal file
@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\Event;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||
use Symfony\Component\Security\Core\User\UserInterface;
|
||||
use Symfony\Contracts\EventDispatcher\Event;
|
||||
|
||||
/**
|
||||
* SwitchUserEvent.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
final class SwitchUserEvent extends Event
|
||||
{
|
||||
private $request;
|
||||
private $targetUser;
|
||||
private $token;
|
||||
|
||||
public function __construct(Request $request, UserInterface $targetUser, TokenInterface $token = null)
|
||||
{
|
||||
$this->request = $request;
|
||||
$this->targetUser = $targetUser;
|
||||
$this->token = $token;
|
||||
}
|
||||
|
||||
public function getRequest(): Request
|
||||
{
|
||||
return $this->request;
|
||||
}
|
||||
|
||||
public function getTargetUser(): UserInterface
|
||||
{
|
||||
return $this->targetUser;
|
||||
}
|
||||
|
||||
public function getToken(): ?TokenInterface
|
||||
{
|
||||
return $this->token;
|
||||
}
|
||||
|
||||
public function setToken(TokenInterface $token)
|
||||
{
|
||||
$this->token = $token;
|
||||
}
|
||||
}
|
51
vendor/symfony/security-http/Event/TokenDeauthenticatedEvent.php
vendored
Normal file
51
vendor/symfony/security-http/Event/TokenDeauthenticatedEvent.php
vendored
Normal file
@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\Event;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||
use Symfony\Contracts\EventDispatcher\Event;
|
||||
|
||||
/**
|
||||
* This event is dispatched when the current security token is deauthenticated
|
||||
* when trying to reference the token.
|
||||
*
|
||||
* This includes changes in the user ({@see DeauthenticatedEvent}), but
|
||||
* also cases where there is no user provider available to refresh the user.
|
||||
*
|
||||
* Use this event if you want to trigger some actions whenever a user is
|
||||
* deauthenticated and redirected back to the authentication entry point
|
||||
* (e.g. clearing all remember-me cookies).
|
||||
*
|
||||
* @author Wouter de Jong <wouter@wouterj.nl>
|
||||
*/
|
||||
final class TokenDeauthenticatedEvent extends Event
|
||||
{
|
||||
private $originalToken;
|
||||
private $request;
|
||||
|
||||
public function __construct(TokenInterface $originalToken, Request $request)
|
||||
{
|
||||
$this->originalToken = $originalToken;
|
||||
$this->request = $request;
|
||||
}
|
||||
|
||||
public function getOriginalToken(): TokenInterface
|
||||
{
|
||||
return $this->originalToken;
|
||||
}
|
||||
|
||||
public function getRequest(): Request
|
||||
{
|
||||
return $this->request;
|
||||
}
|
||||
}
|
119
vendor/symfony/security-http/EventListener/CheckCredentialsListener.php
vendored
Normal file
119
vendor/symfony/security-http/EventListener/CheckCredentialsListener.php
vendored
Normal file
@ -0,0 +1,119 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\EventListener;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\PasswordHasher\Hasher\PasswordHasherFactoryInterface;
|
||||
use Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface;
|
||||
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
|
||||
use Symfony\Component\Security\Core\User\LegacyPasswordAuthenticatedUserInterface;
|
||||
use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\PasswordUpgradeBadge;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\Credentials\CustomCredentials;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\Credentials\PasswordCredentials;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\UserPassportInterface;
|
||||
use Symfony\Component\Security\Http\Event\CheckPassportEvent;
|
||||
|
||||
/**
|
||||
* This listeners uses the interfaces of authenticators to
|
||||
* determine how to check credentials.
|
||||
*
|
||||
* @author Wouter de Jong <wouter@driveamber.com>
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
class CheckCredentialsListener implements EventSubscriberInterface
|
||||
{
|
||||
private $hasherFactory;
|
||||
|
||||
/**
|
||||
* @param PasswordHasherFactoryInterface $hasherFactory
|
||||
*/
|
||||
public function __construct($hasherFactory)
|
||||
{
|
||||
if ($hasherFactory instanceof EncoderFactoryInterface) {
|
||||
trigger_deprecation('symfony/security-core', '5.3', 'Passing a "%s" instance to the "%s" constructor is deprecated, use "%s" instead.', EncoderFactoryInterface::class, __CLASS__, PasswordHasherFactoryInterface::class);
|
||||
}
|
||||
|
||||
$this->hasherFactory = $hasherFactory;
|
||||
}
|
||||
|
||||
public function checkPassport(CheckPassportEvent $event): void
|
||||
{
|
||||
$passport = $event->getPassport();
|
||||
if ($passport instanceof UserPassportInterface && $passport->hasBadge(PasswordCredentials::class)) {
|
||||
// Use the password hasher to validate the credentials
|
||||
$user = $passport->getUser();
|
||||
|
||||
if (!$user instanceof PasswordAuthenticatedUserInterface) {
|
||||
trigger_deprecation('symfony/security-http', '5.3', 'Not implementing the "%s" interface in class "%s" while using password-based authentication is deprecated.', PasswordAuthenticatedUserInterface::class, get_debug_type($user));
|
||||
}
|
||||
|
||||
/** @var PasswordCredentials $badge */
|
||||
$badge = $passport->getBadge(PasswordCredentials::class);
|
||||
|
||||
if ($badge->isResolved()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$presentedPassword = $badge->getPassword();
|
||||
if ('' === $presentedPassword) {
|
||||
throw new BadCredentialsException('The presented password cannot be empty.');
|
||||
}
|
||||
|
||||
if (null === $user->getPassword()) {
|
||||
throw new BadCredentialsException('The presented password is invalid.');
|
||||
}
|
||||
|
||||
$salt = method_exists($user, 'getSalt') ? $user->getSalt() : '';
|
||||
if ($salt && !$user instanceof LegacyPasswordAuthenticatedUserInterface) {
|
||||
trigger_deprecation('symfony/security-http', '5.3', 'Returning a string from "getSalt()" without implementing the "%s" interface is deprecated, the "%s" class should implement it.', LegacyPasswordAuthenticatedUserInterface::class, get_debug_type($user));
|
||||
}
|
||||
|
||||
// @deprecated since Symfony 5.3
|
||||
if ($this->hasherFactory instanceof EncoderFactoryInterface) {
|
||||
if (!$this->hasherFactory->getEncoder($user)->isPasswordValid($user->getPassword(), $presentedPassword, $salt)) {
|
||||
throw new BadCredentialsException('The presented password is invalid.');
|
||||
}
|
||||
} else {
|
||||
if (!$this->hasherFactory->getPasswordHasher($user)->verify($user->getPassword(), $presentedPassword, $salt)) {
|
||||
throw new BadCredentialsException('The presented password is invalid.');
|
||||
}
|
||||
}
|
||||
|
||||
$badge->markResolved();
|
||||
|
||||
if (!$passport->hasBadge(PasswordUpgradeBadge::class)) {
|
||||
$passport->addBadge(new PasswordUpgradeBadge($presentedPassword));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ($passport->hasBadge(CustomCredentials::class)) {
|
||||
/** @var CustomCredentials $badge */
|
||||
$badge = $passport->getBadge(CustomCredentials::class);
|
||||
if ($badge->isResolved()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$badge->executeCustomChecker($passport->getUser());
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [CheckPassportEvent::class => 'checkPassport'];
|
||||
}
|
||||
}
|
74
vendor/symfony/security-http/EventListener/CheckRememberMeConditionsListener.php
vendored
Normal file
74
vendor/symfony/security-http/EventListener/CheckRememberMeConditionsListener.php
vendored
Normal file
@ -0,0 +1,74 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\EventListener;
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\RememberMeBadge;
|
||||
use Symfony\Component\Security\Http\Event\LoginSuccessEvent;
|
||||
use Symfony\Component\Security\Http\ParameterBagUtils;
|
||||
|
||||
/**
|
||||
* Checks if all conditions are met for remember me.
|
||||
*
|
||||
* The conditions that must be met for this listener to enable remember me:
|
||||
* A) This badge is present in the Passport
|
||||
* B) The remember_me key under your firewall is configured
|
||||
* C) The "remember me" functionality is activated. This is usually
|
||||
* done by having a _remember_me checkbox in your form, but
|
||||
* can be configured by the "always_remember_me" and "remember_me_parameter"
|
||||
* parameters under the "remember_me" firewall key (or "always_remember_me"
|
||||
* is enabled)
|
||||
*
|
||||
* @author Wouter de Jong <wouter@wouterj.nl>
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
class CheckRememberMeConditionsListener implements EventSubscriberInterface
|
||||
{
|
||||
private $options;
|
||||
private $logger;
|
||||
|
||||
public function __construct(array $options = [], LoggerInterface $logger = null)
|
||||
{
|
||||
$this->options = $options + ['always_remember_me' => false, 'remember_me_parameter' => '_remember_me'];
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
public function onSuccessfulLogin(LoginSuccessEvent $event): void
|
||||
{
|
||||
$passport = $event->getPassport();
|
||||
if (!$passport->hasBadge(RememberMeBadge::class)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/** @var RememberMeBadge $badge */
|
||||
$badge = $passport->getBadge(RememberMeBadge::class);
|
||||
if (!$this->options['always_remember_me']) {
|
||||
$parameter = ParameterBagUtils::getRequestParameterValue($event->getRequest(), $this->options['remember_me_parameter']);
|
||||
if (!('true' === $parameter || 'on' === $parameter || '1' === $parameter || 'yes' === $parameter || true === $parameter)) {
|
||||
if (null !== $this->logger) {
|
||||
$this->logger->debug('Remember me disabled; request does not contain remember me parameter ("{parameter}").', ['parameter' => $this->options['remember_me_parameter']]);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
$badge->enable();
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [LoginSuccessEvent::class => ['onSuccessfulLogin', -32]];
|
||||
}
|
||||
}
|
53
vendor/symfony/security-http/EventListener/CookieClearingLogoutListener.php
vendored
Normal file
53
vendor/symfony/security-http/EventListener/CookieClearingLogoutListener.php
vendored
Normal file
@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\EventListener;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\Security\Http\Event\LogoutEvent;
|
||||
|
||||
/**
|
||||
* This listener clears the passed cookies when a user logs out.
|
||||
*
|
||||
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
class CookieClearingLogoutListener implements EventSubscriberInterface
|
||||
{
|
||||
private $cookies;
|
||||
|
||||
/**
|
||||
* @param array $cookies An array of cookies (keys are names, values contain path and domain) to unset
|
||||
*/
|
||||
public function __construct(array $cookies)
|
||||
{
|
||||
$this->cookies = $cookies;
|
||||
}
|
||||
|
||||
public function onLogout(LogoutEvent $event): void
|
||||
{
|
||||
if (!$response = $event->getResponse()) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($this->cookies as $cookieName => $cookieData) {
|
||||
$response->headers->clearCookie($cookieName, $cookieData['path'], $cookieData['domain'], $cookieData['secure'] ?? false, true, $cookieData['samesite'] ?? null);
|
||||
}
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [
|
||||
LogoutEvent::class => ['onLogout', -255],
|
||||
];
|
||||
}
|
||||
}
|
61
vendor/symfony/security-http/EventListener/CsrfProtectionListener.php
vendored
Normal file
61
vendor/symfony/security-http/EventListener/CsrfProtectionListener.php
vendored
Normal file
@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\EventListener;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\Security\Core\Exception\InvalidCsrfTokenException;
|
||||
use Symfony\Component\Security\Csrf\CsrfToken;
|
||||
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\CsrfTokenBadge;
|
||||
use Symfony\Component\Security\Http\Event\CheckPassportEvent;
|
||||
|
||||
/**
|
||||
* @author Wouter de Jong <wouter@wouterj.nl>
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
class CsrfProtectionListener implements EventSubscriberInterface
|
||||
{
|
||||
private $csrfTokenManager;
|
||||
|
||||
public function __construct(CsrfTokenManagerInterface $csrfTokenManager)
|
||||
{
|
||||
$this->csrfTokenManager = $csrfTokenManager;
|
||||
}
|
||||
|
||||
public function checkPassport(CheckPassportEvent $event): void
|
||||
{
|
||||
$passport = $event->getPassport();
|
||||
if (!$passport->hasBadge(CsrfTokenBadge::class)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/** @var CsrfTokenBadge $badge */
|
||||
$badge = $passport->getBadge(CsrfTokenBadge::class);
|
||||
if ($badge->isResolved()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$csrfToken = new CsrfToken($badge->getCsrfTokenId(), $badge->getCsrfToken());
|
||||
|
||||
if (false === $this->csrfTokenManager->isTokenValid($csrfToken)) {
|
||||
throw new InvalidCsrfTokenException('Invalid CSRF token.');
|
||||
}
|
||||
|
||||
$badge->markResolved();
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [CheckPassportEvent::class => ['checkPassport', 512]];
|
||||
}
|
||||
}
|
43
vendor/symfony/security-http/EventListener/CsrfTokenClearingLogoutListener.php
vendored
Normal file
43
vendor/symfony/security-http/EventListener/CsrfTokenClearingLogoutListener.php
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\EventListener;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\Security\Csrf\TokenStorage\ClearableTokenStorageInterface;
|
||||
use Symfony\Component\Security\Http\Event\LogoutEvent;
|
||||
|
||||
/**
|
||||
* @author Christian Flothmann <christian.flothmann@sensiolabs.de>
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
class CsrfTokenClearingLogoutListener implements EventSubscriberInterface
|
||||
{
|
||||
private $csrfTokenStorage;
|
||||
|
||||
public function __construct(ClearableTokenStorageInterface $csrfTokenStorage)
|
||||
{
|
||||
$this->csrfTokenStorage = $csrfTokenStorage;
|
||||
}
|
||||
|
||||
public function onLogout(LogoutEvent $event): void
|
||||
{
|
||||
$this->csrfTokenStorage->clear();
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [
|
||||
LogoutEvent::class => 'onLogout',
|
||||
];
|
||||
}
|
||||
}
|
52
vendor/symfony/security-http/EventListener/DefaultLogoutListener.php
vendored
Normal file
52
vendor/symfony/security-http/EventListener/DefaultLogoutListener.php
vendored
Normal file
@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\EventListener;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\Security\Http\Event\LogoutEvent;
|
||||
use Symfony\Component\Security\Http\HttpUtils;
|
||||
|
||||
/**
|
||||
* Default logout listener will redirect users to a configured path.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Alexander <iam.asm89@gmail.com>
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
class DefaultLogoutListener implements EventSubscriberInterface
|
||||
{
|
||||
private $httpUtils;
|
||||
private $targetUrl;
|
||||
|
||||
public function __construct(HttpUtils $httpUtils, string $targetUrl = '/')
|
||||
{
|
||||
$this->httpUtils = $httpUtils;
|
||||
$this->targetUrl = $targetUrl;
|
||||
}
|
||||
|
||||
public function onLogout(LogoutEvent $event): void
|
||||
{
|
||||
if (null !== $event->getResponse()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$event->setResponse($this->httpUtils->createRedirectResponse($event->getRequest(), $this->targetUrl));
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [
|
||||
LogoutEvent::class => ['onLogout', 64],
|
||||
];
|
||||
}
|
||||
}
|
65
vendor/symfony/security-http/EventListener/LoginThrottlingListener.php
vendored
Normal file
65
vendor/symfony/security-http/EventListener/LoginThrottlingListener.php
vendored
Normal file
@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\EventListener;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\HttpFoundation\RateLimiter\RequestRateLimiterInterface;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
use Symfony\Component\Security\Core\Exception\TooManyLoginAttemptsAuthenticationException;
|
||||
use Symfony\Component\Security\Core\Security;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
|
||||
use Symfony\Component\Security\Http\Event\CheckPassportEvent;
|
||||
use Symfony\Component\Security\Http\Event\LoginSuccessEvent;
|
||||
|
||||
/**
|
||||
* @author Wouter de Jong <wouter@wouterj.nl>
|
||||
*/
|
||||
final class LoginThrottlingListener implements EventSubscriberInterface
|
||||
{
|
||||
private $requestStack;
|
||||
private $limiter;
|
||||
|
||||
public function __construct(RequestStack $requestStack, RequestRateLimiterInterface $limiter)
|
||||
{
|
||||
$this->requestStack = $requestStack;
|
||||
$this->limiter = $limiter;
|
||||
}
|
||||
|
||||
public function checkPassport(CheckPassportEvent $event): void
|
||||
{
|
||||
$passport = $event->getPassport();
|
||||
if (!$passport->hasBadge(UserBadge::class)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$request = $this->requestStack->getMainRequest();
|
||||
$request->attributes->set(Security::LAST_USERNAME, $passport->getBadge(UserBadge::class)->getUserIdentifier());
|
||||
|
||||
$limit = $this->limiter->consume($request);
|
||||
if (!$limit->isAccepted()) {
|
||||
throw new TooManyLoginAttemptsAuthenticationException(ceil(($limit->getRetryAfter()->getTimestamp() - time()) / 60));
|
||||
}
|
||||
}
|
||||
|
||||
public function onSuccessfulLogin(LoginSuccessEvent $event): void
|
||||
{
|
||||
$this->limiter->reset($event->getRequest());
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [
|
||||
CheckPassportEvent::class => ['checkPassport', 2080],
|
||||
LoginSuccessEvent::class => 'onSuccessfulLogin',
|
||||
];
|
||||
}
|
||||
}
|
96
vendor/symfony/security-http/EventListener/PasswordMigratingListener.php
vendored
Normal file
96
vendor/symfony/security-http/EventListener/PasswordMigratingListener.php
vendored
Normal file
@ -0,0 +1,96 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\EventListener;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\PasswordHasher\Hasher\PasswordHasherFactoryInterface;
|
||||
use Symfony\Component\PasswordHasher\PasswordHasherInterface;
|
||||
use Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface;
|
||||
use Symfony\Component\Security\Core\User\PasswordUpgraderInterface;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\PasswordUpgradeBadge;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\UserPassportInterface;
|
||||
use Symfony\Component\Security\Http\Event\LoginSuccessEvent;
|
||||
|
||||
/**
|
||||
* @author Wouter de Jong <wouter@wouterj.nl>
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
class PasswordMigratingListener implements EventSubscriberInterface
|
||||
{
|
||||
private $hasherFactory;
|
||||
|
||||
/**
|
||||
* @param PasswordHasherFactoryInterface $hasherFactory
|
||||
*/
|
||||
public function __construct($hasherFactory)
|
||||
{
|
||||
if ($hasherFactory instanceof EncoderFactoryInterface) {
|
||||
trigger_deprecation('symfony/security-core', '5.3', 'Passing a "%s" instance to the "%s" constructor is deprecated, use "%s" instead.', EncoderFactoryInterface::class, __CLASS__, PasswordHasherFactoryInterface::class);
|
||||
}
|
||||
|
||||
$this->hasherFactory = $hasherFactory;
|
||||
}
|
||||
|
||||
public function onLoginSuccess(LoginSuccessEvent $event): void
|
||||
{
|
||||
$passport = $event->getPassport();
|
||||
if (!$passport instanceof UserPassportInterface || !$passport->hasBadge(PasswordUpgradeBadge::class)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/** @var PasswordUpgradeBadge $badge */
|
||||
$badge = $passport->getBadge(PasswordUpgradeBadge::class);
|
||||
$plaintextPassword = $badge->getAndErasePlaintextPassword();
|
||||
|
||||
if ('' === $plaintextPassword) {
|
||||
return;
|
||||
}
|
||||
|
||||
$user = $passport->getUser();
|
||||
if (null === $user->getPassword()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$passwordHasher = $this->hasherFactory instanceof EncoderFactoryInterface ? $this->hasherFactory->getEncoder($user) : $this->hasherFactory->getPasswordHasher($user);
|
||||
if (!$passwordHasher->needsRehash($user->getPassword())) {
|
||||
return;
|
||||
}
|
||||
|
||||
$passwordUpgrader = $badge->getPasswordUpgrader();
|
||||
|
||||
if (null === $passwordUpgrader) {
|
||||
if (!$passport->hasBadge(UserBadge::class)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/** @var UserBadge $userBadge */
|
||||
$userBadge = $passport->getBadge(UserBadge::class);
|
||||
$userLoader = $userBadge->getUserLoader();
|
||||
if (\is_array($userLoader) && $userLoader[0] instanceof PasswordUpgraderInterface) {
|
||||
$passwordUpgrader = $userLoader[0];
|
||||
} elseif (!$userLoader instanceof \Closure
|
||||
|| !($passwordUpgrader = (new \ReflectionFunction($userLoader))->getClosureThis()) instanceof PasswordUpgraderInterface
|
||||
) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
$passwordUpgrader->upgradePassword($user, $passwordHasher instanceof PasswordHasherInterface ? $passwordHasher->hash($plaintextPassword, $user->getSalt()) : $passwordHasher->encodePassword($plaintextPassword, $user->getSalt()));
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [LoginSuccessEvent::class => 'onLoginSuccess'];
|
||||
}
|
||||
}
|
91
vendor/symfony/security-http/EventListener/RememberMeListener.php
vendored
Normal file
91
vendor/symfony/security-http/EventListener/RememberMeListener.php
vendored
Normal file
@ -0,0 +1,91 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\EventListener;
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\RememberMeBadge;
|
||||
use Symfony\Component\Security\Http\Event\LoginFailureEvent;
|
||||
use Symfony\Component\Security\Http\Event\LoginSuccessEvent;
|
||||
use Symfony\Component\Security\Http\Event\LogoutEvent;
|
||||
use Symfony\Component\Security\Http\Event\TokenDeauthenticatedEvent;
|
||||
use Symfony\Component\Security\Http\RememberMe\RememberMeHandlerInterface;
|
||||
|
||||
/**
|
||||
* The RememberMe *listener* creates and deletes remember-me cookies.
|
||||
*
|
||||
* Upon login success or failure and support for remember me
|
||||
* in the firewall and authenticator, this listener will create
|
||||
* a remember-me cookie.
|
||||
* Upon login failure, all remember-me cookies are removed.
|
||||
*
|
||||
* @author Wouter de Jong <wouter@wouterj.nl>
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
class RememberMeListener implements EventSubscriberInterface
|
||||
{
|
||||
private $rememberMeHandler;
|
||||
private $logger;
|
||||
|
||||
public function __construct(RememberMeHandlerInterface $rememberMeHandler, LoggerInterface $logger = null)
|
||||
{
|
||||
$this->rememberMeHandler = $rememberMeHandler;
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
public function onSuccessfulLogin(LoginSuccessEvent $event): void
|
||||
{
|
||||
$passport = $event->getPassport();
|
||||
if (!$passport->hasBadge(RememberMeBadge::class)) {
|
||||
if (null !== $this->logger) {
|
||||
$this->logger->debug('Remember me skipped: your authenticator does not support it.', ['authenticator' => \get_class($event->getAuthenticator())]);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Make sure any old remember-me cookies are cancelled
|
||||
$this->rememberMeHandler->clearRememberMeCookie();
|
||||
|
||||
/** @var RememberMeBadge $badge */
|
||||
$badge = $passport->getBadge(RememberMeBadge::class);
|
||||
if (!$badge->isEnabled()) {
|
||||
if (null !== $this->logger) {
|
||||
$this->logger->debug('Remember me skipped: the RememberMeBadge is not enabled.');
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (null !== $this->logger) {
|
||||
$this->logger->debug('Remember-me was requested; setting cookie.');
|
||||
}
|
||||
|
||||
$this->rememberMeHandler->createRememberMeCookie($event->getUser());
|
||||
}
|
||||
|
||||
public function clearCookie(): void
|
||||
{
|
||||
$this->rememberMeHandler->clearRememberMeCookie();
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [
|
||||
LoginSuccessEvent::class => ['onSuccessfulLogin', -64],
|
||||
LoginFailureEvent::class => 'clearCookie',
|
||||
LogoutEvent::class => 'clearCookie',
|
||||
TokenDeauthenticatedEvent::class => 'clearCookie',
|
||||
];
|
||||
}
|
||||
}
|
64
vendor/symfony/security-http/EventListener/RememberMeLogoutListener.php
vendored
Normal file
64
vendor/symfony/security-http/EventListener/RememberMeLogoutListener.php
vendored
Normal file
@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\EventListener;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\Security\Core\Exception\LogicException;
|
||||
use Symfony\Component\Security\Http\Event\LogoutEvent;
|
||||
use Symfony\Component\Security\Http\RememberMe\RememberMeServicesInterface;
|
||||
|
||||
trigger_deprecation('symfony/security-http', '5.4', 'The "%s" class is deprecated.', RememberMeLogoutListener::class);
|
||||
|
||||
/**
|
||||
* @author Wouter de Jong <wouter@wouterj.nl>
|
||||
*
|
||||
* @final
|
||||
*
|
||||
* @deprecated since Symfony 5.4
|
||||
*/
|
||||
class RememberMeLogoutListener implements EventSubscriberInterface
|
||||
{
|
||||
private $rememberMeServices;
|
||||
|
||||
public function __construct(RememberMeServicesInterface $rememberMeServices)
|
||||
{
|
||||
if (!method_exists($rememberMeServices, 'logout')) {
|
||||
trigger_deprecation('symfony/security-core', '5.1', '"%s" should implement the "logout(Request $request, Response $response, TokenInterface $token)" method, this method will be added to the "%s" in version 6.0.', \get_class($rememberMeServices), RememberMeServicesInterface::class);
|
||||
}
|
||||
|
||||
$this->rememberMeServices = $rememberMeServices;
|
||||
}
|
||||
|
||||
public function onLogout(LogoutEvent $event): void
|
||||
{
|
||||
if (!method_exists($this->rememberMeServices, 'logout')) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!$event->getToken()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (null === $event->getResponse()) {
|
||||
throw new LogicException(sprintf('No response was set for this logout action. Make sure the DefaultLogoutListener or another listener has set the response before "%s" is called.', __CLASS__));
|
||||
}
|
||||
|
||||
$this->rememberMeServices->logout($event->getRequest(), $event->getResponse(), $event->getToken());
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [
|
||||
LogoutEvent::class => 'onLogout',
|
||||
];
|
||||
}
|
||||
}
|
39
vendor/symfony/security-http/EventListener/SessionLogoutListener.php
vendored
Normal file
39
vendor/symfony/security-http/EventListener/SessionLogoutListener.php
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\EventListener;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\Security\Http\Event\LogoutEvent;
|
||||
|
||||
/**
|
||||
* Handler for clearing invalidating the current session.
|
||||
*
|
||||
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
class SessionLogoutListener implements EventSubscriberInterface
|
||||
{
|
||||
public function onLogout(LogoutEvent $event): void
|
||||
{
|
||||
if ($event->getRequest()->hasSession()) {
|
||||
$event->getRequest()->getSession()->invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [
|
||||
LogoutEvent::class => 'onLogout',
|
||||
];
|
||||
}
|
||||
}
|
53
vendor/symfony/security-http/EventListener/SessionStrategyListener.php
vendored
Normal file
53
vendor/symfony/security-http/EventListener/SessionStrategyListener.php
vendored
Normal file
@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\EventListener;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\Security\Http\Event\LoginSuccessEvent;
|
||||
use Symfony\Component\Security\Http\Session\SessionAuthenticationStrategy;
|
||||
use Symfony\Component\Security\Http\Session\SessionAuthenticationStrategyInterface;
|
||||
|
||||
/**
|
||||
* Migrates/invalidates the session after successful login.
|
||||
*
|
||||
* This should be registered as subscriber to any "stateful" firewalls.
|
||||
*
|
||||
* @see SessionAuthenticationStrategy
|
||||
*
|
||||
* @author Wouter de Jong <wouter@wouterj.nl>
|
||||
*/
|
||||
class SessionStrategyListener implements EventSubscriberInterface
|
||||
{
|
||||
private $sessionAuthenticationStrategy;
|
||||
|
||||
public function __construct(SessionAuthenticationStrategyInterface $sessionAuthenticationStrategy)
|
||||
{
|
||||
$this->sessionAuthenticationStrategy = $sessionAuthenticationStrategy;
|
||||
}
|
||||
|
||||
public function onSuccessfulLogin(LoginSuccessEvent $event): void
|
||||
{
|
||||
$request = $event->getRequest();
|
||||
$token = $event->getAuthenticatedToken();
|
||||
|
||||
if (!$request->hasSession() || !$request->hasPreviousSession()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->sessionAuthenticationStrategy->onAuthentication($request, $token);
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [LoginSuccessEvent::class => 'onSuccessfulLogin'];
|
||||
}
|
||||
}
|
63
vendor/symfony/security-http/EventListener/UserCheckerListener.php
vendored
Normal file
63
vendor/symfony/security-http/EventListener/UserCheckerListener.php
vendored
Normal file
@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\EventListener;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\Security\Core\Event\AuthenticationSuccessEvent;
|
||||
use Symfony\Component\Security\Core\User\UserCheckerInterface;
|
||||
use Symfony\Component\Security\Core\User\UserInterface;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\PreAuthenticatedUserBadge;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\UserPassportInterface;
|
||||
use Symfony\Component\Security\Http\Event\CheckPassportEvent;
|
||||
|
||||
/**
|
||||
* @author Wouter de Jong <wouter@wouterj.nl>
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
class UserCheckerListener implements EventSubscriberInterface
|
||||
{
|
||||
private $userChecker;
|
||||
|
||||
public function __construct(UserCheckerInterface $userChecker)
|
||||
{
|
||||
$this->userChecker = $userChecker;
|
||||
}
|
||||
|
||||
public function preCheckCredentials(CheckPassportEvent $event): void
|
||||
{
|
||||
$passport = $event->getPassport();
|
||||
if (!$passport instanceof UserPassportInterface || $passport->hasBadge(PreAuthenticatedUserBadge::class)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->userChecker->checkPreAuth($passport->getUser());
|
||||
}
|
||||
|
||||
public function postCheckCredentials(AuthenticationSuccessEvent $event): void
|
||||
{
|
||||
$user = $event->getAuthenticationToken()->getUser();
|
||||
if (!$user instanceof UserInterface) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->userChecker->checkPostAuth($user);
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [
|
||||
CheckPassportEvent::class => ['preCheckCredentials', 256],
|
||||
AuthenticationSuccessEvent::class => ['postCheckCredentials', 256],
|
||||
];
|
||||
}
|
||||
}
|
57
vendor/symfony/security-http/EventListener/UserProviderListener.php
vendored
Normal file
57
vendor/symfony/security-http/EventListener/UserProviderListener.php
vendored
Normal file
@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\EventListener;
|
||||
|
||||
use Symfony\Component\Security\Core\User\UserProviderInterface;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
|
||||
use Symfony\Component\Security\Http\Event\CheckPassportEvent;
|
||||
|
||||
/**
|
||||
* Configures the user provider as user loader, if no user load
|
||||
* has been explicitly set.
|
||||
*
|
||||
* @author Wouter de Jong <wouter@wouterj.nl>
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
class UserProviderListener
|
||||
{
|
||||
private $userProvider;
|
||||
|
||||
public function __construct(UserProviderInterface $userProvider)
|
||||
{
|
||||
$this->userProvider = $userProvider;
|
||||
}
|
||||
|
||||
public function checkPassport(CheckPassportEvent $event): void
|
||||
{
|
||||
$passport = $event->getPassport();
|
||||
if (!$passport->hasBadge(UserBadge::class)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/** @var UserBadge $badge */
|
||||
$badge = $passport->getBadge(UserBadge::class);
|
||||
if (null !== $badge->getUserLoader()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// @deprecated since Symfony 5.3, change to $this->userProvider->loadUserByIdentifier() in 6.0
|
||||
if (method_exists($this->userProvider, 'loadUserByIdentifier')) {
|
||||
$badge->setUserLoader([$this->userProvider, 'loadUserByIdentifier']);
|
||||
} else {
|
||||
trigger_deprecation('symfony/security-http', '5.3', 'Not implementing method "loadUserByIdentifier()" in user provider "%s" is deprecated. This method will replace "loadUserByUsername()" in Symfony 6.0.', get_debug_type($this->userProvider));
|
||||
|
||||
$badge->setUserLoader([$this->userProvider, 'loadUserByUsername']);
|
||||
}
|
||||
}
|
||||
}
|
131
vendor/symfony/security-http/Firewall.php
vendored
Normal file
131
vendor/symfony/security-http/Firewall.php
vendored
Normal file
@ -0,0 +1,131 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\Event\FinishRequestEvent;
|
||||
use Symfony\Component\HttpKernel\Event\RequestEvent;
|
||||
use Symfony\Component\HttpKernel\KernelEvents;
|
||||
use Symfony\Component\Security\Http\Firewall\ExceptionListener;
|
||||
use Symfony\Component\Security\Http\Firewall\FirewallListenerInterface;
|
||||
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
|
||||
|
||||
/**
|
||||
* Firewall uses a FirewallMap to register security listeners for the given
|
||||
* request.
|
||||
*
|
||||
* It allows for different security strategies within the same application
|
||||
* (a Basic authentication for the /api, and a web based authentication for
|
||||
* everything else for instance).
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class Firewall implements EventSubscriberInterface
|
||||
{
|
||||
private $map;
|
||||
private $dispatcher;
|
||||
|
||||
/**
|
||||
* @var \SplObjectStorage<Request, ExceptionListener>
|
||||
*/
|
||||
private $exceptionListeners;
|
||||
|
||||
public function __construct(FirewallMapInterface $map, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$this->map = $map;
|
||||
$this->dispatcher = $dispatcher;
|
||||
$this->exceptionListeners = new \SplObjectStorage();
|
||||
}
|
||||
|
||||
public function onKernelRequest(RequestEvent $event)
|
||||
{
|
||||
if (!$event->isMainRequest()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// register listeners for this firewall
|
||||
$listeners = $this->map->getListeners($event->getRequest());
|
||||
|
||||
$authenticationListeners = $listeners[0];
|
||||
$exceptionListener = $listeners[1];
|
||||
$logoutListener = $listeners[2];
|
||||
|
||||
if (null !== $exceptionListener) {
|
||||
$this->exceptionListeners[$event->getRequest()] = $exceptionListener;
|
||||
$exceptionListener->register($this->dispatcher);
|
||||
}
|
||||
|
||||
// Authentication listeners are pre-sorted by SortFirewallListenersPass
|
||||
$authenticationListeners = function () use ($authenticationListeners, $logoutListener) {
|
||||
if (null !== $logoutListener) {
|
||||
$logoutListenerPriority = $this->getListenerPriority($logoutListener);
|
||||
}
|
||||
|
||||
foreach ($authenticationListeners as $listener) {
|
||||
$listenerPriority = $this->getListenerPriority($listener);
|
||||
|
||||
// Yielding the LogoutListener at the correct position
|
||||
if (null !== $logoutListener && $listenerPriority < $logoutListenerPriority) {
|
||||
yield $logoutListener;
|
||||
$logoutListener = null;
|
||||
}
|
||||
|
||||
yield $listener;
|
||||
}
|
||||
|
||||
// When LogoutListener has the lowest priority of all listeners
|
||||
if (null !== $logoutListener) {
|
||||
yield $logoutListener;
|
||||
}
|
||||
};
|
||||
|
||||
$this->callListeners($event, $authenticationListeners());
|
||||
}
|
||||
|
||||
public function onKernelFinishRequest(FinishRequestEvent $event)
|
||||
{
|
||||
$request = $event->getRequest();
|
||||
|
||||
if (isset($this->exceptionListeners[$request])) {
|
||||
$this->exceptionListeners[$request]->unregister($this->dispatcher);
|
||||
unset($this->exceptionListeners[$request]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return [
|
||||
KernelEvents::REQUEST => ['onKernelRequest', 8],
|
||||
KernelEvents::FINISH_REQUEST => 'onKernelFinishRequest',
|
||||
];
|
||||
}
|
||||
|
||||
protected function callListeners(RequestEvent $event, iterable $listeners)
|
||||
{
|
||||
foreach ($listeners as $listener) {
|
||||
$listener($event);
|
||||
|
||||
if ($event->hasResponse()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function getListenerPriority(object $logoutListener): int
|
||||
{
|
||||
return $logoutListener instanceof FirewallListenerInterface ? $logoutListener->getPriority() : 0;
|
||||
}
|
||||
}
|
229
vendor/symfony/security-http/Firewall/AbstractAuthenticationListener.php
vendored
Normal file
229
vendor/symfony/security-http/Firewall/AbstractAuthenticationListener.php
vendored
Normal file
@ -0,0 +1,229 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\Firewall;
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\Event\RequestEvent;
|
||||
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
|
||||
use Symfony\Component\Security\Core\Exception\AuthenticationException;
|
||||
use Symfony\Component\Security\Core\Exception\SessionUnavailableException;
|
||||
use Symfony\Component\Security\Core\Security;
|
||||
use Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface;
|
||||
use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface;
|
||||
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
|
||||
use Symfony\Component\Security\Http\HttpUtils;
|
||||
use Symfony\Component\Security\Http\RememberMe\RememberMeServicesInterface;
|
||||
use Symfony\Component\Security\Http\SecurityEvents;
|
||||
use Symfony\Component\Security\Http\Session\SessionAuthenticationStrategyInterface;
|
||||
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
|
||||
|
||||
trigger_deprecation('symfony/security-http', '5.3', 'The "%s" class is deprecated, use the new authenticator system instead.', AbstractAuthenticationListener::class);
|
||||
|
||||
/**
|
||||
* The AbstractAuthenticationListener is the preferred base class for all
|
||||
* browser-/HTTP-based authentication requests.
|
||||
*
|
||||
* Subclasses likely have to implement the following:
|
||||
* - an TokenInterface to hold authentication related data
|
||||
* - an AuthenticationProvider to perform the actual authentication of the
|
||||
* token, retrieve the UserInterface implementation from a database, and
|
||||
* perform the specific account checks using the UserChecker
|
||||
*
|
||||
* By default, this listener only is active for a specific path, e.g.
|
||||
* /login_check. If you want to change this behavior, you can overwrite the
|
||||
* requiresAuthentication() method.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
|
||||
*
|
||||
* @deprecated since Symfony 5.3, use the new authenticator system instead
|
||||
*/
|
||||
abstract class AbstractAuthenticationListener extends AbstractListener
|
||||
{
|
||||
protected $options;
|
||||
protected $logger;
|
||||
protected $authenticationManager;
|
||||
protected $providerKey;
|
||||
protected $httpUtils;
|
||||
|
||||
private $tokenStorage;
|
||||
private $sessionStrategy;
|
||||
private $dispatcher;
|
||||
private $successHandler;
|
||||
private $failureHandler;
|
||||
private $rememberMeServices;
|
||||
|
||||
/**
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function __construct(TokenStorageInterface $tokenStorage, AuthenticationManagerInterface $authenticationManager, SessionAuthenticationStrategyInterface $sessionStrategy, HttpUtils $httpUtils, string $providerKey, AuthenticationSuccessHandlerInterface $successHandler, AuthenticationFailureHandlerInterface $failureHandler, array $options = [], LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null)
|
||||
{
|
||||
if (empty($providerKey)) {
|
||||
throw new \InvalidArgumentException('$providerKey must not be empty.');
|
||||
}
|
||||
|
||||
$this->tokenStorage = $tokenStorage;
|
||||
$this->authenticationManager = $authenticationManager;
|
||||
$this->sessionStrategy = $sessionStrategy;
|
||||
$this->providerKey = $providerKey;
|
||||
$this->successHandler = $successHandler;
|
||||
$this->failureHandler = $failureHandler;
|
||||
$this->options = array_merge([
|
||||
'check_path' => '/login_check',
|
||||
'login_path' => '/login',
|
||||
'always_use_default_target_path' => false,
|
||||
'default_target_path' => '/',
|
||||
'target_path_parameter' => '_target_path',
|
||||
'use_referer' => false,
|
||||
'failure_path' => null,
|
||||
'failure_forward' => false,
|
||||
'require_previous_session' => true,
|
||||
], $options);
|
||||
$this->logger = $logger;
|
||||
$this->dispatcher = $dispatcher;
|
||||
$this->httpUtils = $httpUtils;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the RememberMeServices implementation to use.
|
||||
*/
|
||||
public function setRememberMeServices(RememberMeServicesInterface $rememberMeServices)
|
||||
{
|
||||
$this->rememberMeServices = $rememberMeServices;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function supports(Request $request): ?bool
|
||||
{
|
||||
return $this->requiresAuthentication($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles form based authentication.
|
||||
*
|
||||
* @throws \RuntimeException
|
||||
* @throws SessionUnavailableException
|
||||
*/
|
||||
public function authenticate(RequestEvent $event)
|
||||
{
|
||||
$request = $event->getRequest();
|
||||
|
||||
if (!$request->hasSession()) {
|
||||
throw new \RuntimeException('This authentication method requires a session.');
|
||||
}
|
||||
|
||||
try {
|
||||
if ($this->options['require_previous_session'] && !$request->hasPreviousSession()) {
|
||||
throw new SessionUnavailableException('Your session has timed out, or you have disabled cookies.');
|
||||
}
|
||||
|
||||
if (null === $returnValue = $this->attemptAuthentication($request)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($returnValue instanceof TokenInterface) {
|
||||
$this->sessionStrategy->onAuthentication($request, $returnValue);
|
||||
|
||||
$response = $this->onSuccess($request, $returnValue);
|
||||
} elseif ($returnValue instanceof Response) {
|
||||
$response = $returnValue;
|
||||
} else {
|
||||
throw new \RuntimeException('attemptAuthentication() must either return a Response, an implementation of TokenInterface, or null.');
|
||||
}
|
||||
} catch (AuthenticationException $e) {
|
||||
$response = $this->onFailure($request, $e);
|
||||
}
|
||||
|
||||
$event->setResponse($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this request requires authentication.
|
||||
*
|
||||
* The default implementation only processes requests to a specific path,
|
||||
* but a subclass could change this to only authenticate requests where a
|
||||
* certain parameters is present.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function requiresAuthentication(Request $request)
|
||||
{
|
||||
return $this->httpUtils->checkRequestPath($request, $this->options['check_path']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs authentication.
|
||||
*
|
||||
* @return TokenInterface|Response|null The authenticated token, null if full authentication is not possible, or a Response
|
||||
*
|
||||
* @throws AuthenticationException if the authentication fails
|
||||
*/
|
||||
abstract protected function attemptAuthentication(Request $request);
|
||||
|
||||
private function onFailure(Request $request, AuthenticationException $failed): Response
|
||||
{
|
||||
if (null !== $this->logger) {
|
||||
$this->logger->info('Authentication request failed.', ['exception' => $failed]);
|
||||
}
|
||||
|
||||
$token = $this->tokenStorage->getToken();
|
||||
if ($token instanceof UsernamePasswordToken && $this->providerKey === $token->getFirewallName()) {
|
||||
$this->tokenStorage->setToken(null);
|
||||
}
|
||||
|
||||
$response = $this->failureHandler->onAuthenticationFailure($request, $failed);
|
||||
|
||||
if (!$response instanceof Response) {
|
||||
throw new \RuntimeException('Authentication Failure Handler did not return a Response.');
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
private function onSuccess(Request $request, TokenInterface $token): Response
|
||||
{
|
||||
if (null !== $this->logger) {
|
||||
// @deprecated since Symfony 5.3, change to $token->getUserIdentifier() in 6.0
|
||||
$this->logger->info('User has been authenticated successfully.', ['username' => method_exists($token, 'getUserIdentifier') ? $token->getUserIdentifier() : $token->getUsername()]);
|
||||
}
|
||||
|
||||
$this->tokenStorage->setToken($token);
|
||||
|
||||
$session = $request->getSession();
|
||||
$session->remove(Security::AUTHENTICATION_ERROR);
|
||||
$session->remove(Security::LAST_USERNAME);
|
||||
|
||||
if (null !== $this->dispatcher) {
|
||||
$loginEvent = new InteractiveLoginEvent($request, $token);
|
||||
$this->dispatcher->dispatch($loginEvent, SecurityEvents::INTERACTIVE_LOGIN);
|
||||
}
|
||||
|
||||
$response = $this->successHandler->onAuthenticationSuccess($request, $token);
|
||||
|
||||
if (!$response instanceof Response) {
|
||||
throw new \RuntimeException('Authentication Success Handler did not return a Response.');
|
||||
}
|
||||
|
||||
if (null !== $this->rememberMeServices) {
|
||||
$this->rememberMeServices->loginSuccess($request, $response, $token);
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
}
|
34
vendor/symfony/security-http/Firewall/AbstractListener.php
vendored
Normal file
34
vendor/symfony/security-http/Firewall/AbstractListener.php
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\Firewall;
|
||||
|
||||
use Symfony\Component\HttpKernel\Event\RequestEvent;
|
||||
|
||||
/**
|
||||
* A base class for listeners that can tell whether they should authenticate incoming requests.
|
||||
*
|
||||
* @author Nicolas Grekas <p@tchwork.com>
|
||||
*/
|
||||
abstract class AbstractListener implements FirewallListenerInterface
|
||||
{
|
||||
final public function __invoke(RequestEvent $event)
|
||||
{
|
||||
if (false !== $this->supports($event->getRequest())) {
|
||||
$this->authenticate($event);
|
||||
}
|
||||
}
|
||||
|
||||
public static function getPriority(): int
|
||||
{
|
||||
return 0; // Default
|
||||
}
|
||||
}
|
160
vendor/symfony/security-http/Firewall/AbstractPreAuthenticatedListener.php
vendored
Normal file
160
vendor/symfony/security-http/Firewall/AbstractPreAuthenticatedListener.php
vendored
Normal file
@ -0,0 +1,160 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\Firewall;
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\Event\RequestEvent;
|
||||
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\PreAuthenticatedToken;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||
use Symfony\Component\Security\Core\Exception\AuthenticationException;
|
||||
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
|
||||
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
|
||||
use Symfony\Component\Security\Http\SecurityEvents;
|
||||
use Symfony\Component\Security\Http\Session\SessionAuthenticationStrategyInterface;
|
||||
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
|
||||
|
||||
trigger_deprecation('symfony/security-http', '5.3', 'The "%s" class is deprecated, use the new authenticator system instead.', AbstractPreAuthenticatedListener::class);
|
||||
|
||||
/**
|
||||
* AbstractPreAuthenticatedListener is the base class for all listener that
|
||||
* authenticates users based on a pre-authenticated request (like a certificate
|
||||
* for instance).
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @internal
|
||||
*
|
||||
* @deprecated since Symfony 5.3, use the new authenticator system instead
|
||||
*/
|
||||
abstract class AbstractPreAuthenticatedListener extends AbstractListener
|
||||
{
|
||||
protected $logger;
|
||||
private $tokenStorage;
|
||||
private $authenticationManager;
|
||||
private $providerKey;
|
||||
private $dispatcher;
|
||||
private $sessionStrategy;
|
||||
|
||||
public function __construct(TokenStorageInterface $tokenStorage, AuthenticationManagerInterface $authenticationManager, string $providerKey, LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null)
|
||||
{
|
||||
$this->tokenStorage = $tokenStorage;
|
||||
$this->authenticationManager = $authenticationManager;
|
||||
$this->providerKey = $providerKey;
|
||||
$this->logger = $logger;
|
||||
$this->dispatcher = $dispatcher;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function supports(Request $request): ?bool
|
||||
{
|
||||
try {
|
||||
$request->attributes->set('_pre_authenticated_data', $this->getPreAuthenticatedData($request));
|
||||
} catch (BadCredentialsException $e) {
|
||||
$this->clearToken($e);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles pre-authentication.
|
||||
*/
|
||||
public function authenticate(RequestEvent $event)
|
||||
{
|
||||
$request = $event->getRequest();
|
||||
|
||||
[$user, $credentials] = $request->attributes->get('_pre_authenticated_data');
|
||||
$request->attributes->remove('_pre_authenticated_data');
|
||||
|
||||
if (null !== $this->logger) {
|
||||
$this->logger->debug('Checking current security token.', ['token' => (string) $this->tokenStorage->getToken()]);
|
||||
}
|
||||
|
||||
if (null !== $token = $this->tokenStorage->getToken()) {
|
||||
// @deprecated since Symfony 5.3, change to $token->getUserIdentifier() in 6.0
|
||||
if ($token instanceof PreAuthenticatedToken && $this->providerKey == $token->getFirewallName() && $token->isAuthenticated() && (method_exists($token, 'getUserIdentifier') ? $token->getUserIdentifier() : $token->getUsername()) === $user) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (null !== $this->logger) {
|
||||
$this->logger->debug('Trying to pre-authenticate user.', ['username' => (string) $user]);
|
||||
}
|
||||
|
||||
try {
|
||||
$token = $this->authenticationManager->authenticate(new PreAuthenticatedToken($user, $credentials, $this->providerKey));
|
||||
|
||||
if (null !== $this->logger) {
|
||||
$this->logger->info('Pre-authentication successful.', ['token' => (string) $token]);
|
||||
}
|
||||
|
||||
$this->migrateSession($request, $token);
|
||||
|
||||
$this->tokenStorage->setToken($token);
|
||||
|
||||
if (null !== $this->dispatcher) {
|
||||
$loginEvent = new InteractiveLoginEvent($request, $token);
|
||||
$this->dispatcher->dispatch($loginEvent, SecurityEvents::INTERACTIVE_LOGIN);
|
||||
}
|
||||
} catch (AuthenticationException $e) {
|
||||
$this->clearToken($e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Call this method if your authentication token is stored to a session.
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
public function setSessionAuthenticationStrategy(SessionAuthenticationStrategyInterface $sessionStrategy)
|
||||
{
|
||||
$this->sessionStrategy = $sessionStrategy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears a PreAuthenticatedToken for this provider (if present).
|
||||
*/
|
||||
private function clearToken(AuthenticationException $exception)
|
||||
{
|
||||
$token = $this->tokenStorage->getToken();
|
||||
if ($token instanceof PreAuthenticatedToken && $this->providerKey === $token->getFirewallName()) {
|
||||
$this->tokenStorage->setToken(null);
|
||||
|
||||
if (null !== $this->logger) {
|
||||
$this->logger->info('Cleared security token due to an exception.', ['exception' => $exception]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the user and credentials from the Request.
|
||||
*
|
||||
* @return array An array composed of the user and the credentials
|
||||
*/
|
||||
abstract protected function getPreAuthenticatedData(Request $request);
|
||||
|
||||
private function migrateSession(Request $request, TokenInterface $token)
|
||||
{
|
||||
if (!$this->sessionStrategy || !$request->hasSession() || !$request->hasPreviousSession()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->sessionStrategy->onAuthentication($request, $token);
|
||||
}
|
||||
}
|
143
vendor/symfony/security-http/Firewall/AccessListener.php
vendored
Normal file
143
vendor/symfony/security-http/Firewall/AccessListener.php
vendored
Normal file
@ -0,0 +1,143 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\Firewall;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\Event\RequestEvent;
|
||||
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\NullToken;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
|
||||
use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface;
|
||||
use Symfony\Component\Security\Core\Authorization\Voter\AuthenticatedVoter;
|
||||
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
|
||||
use Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException;
|
||||
use Symfony\Component\Security\Http\AccessMapInterface;
|
||||
use Symfony\Component\Security\Http\Authentication\NoopAuthenticationManager;
|
||||
use Symfony\Component\Security\Http\Event\LazyResponseEvent;
|
||||
|
||||
/**
|
||||
* AccessListener enforces access control rules.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
class AccessListener extends AbstractListener
|
||||
{
|
||||
private $tokenStorage;
|
||||
private $accessDecisionManager;
|
||||
private $map;
|
||||
private $authManager;
|
||||
private $exceptionOnNoToken;
|
||||
|
||||
public function __construct(TokenStorageInterface $tokenStorage, AccessDecisionManagerInterface $accessDecisionManager, AccessMapInterface $map, /*bool*/ $exceptionOnNoToken = true)
|
||||
{
|
||||
if ($exceptionOnNoToken instanceof AuthenticationManagerInterface) {
|
||||
trigger_deprecation('symfony/security-http', '5.4', 'The $authManager argument of "%s" is deprecated.', __METHOD__);
|
||||
$authManager = $exceptionOnNoToken;
|
||||
$exceptionOnNoToken = \func_num_args() > 4 ? func_get_arg(4) : true;
|
||||
}
|
||||
|
||||
if (false !== $exceptionOnNoToken) {
|
||||
trigger_deprecation('symfony/security-http', '5.4', 'Not setting the $exceptionOnNoToken argument of "%s" to "false" is deprecated.', __METHOD__);
|
||||
}
|
||||
|
||||
$this->tokenStorage = $tokenStorage;
|
||||
$this->accessDecisionManager = $accessDecisionManager;
|
||||
$this->map = $map;
|
||||
$this->authManager = $authManager ?? (class_exists(AuthenticationManagerInterface::class) ? new NoopAuthenticationManager() : null);
|
||||
$this->exceptionOnNoToken = $exceptionOnNoToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function supports(Request $request): ?bool
|
||||
{
|
||||
[$attributes] = $this->map->getPatterns($request);
|
||||
$request->attributes->set('_access_control_attributes', $attributes);
|
||||
|
||||
if ($attributes && (
|
||||
(\defined(AuthenticatedVoter::class.'::IS_AUTHENTICATED_ANONYMOUSLY') ? [AuthenticatedVoter::IS_AUTHENTICATED_ANONYMOUSLY] !== $attributes : true)
|
||||
&& [AuthenticatedVoter::PUBLIC_ACCESS] !== $attributes
|
||||
)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles access authorization.
|
||||
*
|
||||
* @throws AccessDeniedException
|
||||
* @throws AuthenticationCredentialsNotFoundException when the token storage has no authentication token and $exceptionOnNoToken is set to true
|
||||
*/
|
||||
public function authenticate(RequestEvent $event)
|
||||
{
|
||||
if (!$event instanceof LazyResponseEvent && null === ($token = $this->tokenStorage->getToken()) && $this->exceptionOnNoToken) {
|
||||
throw new AuthenticationCredentialsNotFoundException('A Token was not found in the TokenStorage.');
|
||||
}
|
||||
|
||||
$request = $event->getRequest();
|
||||
|
||||
$attributes = $request->attributes->get('_access_control_attributes');
|
||||
$request->attributes->remove('_access_control_attributes');
|
||||
|
||||
if (!$attributes || ((
|
||||
(\defined(AuthenticatedVoter::class.'::IS_AUTHENTICATED_ANONYMOUSLY') ? [AuthenticatedVoter::IS_AUTHENTICATED_ANONYMOUSLY] === $attributes : false)
|
||||
|| [AuthenticatedVoter::PUBLIC_ACCESS] === $attributes
|
||||
) && $event instanceof LazyResponseEvent)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($event instanceof LazyResponseEvent) {
|
||||
$token = $this->tokenStorage->getToken();
|
||||
}
|
||||
|
||||
if (null === $token) {
|
||||
if ($this->exceptionOnNoToken) {
|
||||
throw new AuthenticationCredentialsNotFoundException('A Token was not found in the TokenStorage.');
|
||||
}
|
||||
|
||||
$token = new NullToken();
|
||||
}
|
||||
|
||||
// @deprecated since Symfony 5.4
|
||||
if (method_exists($token, 'isAuthenticated') && !$token->isAuthenticated(false)) {
|
||||
trigger_deprecation('symfony/core', '5.4', 'Returning false from "%s()" is deprecated, return null from "getUser()" instead.');
|
||||
|
||||
if ($this->authManager) {
|
||||
$token = $this->authManager->authenticate($token);
|
||||
$this->tokenStorage->setToken($token);
|
||||
}
|
||||
}
|
||||
|
||||
if (!$this->accessDecisionManager->decide($token, $attributes, $request, true)) {
|
||||
throw $this->createAccessDeniedException($request, $attributes);
|
||||
}
|
||||
}
|
||||
|
||||
private function createAccessDeniedException(Request $request, array $attributes)
|
||||
{
|
||||
$exception = new AccessDeniedException();
|
||||
$exception->setAttributes($attributes);
|
||||
$exception->setSubject($request);
|
||||
|
||||
return $exception;
|
||||
}
|
||||
|
||||
public static function getPriority(): int
|
||||
{
|
||||
return -255;
|
||||
}
|
||||
}
|
84
vendor/symfony/security-http/Firewall/AnonymousAuthenticationListener.php
vendored
Normal file
84
vendor/symfony/security-http/Firewall/AnonymousAuthenticationListener.php
vendored
Normal file
@ -0,0 +1,84 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\Firewall;
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\Event\RequestEvent;
|
||||
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
|
||||
use Symfony\Component\Security\Core\Exception\AuthenticationException;
|
||||
|
||||
trigger_deprecation('symfony/security-http', '5.3', 'The "%s" class is deprecated, use the new authenticator system instead.', AnonymousAuthenticationListener::class);
|
||||
|
||||
// Help opcache.preload discover always-needed symbols
|
||||
class_exists(AnonymousToken::class);
|
||||
|
||||
/**
|
||||
* AnonymousAuthenticationListener automatically adds a Token if none is
|
||||
* already present.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @deprecated since Symfony 5.3, use the new authenticator system instead
|
||||
*/
|
||||
class AnonymousAuthenticationListener extends AbstractListener
|
||||
{
|
||||
private $tokenStorage;
|
||||
private $secret;
|
||||
private $authenticationManager;
|
||||
private $logger;
|
||||
|
||||
public function __construct(TokenStorageInterface $tokenStorage, string $secret, LoggerInterface $logger = null, AuthenticationManagerInterface $authenticationManager = null)
|
||||
{
|
||||
$this->tokenStorage = $tokenStorage;
|
||||
$this->secret = $secret;
|
||||
$this->authenticationManager = $authenticationManager;
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function supports(Request $request): ?bool
|
||||
{
|
||||
return null; // always run authenticate() lazily with lazy firewalls
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles anonymous authentication.
|
||||
*/
|
||||
public function authenticate(RequestEvent $event)
|
||||
{
|
||||
if (null !== $this->tokenStorage->getToken()) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
$token = new AnonymousToken($this->secret, 'anon.', []);
|
||||
if (null !== $this->authenticationManager) {
|
||||
$token = $this->authenticationManager->authenticate($token);
|
||||
}
|
||||
|
||||
$this->tokenStorage->setToken($token);
|
||||
|
||||
if (null !== $this->logger) {
|
||||
$this->logger->info('Populated the TokenStorage with an anonymous Token.');
|
||||
}
|
||||
} catch (AuthenticationException $failed) {
|
||||
if (null !== $this->logger) {
|
||||
$this->logger->info('Anonymous authentication failed.', ['exception' => $failed]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
47
vendor/symfony/security-http/Firewall/AuthenticatorManagerListener.php
vendored
Normal file
47
vendor/symfony/security-http/Firewall/AuthenticatorManagerListener.php
vendored
Normal file
@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\Firewall;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\Event\RequestEvent;
|
||||
use Symfony\Component\Security\Http\Authentication\AuthenticatorManagerInterface;
|
||||
|
||||
/**
|
||||
* Firewall authentication listener that delegates to the authenticator system.
|
||||
*
|
||||
* @author Wouter de Jong <wouter@wouterj.nl>
|
||||
*/
|
||||
class AuthenticatorManagerListener extends AbstractListener
|
||||
{
|
||||
private $authenticatorManager;
|
||||
|
||||
public function __construct(AuthenticatorManagerInterface $authenticationManager)
|
||||
{
|
||||
$this->authenticatorManager = $authenticationManager;
|
||||
}
|
||||
|
||||
public function supports(Request $request): ?bool
|
||||
{
|
||||
return $this->authenticatorManager->supports($request);
|
||||
}
|
||||
|
||||
public function authenticate(RequestEvent $event): void
|
||||
{
|
||||
$request = $event->getRequest();
|
||||
$response = $this->authenticatorManager->authenticateRequest($request);
|
||||
if (null === $response) {
|
||||
return;
|
||||
}
|
||||
|
||||
$event->setResponse($response);
|
||||
}
|
||||
}
|
132
vendor/symfony/security-http/Firewall/BasicAuthenticationListener.php
vendored
Normal file
132
vendor/symfony/security-http/Firewall/BasicAuthenticationListener.php
vendored
Normal file
@ -0,0 +1,132 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\Firewall;
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\Event\RequestEvent;
|
||||
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
|
||||
use Symfony\Component\Security\Core\Exception\AuthenticationException;
|
||||
use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface;
|
||||
use Symfony\Component\Security\Http\Session\SessionAuthenticationStrategyInterface;
|
||||
|
||||
trigger_deprecation('symfony/security-http', '5.3', 'The "%s" class is deprecated, use the new authenticator system instead.', AnonymousAuthenticationListener::class);
|
||||
|
||||
/**
|
||||
* BasicAuthenticationListener implements Basic HTTP authentication.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @final
|
||||
*
|
||||
* @deprecated since Symfony 5.3, use the new authenticator system instead
|
||||
*/
|
||||
class BasicAuthenticationListener extends AbstractListener
|
||||
{
|
||||
private $tokenStorage;
|
||||
private $authenticationManager;
|
||||
private $providerKey;
|
||||
private $authenticationEntryPoint;
|
||||
private $logger;
|
||||
private $ignoreFailure;
|
||||
private $sessionStrategy;
|
||||
|
||||
public function __construct(TokenStorageInterface $tokenStorage, AuthenticationManagerInterface $authenticationManager, string $providerKey, AuthenticationEntryPointInterface $authenticationEntryPoint, LoggerInterface $logger = null)
|
||||
{
|
||||
if (empty($providerKey)) {
|
||||
throw new \InvalidArgumentException('$providerKey must not be empty.');
|
||||
}
|
||||
|
||||
$this->tokenStorage = $tokenStorage;
|
||||
$this->authenticationManager = $authenticationManager;
|
||||
$this->providerKey = $providerKey;
|
||||
$this->authenticationEntryPoint = $authenticationEntryPoint;
|
||||
$this->logger = $logger;
|
||||
$this->ignoreFailure = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function supports(Request $request): ?bool
|
||||
{
|
||||
return null !== $request->headers->get('PHP_AUTH_USER');
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles basic authentication.
|
||||
*/
|
||||
public function authenticate(RequestEvent $event)
|
||||
{
|
||||
$request = $event->getRequest();
|
||||
|
||||
if (null === $username = $request->headers->get('PHP_AUTH_USER')) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (null !== $token = $this->tokenStorage->getToken()) {
|
||||
// @deprecated since Symfony 5.3, change to $token->getUserIdentifier() in 6.0
|
||||
if ($token instanceof UsernamePasswordToken && $token->isAuthenticated(false) && (method_exists($token, 'getUserIdentifier') ? $token->getUserIdentifier() : $token->getUsername()) === $username) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (null !== $this->logger) {
|
||||
$this->logger->info('Basic authentication Authorization header found for user.', ['username' => $username]);
|
||||
}
|
||||
|
||||
try {
|
||||
$token = $this->authenticationManager->authenticate(new UsernamePasswordToken($username, $request->headers->get('PHP_AUTH_PW'), $this->providerKey));
|
||||
|
||||
$this->migrateSession($request, $token);
|
||||
|
||||
$this->tokenStorage->setToken($token);
|
||||
} catch (AuthenticationException $e) {
|
||||
$token = $this->tokenStorage->getToken();
|
||||
if ($token instanceof UsernamePasswordToken && $this->providerKey === $token->getFirewallName()) {
|
||||
$this->tokenStorage->setToken(null);
|
||||
}
|
||||
|
||||
if (null !== $this->logger) {
|
||||
$this->logger->info('Basic authentication failed for user.', ['username' => $username, 'exception' => $e]);
|
||||
}
|
||||
|
||||
if ($this->ignoreFailure) {
|
||||
return;
|
||||
}
|
||||
|
||||
$event->setResponse($this->authenticationEntryPoint->start($request, $e));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Call this method if your authentication token is stored to a session.
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
public function setSessionAuthenticationStrategy(SessionAuthenticationStrategyInterface $sessionStrategy)
|
||||
{
|
||||
$this->sessionStrategy = $sessionStrategy;
|
||||
}
|
||||
|
||||
private function migrateSession(Request $request, TokenInterface $token)
|
||||
{
|
||||
if (!$this->sessionStrategy || !$request->hasSession() || !$request->hasPreviousSession()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->sessionStrategy->onAuthentication($request, $token);
|
||||
}
|
||||
}
|
122
vendor/symfony/security-http/Firewall/ChannelListener.php
vendored
Normal file
122
vendor/symfony/security-http/Firewall/ChannelListener.php
vendored
Normal file
@ -0,0 +1,122 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\Firewall;
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\Event\RequestEvent;
|
||||
use Symfony\Component\Security\Http\AccessMapInterface;
|
||||
use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface;
|
||||
|
||||
/**
|
||||
* ChannelListener switches the HTTP protocol based on the access control
|
||||
* configuration.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
class ChannelListener extends AbstractListener
|
||||
{
|
||||
private $map;
|
||||
private $authenticationEntryPoint = null;
|
||||
private $logger;
|
||||
private $httpPort;
|
||||
private $httpsPort;
|
||||
|
||||
public function __construct(AccessMapInterface $map, /*LoggerInterface*/ $logger = null, /*int*/ $httpPort = 80, /*int*/ $httpsPort = 443)
|
||||
{
|
||||
if ($logger instanceof AuthenticationEntryPointInterface) {
|
||||
trigger_deprecation('symfony/security-http', '5.4', 'The "$authenticationEntryPoint" argument of "%s()" is deprecated.', __METHOD__);
|
||||
|
||||
$this->authenticationEntryPoint = $logger;
|
||||
$nrOfArgs = \func_num_args();
|
||||
$logger = $nrOfArgs > 2 ? func_get_arg(2) : null;
|
||||
$httpPort = $nrOfArgs > 3 ? func_get_arg(3) : 80;
|
||||
$httpsPort = $nrOfArgs > 4 ? func_get_arg(4) : 443;
|
||||
}
|
||||
|
||||
if (null !== $logger && !$logger instanceof LoggerInterface) {
|
||||
throw new \TypeError(sprintf('Argument "$logger" of "%s()" must be instance of "%s", "%s" given.', __METHOD__, LoggerInterface::class, get_debug_type($logger)));
|
||||
}
|
||||
|
||||
$this->map = $map;
|
||||
$this->logger = $logger;
|
||||
$this->httpPort = $httpPort;
|
||||
$this->httpsPort = $httpsPort;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles channel management.
|
||||
*/
|
||||
public function supports(Request $request): ?bool
|
||||
{
|
||||
[, $channel] = $this->map->getPatterns($request);
|
||||
|
||||
if ('https' === $channel && !$request->isSecure()) {
|
||||
if (null !== $this->logger) {
|
||||
if ('https' === $request->headers->get('X-Forwarded-Proto')) {
|
||||
$this->logger->info('Redirecting to HTTPS. ("X-Forwarded-Proto" header is set to "https" - did you set "trusted_proxies" correctly?)');
|
||||
} elseif (str_contains($request->headers->get('Forwarded', ''), 'proto=https')) {
|
||||
$this->logger->info('Redirecting to HTTPS. ("Forwarded" header is set to "proto=https" - did you set "trusted_proxies" correctly?)');
|
||||
} else {
|
||||
$this->logger->info('Redirecting to HTTPS.');
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if ('http' === $channel && $request->isSecure()) {
|
||||
if (null !== $this->logger) {
|
||||
$this->logger->info('Redirecting to HTTP.');
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function authenticate(RequestEvent $event)
|
||||
{
|
||||
$request = $event->getRequest();
|
||||
|
||||
$event->setResponse($this->createRedirectResponse($request));
|
||||
}
|
||||
|
||||
private function createRedirectResponse(Request $request): RedirectResponse
|
||||
{
|
||||
if (null !== $this->authenticationEntryPoint) {
|
||||
return $this->authenticationEntryPoint->start($request);
|
||||
}
|
||||
|
||||
$scheme = $request->isSecure() ? 'http' : 'https';
|
||||
if ('http' === $scheme && 80 != $this->httpPort) {
|
||||
$port = ':'.$this->httpPort;
|
||||
} elseif ('https' === $scheme && 443 != $this->httpsPort) {
|
||||
$port = ':'.$this->httpsPort;
|
||||
} else {
|
||||
$port = '';
|
||||
}
|
||||
|
||||
$qs = $request->getQueryString();
|
||||
if (null !== $qs) {
|
||||
$qs = '?'.$qs;
|
||||
}
|
||||
|
||||
$url = $scheme.'://'.$request->getHost().$port.$request->getBaseUrl().$request->getPathInfo().$qs;
|
||||
|
||||
return new RedirectResponse($url, 301);
|
||||
}
|
||||
}
|
402
vendor/symfony/security-http/Firewall/ContextListener.php
vendored
Normal file
402
vendor/symfony/security-http/Firewall/ContextListener.php
vendored
Normal file
@ -0,0 +1,402 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\Firewall;
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\EventDispatcher\Event;
|
||||
use Symfony\Component\EventDispatcher\LegacyEventDispatcherProxy;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Session\Session;
|
||||
use Symfony\Component\HttpKernel\Event\RequestEvent;
|
||||
use Symfony\Component\HttpKernel\Event\ResponseEvent;
|
||||
use Symfony\Component\HttpKernel\KernelEvents;
|
||||
use Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolver;
|
||||
use Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolverInterface;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\AbstractToken;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\RememberMeToken;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\SwitchUserToken;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
|
||||
use Symfony\Component\Security\Core\Exception\UserNotFoundException;
|
||||
use Symfony\Component\Security\Core\User\EquatableInterface;
|
||||
use Symfony\Component\Security\Core\User\UserInterface;
|
||||
use Symfony\Component\Security\Core\User\UserProviderInterface;
|
||||
use Symfony\Component\Security\Http\Event\DeauthenticatedEvent;
|
||||
use Symfony\Component\Security\Http\Event\TokenDeauthenticatedEvent;
|
||||
use Symfony\Component\Security\Http\RememberMe\RememberMeServicesInterface;
|
||||
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
|
||||
|
||||
/**
|
||||
* ContextListener manages the SecurityContext persistence through a session.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
class ContextListener extends AbstractListener
|
||||
{
|
||||
private $tokenStorage;
|
||||
private $sessionKey;
|
||||
private $logger;
|
||||
private $userProviders;
|
||||
private $dispatcher;
|
||||
private $registered;
|
||||
private $trustResolver;
|
||||
private $rememberMeServices;
|
||||
private $sessionTrackerEnabler;
|
||||
|
||||
/**
|
||||
* @param iterable<mixed, UserProviderInterface> $userProviders
|
||||
*/
|
||||
public function __construct(TokenStorageInterface $tokenStorage, iterable $userProviders, string $contextKey, LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null, AuthenticationTrustResolverInterface $trustResolver = null, callable $sessionTrackerEnabler = null)
|
||||
{
|
||||
if (empty($contextKey)) {
|
||||
throw new \InvalidArgumentException('$contextKey must not be empty.');
|
||||
}
|
||||
|
||||
$this->tokenStorage = $tokenStorage;
|
||||
$this->userProviders = $userProviders;
|
||||
$this->sessionKey = '_security_'.$contextKey;
|
||||
$this->logger = $logger;
|
||||
$this->dispatcher = class_exists(Event::class) ? LegacyEventDispatcherProxy::decorate($dispatcher) : $dispatcher;
|
||||
|
||||
$this->trustResolver = $trustResolver ?? new AuthenticationTrustResolver(AnonymousToken::class, RememberMeToken::class);
|
||||
$this->sessionTrackerEnabler = $sessionTrackerEnabler;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function supports(Request $request): ?bool
|
||||
{
|
||||
return null; // always run authenticate() lazily with lazy firewalls
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the Security Token from the session.
|
||||
*/
|
||||
public function authenticate(RequestEvent $event)
|
||||
{
|
||||
if (!$this->registered && null !== $this->dispatcher && $event->isMainRequest()) {
|
||||
$this->dispatcher->addListener(KernelEvents::RESPONSE, [$this, 'onKernelResponse']);
|
||||
$this->registered = true;
|
||||
}
|
||||
|
||||
$request = $event->getRequest();
|
||||
$session = $request->hasPreviousSession() && $request->hasSession() ? $request->getSession() : null;
|
||||
|
||||
$request->attributes->set('_security_firewall_run', $this->sessionKey);
|
||||
|
||||
if (null !== $session) {
|
||||
$usageIndexValue = $session instanceof Session ? $usageIndexReference = &$session->getUsageIndex() : 0;
|
||||
$usageIndexReference = \PHP_INT_MIN;
|
||||
$sessionId = $request->cookies->all()[$session->getName()] ?? null;
|
||||
$token = $session->get($this->sessionKey);
|
||||
|
||||
// sessionId = true is used in the tests
|
||||
if ($this->sessionTrackerEnabler && \in_array($sessionId, [true, $session->getId()], true)) {
|
||||
$usageIndexReference = $usageIndexValue;
|
||||
} else {
|
||||
$usageIndexReference = $usageIndexReference - \PHP_INT_MIN + $usageIndexValue;
|
||||
}
|
||||
}
|
||||
|
||||
if (null === $session || null === $token) {
|
||||
if ($this->sessionTrackerEnabler) {
|
||||
($this->sessionTrackerEnabler)();
|
||||
}
|
||||
|
||||
$this->tokenStorage->setToken(null);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$token = $this->safelyUnserialize($token);
|
||||
|
||||
if (null !== $this->logger) {
|
||||
$this->logger->debug('Read existing security token from the session.', [
|
||||
'key' => $this->sessionKey,
|
||||
'token_class' => \is_object($token) ? \get_class($token) : null,
|
||||
]);
|
||||
}
|
||||
|
||||
if ($token instanceof TokenInterface) {
|
||||
$originalToken = $token;
|
||||
$token = $this->refreshUser($token);
|
||||
|
||||
if (!$token) {
|
||||
if ($this->logger) {
|
||||
$this->logger->debug('Token was deauthenticated after trying to refresh it.');
|
||||
}
|
||||
|
||||
if ($this->dispatcher) {
|
||||
$this->dispatcher->dispatch(new TokenDeauthenticatedEvent($originalToken, $request));
|
||||
}
|
||||
|
||||
if ($this->rememberMeServices) {
|
||||
$this->rememberMeServices->loginFail($request);
|
||||
}
|
||||
}
|
||||
} elseif (null !== $token) {
|
||||
if (null !== $this->logger) {
|
||||
$this->logger->warning('Expected a security token from the session, got something else.', ['key' => $this->sessionKey, 'received' => $token]);
|
||||
}
|
||||
|
||||
$token = null;
|
||||
}
|
||||
|
||||
if ($this->sessionTrackerEnabler) {
|
||||
($this->sessionTrackerEnabler)();
|
||||
}
|
||||
|
||||
$this->tokenStorage->setToken($token);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the security token into the session.
|
||||
*/
|
||||
public function onKernelResponse(ResponseEvent $event)
|
||||
{
|
||||
if (!$event->isMainRequest()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$request = $event->getRequest();
|
||||
|
||||
if (!$request->hasSession() || $request->attributes->get('_security_firewall_run') !== $this->sessionKey) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($this->dispatcher) {
|
||||
$this->dispatcher->removeListener(KernelEvents::RESPONSE, [$this, 'onKernelResponse']);
|
||||
}
|
||||
$this->registered = false;
|
||||
$session = $request->getSession();
|
||||
$sessionId = $session->getId();
|
||||
$usageIndexValue = $session instanceof Session ? $usageIndexReference = &$session->getUsageIndex() : null;
|
||||
$token = $this->tokenStorage->getToken();
|
||||
|
||||
// @deprecated always use isAuthenticated() in 6.0
|
||||
$notAuthenticated = method_exists($this->trustResolver, 'isAuthenticated') ? !$this->trustResolver->isAuthenticated($token) : (null === $token || $this->trustResolver->isAnonymous($token));
|
||||
if ($notAuthenticated) {
|
||||
if ($request->hasPreviousSession()) {
|
||||
$session->remove($this->sessionKey);
|
||||
}
|
||||
} else {
|
||||
$session->set($this->sessionKey, serialize($token));
|
||||
|
||||
if (null !== $this->logger) {
|
||||
$this->logger->debug('Stored the security token in the session.', ['key' => $this->sessionKey]);
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->sessionTrackerEnabler && $session->getId() === $sessionId) {
|
||||
$usageIndexReference = $usageIndexValue;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Refreshes the user by reloading it from the user provider.
|
||||
*
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
protected function refreshUser(TokenInterface $token): ?TokenInterface
|
||||
{
|
||||
$user = $token->getUser();
|
||||
if (!$user instanceof UserInterface) {
|
||||
return $token;
|
||||
}
|
||||
|
||||
$userNotFoundByProvider = false;
|
||||
$userDeauthenticated = false;
|
||||
$userClass = \get_class($user);
|
||||
|
||||
foreach ($this->userProviders as $provider) {
|
||||
if (!$provider instanceof UserProviderInterface) {
|
||||
throw new \InvalidArgumentException(sprintf('User provider "%s" must implement "%s".', get_debug_type($provider), UserProviderInterface::class));
|
||||
}
|
||||
|
||||
if (!$provider->supportsClass($userClass)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
$refreshedUser = $provider->refreshUser($user);
|
||||
$newToken = clone $token;
|
||||
$newToken->setUser($refreshedUser, false);
|
||||
|
||||
// tokens can be deauthenticated if the user has been changed.
|
||||
if ($token instanceof AbstractToken && $this->hasUserChanged($user, $newToken)) {
|
||||
$userDeauthenticated = true;
|
||||
// @deprecated since Symfony 5.4
|
||||
if (method_exists($newToken, 'setAuthenticated')) {
|
||||
$newToken->setAuthenticated(false, false);
|
||||
}
|
||||
|
||||
if (null !== $this->logger) {
|
||||
// @deprecated since Symfony 5.3, change to $refreshedUser->getUserIdentifier() in 6.0
|
||||
$this->logger->debug('Cannot refresh token because user has changed.', ['username' => method_exists($refreshedUser, 'getUserIdentifier') ? $refreshedUser->getUserIdentifier() : $refreshedUser->getUsername(), 'provider' => \get_class($provider)]);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
$token->setUser($refreshedUser);
|
||||
|
||||
if (null !== $this->logger) {
|
||||
// @deprecated since Symfony 5.3, change to $refreshedUser->getUserIdentifier() in 6.0
|
||||
$context = ['provider' => \get_class($provider), 'username' => method_exists($refreshedUser, 'getUserIdentifier') ? $refreshedUser->getUserIdentifier() : $refreshedUser->getUsername()];
|
||||
|
||||
if ($token instanceof SwitchUserToken) {
|
||||
$originalToken = $token->getOriginalToken();
|
||||
// @deprecated since Symfony 5.3, change to $originalToken->getUserIdentifier() in 6.0
|
||||
$context['impersonator_username'] = method_exists($originalToken, 'getUserIdentifier') ? $originalToken->getUserIdentifier() : $originalToken->getUsername();
|
||||
}
|
||||
|
||||
$this->logger->debug('User was reloaded from a user provider.', $context);
|
||||
}
|
||||
|
||||
return $token;
|
||||
} catch (UnsupportedUserException $e) {
|
||||
// let's try the next user provider
|
||||
} catch (UserNotFoundException $e) {
|
||||
if (null !== $this->logger) {
|
||||
$this->logger->warning('Username could not be found in the selected user provider.', ['username' => method_exists($e, 'getUserIdentifier') ? $e->getUserIdentifier() : $e->getUsername(), 'provider' => \get_class($provider)]);
|
||||
}
|
||||
|
||||
$userNotFoundByProvider = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ($userDeauthenticated) {
|
||||
// @deprecated since Symfony 5.4
|
||||
if ($this->dispatcher) {
|
||||
$this->dispatcher->dispatch(new DeauthenticatedEvent($token, $newToken, false), DeauthenticatedEvent::class);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($userNotFoundByProvider) {
|
||||
return null;
|
||||
}
|
||||
|
||||
throw new \RuntimeException(sprintf('There is no user provider for user "%s". Shouldn\'t the "supportsClass()" method of your user provider return true for this classname?', $userClass));
|
||||
}
|
||||
|
||||
private function safelyUnserialize(string $serializedToken)
|
||||
{
|
||||
$token = null;
|
||||
$prevUnserializeHandler = ini_set('unserialize_callback_func', __CLASS__.'::handleUnserializeCallback');
|
||||
$prevErrorHandler = set_error_handler(function ($type, $msg, $file, $line, $context = []) use (&$prevErrorHandler) {
|
||||
if (__FILE__ === $file) {
|
||||
throw new \ErrorException($msg, 0x37313BC, $type, $file, $line);
|
||||
}
|
||||
|
||||
return $prevErrorHandler ? $prevErrorHandler($type, $msg, $file, $line, $context) : false;
|
||||
});
|
||||
|
||||
try {
|
||||
$token = unserialize($serializedToken);
|
||||
} catch (\ErrorException $e) {
|
||||
if (0x37313BC !== $e->getCode()) {
|
||||
throw $e;
|
||||
}
|
||||
if ($this->logger) {
|
||||
$this->logger->warning('Failed to unserialize the security token from the session.', ['key' => $this->sessionKey, 'received' => $serializedToken, 'exception' => $e]);
|
||||
}
|
||||
} finally {
|
||||
restore_error_handler();
|
||||
ini_set('unserialize_callback_func', $prevUnserializeHandler);
|
||||
}
|
||||
|
||||
return $token;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|\Stringable|UserInterface $originalUser
|
||||
*/
|
||||
private static function hasUserChanged($originalUser, TokenInterface $refreshedToken): bool
|
||||
{
|
||||
$refreshedUser = $refreshedToken->getUser();
|
||||
|
||||
if ($originalUser instanceof UserInterface) {
|
||||
if (!$refreshedUser instanceof UserInterface) {
|
||||
return true;
|
||||
} else {
|
||||
// noop
|
||||
}
|
||||
} elseif ($refreshedUser instanceof UserInterface) {
|
||||
return true;
|
||||
} else {
|
||||
return (string) $originalUser !== (string) $refreshedUser;
|
||||
}
|
||||
|
||||
if ($originalUser instanceof EquatableInterface) {
|
||||
return !(bool) $originalUser->isEqualTo($refreshedUser);
|
||||
}
|
||||
|
||||
// @deprecated since Symfony 5.3, check for PasswordAuthenticatedUserInterface on both user objects before comparing passwords
|
||||
if ($originalUser->getPassword() !== $refreshedUser->getPassword()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// @deprecated since Symfony 5.3, check for LegacyPasswordAuthenticatedUserInterface on both user objects before comparing salts
|
||||
if ($originalUser->getSalt() !== $refreshedUser->getSalt()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$userRoles = array_map('strval', (array) $refreshedUser->getRoles());
|
||||
|
||||
if ($refreshedToken instanceof SwitchUserToken) {
|
||||
$userRoles[] = 'ROLE_PREVIOUS_ADMIN';
|
||||
}
|
||||
|
||||
if (
|
||||
\count($userRoles) !== \count($refreshedToken->getRoleNames()) ||
|
||||
\count($userRoles) !== \count(array_intersect($userRoles, $refreshedToken->getRoleNames()))
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// @deprecated since Symfony 5.3, drop getUsername() in 6.0
|
||||
$userIdentifier = function ($refreshedUser) {
|
||||
return method_exists($refreshedUser, 'getUserIdentifier') ? $refreshedUser->getUserIdentifier() : $refreshedUser->getUsername();
|
||||
};
|
||||
if ($userIdentifier($originalUser) !== $userIdentifier($refreshedUser)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
public static function handleUnserializeCallback(string $class)
|
||||
{
|
||||
throw new \ErrorException('Class not found: '.$class, 0x37313BC);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated since Symfony 5.4
|
||||
*/
|
||||
public function setRememberMeServices(RememberMeServicesInterface $rememberMeServices)
|
||||
{
|
||||
trigger_deprecation('symfony/security-http', '5.4', 'Method "%s()" is deprecated, use the new remember me handlers instead.', __METHOD__);
|
||||
|
||||
$this->rememberMeServices = $rememberMeServices;
|
||||
}
|
||||
}
|
250
vendor/symfony/security-http/Firewall/ExceptionListener.php
vendored
Normal file
250
vendor/symfony/security-http/Firewall/ExceptionListener.php
vendored
Normal file
@ -0,0 +1,250 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\Firewall;
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\Event\ExceptionEvent;
|
||||
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
|
||||
use Symfony\Component\HttpKernel\Exception\HttpException;
|
||||
use Symfony\Component\HttpKernel\HttpKernelInterface;
|
||||
use Symfony\Component\HttpKernel\KernelEvents;
|
||||
use Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolverInterface;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
|
||||
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
|
||||
use Symfony\Component\Security\Core\Exception\AccountStatusException;
|
||||
use Symfony\Component\Security\Core\Exception\AuthenticationException;
|
||||
use Symfony\Component\Security\Core\Exception\InsufficientAuthenticationException;
|
||||
use Symfony\Component\Security\Core\Exception\LazyResponseException;
|
||||
use Symfony\Component\Security\Core\Exception\LogoutException;
|
||||
use Symfony\Component\Security\Core\Security;
|
||||
use Symfony\Component\Security\Http\Authorization\AccessDeniedHandlerInterface;
|
||||
use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface;
|
||||
use Symfony\Component\Security\Http\EntryPoint\Exception\NotAnEntryPointException;
|
||||
use Symfony\Component\Security\Http\HttpUtils;
|
||||
use Symfony\Component\Security\Http\Util\TargetPathTrait;
|
||||
|
||||
/**
|
||||
* ExceptionListener catches authentication exception and converts them to
|
||||
* Response instances.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
class ExceptionListener
|
||||
{
|
||||
use TargetPathTrait;
|
||||
|
||||
private $tokenStorage;
|
||||
private $firewallName;
|
||||
private $accessDeniedHandler;
|
||||
private $authenticationEntryPoint;
|
||||
private $authenticationTrustResolver;
|
||||
private $errorPage;
|
||||
private $logger;
|
||||
private $httpUtils;
|
||||
private $stateless;
|
||||
|
||||
public function __construct(TokenStorageInterface $tokenStorage, AuthenticationTrustResolverInterface $trustResolver, HttpUtils $httpUtils, string $firewallName, AuthenticationEntryPointInterface $authenticationEntryPoint = null, string $errorPage = null, AccessDeniedHandlerInterface $accessDeniedHandler = null, LoggerInterface $logger = null, bool $stateless = false)
|
||||
{
|
||||
$this->tokenStorage = $tokenStorage;
|
||||
$this->accessDeniedHandler = $accessDeniedHandler;
|
||||
$this->httpUtils = $httpUtils;
|
||||
$this->firewallName = $firewallName;
|
||||
$this->authenticationEntryPoint = $authenticationEntryPoint;
|
||||
$this->authenticationTrustResolver = $trustResolver;
|
||||
$this->errorPage = $errorPage;
|
||||
$this->logger = $logger;
|
||||
$this->stateless = $stateless;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a onKernelException listener to take care of security exceptions.
|
||||
*/
|
||||
public function register(EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$dispatcher->addListener(KernelEvents::EXCEPTION, [$this, 'onKernelException'], 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters the dispatcher.
|
||||
*/
|
||||
public function unregister(EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$dispatcher->removeListener(KernelEvents::EXCEPTION, [$this, 'onKernelException']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles security related exceptions.
|
||||
*/
|
||||
public function onKernelException(ExceptionEvent $event)
|
||||
{
|
||||
$exception = $event->getThrowable();
|
||||
do {
|
||||
if ($exception instanceof AuthenticationException) {
|
||||
$this->handleAuthenticationException($event, $exception);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ($exception instanceof AccessDeniedException) {
|
||||
$this->handleAccessDeniedException($event, $exception);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ($exception instanceof LazyResponseException) {
|
||||
$event->setResponse($exception->getResponse());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ($exception instanceof LogoutException) {
|
||||
$this->handleLogoutException($event, $exception);
|
||||
|
||||
return;
|
||||
}
|
||||
} while (null !== $exception = $exception->getPrevious());
|
||||
}
|
||||
|
||||
private function handleAuthenticationException(ExceptionEvent $event, AuthenticationException $exception): void
|
||||
{
|
||||
if (null !== $this->logger) {
|
||||
$this->logger->info('An AuthenticationException was thrown; redirecting to authentication entry point.', ['exception' => $exception]);
|
||||
}
|
||||
|
||||
try {
|
||||
$event->setResponse($this->startAuthentication($event->getRequest(), $exception));
|
||||
$event->allowCustomResponseCode();
|
||||
} catch (\Exception $e) {
|
||||
$event->setThrowable($e);
|
||||
}
|
||||
}
|
||||
|
||||
private function handleAccessDeniedException(ExceptionEvent $event, AccessDeniedException $exception)
|
||||
{
|
||||
$event->setThrowable(new AccessDeniedHttpException($exception->getMessage(), $exception));
|
||||
|
||||
$token = $this->tokenStorage->getToken();
|
||||
if (!$this->authenticationTrustResolver->isFullFledged($token)) {
|
||||
if (null !== $this->logger) {
|
||||
$this->logger->debug('Access denied, the user is not fully authenticated; redirecting to authentication entry point.', ['exception' => $exception]);
|
||||
}
|
||||
|
||||
try {
|
||||
$insufficientAuthenticationException = new InsufficientAuthenticationException('Full authentication is required to access this resource.', 0, $exception);
|
||||
if (null !== $token) {
|
||||
$insufficientAuthenticationException->setToken($token);
|
||||
}
|
||||
|
||||
$event->setResponse($this->startAuthentication($event->getRequest(), $insufficientAuthenticationException));
|
||||
} catch (\Exception $e) {
|
||||
$event->setThrowable($e);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (null !== $this->logger) {
|
||||
$this->logger->debug('Access denied, the user is neither anonymous, nor remember-me.', ['exception' => $exception]);
|
||||
}
|
||||
|
||||
try {
|
||||
if (null !== $this->accessDeniedHandler) {
|
||||
$response = $this->accessDeniedHandler->handle($event->getRequest(), $exception);
|
||||
|
||||
if ($response instanceof Response) {
|
||||
$event->setResponse($response);
|
||||
}
|
||||
} elseif (null !== $this->errorPage) {
|
||||
$subRequest = $this->httpUtils->createRequest($event->getRequest(), $this->errorPage);
|
||||
$subRequest->attributes->set(Security::ACCESS_DENIED_ERROR, $exception);
|
||||
|
||||
$event->setResponse($event->getKernel()->handle($subRequest, HttpKernelInterface::SUB_REQUEST, true));
|
||||
$event->allowCustomResponseCode();
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
if (null !== $this->logger) {
|
||||
$this->logger->error('An exception was thrown when handling an AccessDeniedException.', ['exception' => $e]);
|
||||
}
|
||||
|
||||
$event->setThrowable(new \RuntimeException('Exception thrown when handling an exception.', 0, $e));
|
||||
}
|
||||
}
|
||||
|
||||
private function handleLogoutException(ExceptionEvent $event, LogoutException $exception): void
|
||||
{
|
||||
$event->setThrowable(new AccessDeniedHttpException($exception->getMessage(), $exception));
|
||||
|
||||
if (null !== $this->logger) {
|
||||
$this->logger->info('A LogoutException was thrown; wrapping with AccessDeniedHttpException', ['exception' => $exception]);
|
||||
}
|
||||
}
|
||||
|
||||
private function startAuthentication(Request $request, AuthenticationException $authException): Response
|
||||
{
|
||||
if (null === $this->authenticationEntryPoint) {
|
||||
$this->throwUnauthorizedException($authException);
|
||||
}
|
||||
|
||||
if (null !== $this->logger) {
|
||||
$this->logger->debug('Calling Authentication entry point.');
|
||||
}
|
||||
|
||||
if (!$this->stateless) {
|
||||
$this->setTargetPath($request);
|
||||
}
|
||||
|
||||
if ($authException instanceof AccountStatusException) {
|
||||
// remove the security token to prevent infinite redirect loops
|
||||
$this->tokenStorage->setToken(null);
|
||||
|
||||
if (null !== $this->logger) {
|
||||
$this->logger->info('The security token was removed due to an AccountStatusException.', ['exception' => $authException]);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
$response = $this->authenticationEntryPoint->start($request, $authException);
|
||||
} catch (NotAnEntryPointException $e) {
|
||||
$this->throwUnauthorizedException($authException);
|
||||
}
|
||||
|
||||
if (!$response instanceof Response) {
|
||||
$given = get_debug_type($response);
|
||||
|
||||
throw new \LogicException(sprintf('The "%s::start()" method must return a Response object ("%s" returned).', get_debug_type($this->authenticationEntryPoint), $given));
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
protected function setTargetPath(Request $request)
|
||||
{
|
||||
// session isn't required when using HTTP basic authentication mechanism for example
|
||||
if ($request->hasSession() && $request->isMethodSafe() && !$request->isXmlHttpRequest()) {
|
||||
$this->saveTargetPath($request->getSession(), $this->firewallName, $request->getUri());
|
||||
}
|
||||
}
|
||||
|
||||
private function throwUnauthorizedException(AuthenticationException $authException)
|
||||
{
|
||||
if (null !== $this->logger) {
|
||||
$this->logger->notice(sprintf('No Authentication entry point configured, returning a %s HTTP response. Configure "entry_point" on the firewall "%s" if you want to modify the response.', Response::HTTP_UNAUTHORIZED, $this->firewallName));
|
||||
}
|
||||
|
||||
throw new HttpException(Response::HTTP_UNAUTHORIZED, $authException->getMessage(), $authException, [], $authException->getCode());
|
||||
}
|
||||
}
|
43
vendor/symfony/security-http/Firewall/FirewallListenerInterface.php
vendored
Normal file
43
vendor/symfony/security-http/Firewall/FirewallListenerInterface.php
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\Firewall;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\Event\RequestEvent;
|
||||
|
||||
/**
|
||||
* Can be implemented by firewall listeners.
|
||||
*
|
||||
* @author Christian Scheb <me@christianscheb.de>
|
||||
* @author Nicolas Grekas <p@tchwork.com>
|
||||
* @author Robin Chalas <robin.chalas@gmail.com>
|
||||
*/
|
||||
interface FirewallListenerInterface
|
||||
{
|
||||
/**
|
||||
* Tells whether the authenticate() method should be called or not depending on the incoming request.
|
||||
*
|
||||
* Returning null means authenticate() can be called lazily when accessing the token storage.
|
||||
*/
|
||||
public function supports(Request $request): ?bool;
|
||||
|
||||
/**
|
||||
* Does whatever is required to authenticate the request, typically calling $event->setResponse() internally.
|
||||
*/
|
||||
public function authenticate(RequestEvent $event);
|
||||
|
||||
/**
|
||||
* Defines the priority of the listener.
|
||||
* The higher the number, the earlier a listener is executed.
|
||||
*/
|
||||
public static function getPriority(): int;
|
||||
}
|
150
vendor/symfony/security-http/Firewall/LogoutListener.php
vendored
Normal file
150
vendor/symfony/security-http/Firewall/LogoutListener.php
vendored
Normal file
@ -0,0 +1,150 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\Firewall;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventDispatcher;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\Event\RequestEvent;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
|
||||
use Symfony\Component\Security\Core\Exception\LogicException;
|
||||
use Symfony\Component\Security\Core\Exception\LogoutException;
|
||||
use Symfony\Component\Security\Csrf\CsrfToken;
|
||||
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
|
||||
use Symfony\Component\Security\Http\Event\LogoutEvent;
|
||||
use Symfony\Component\Security\Http\HttpUtils;
|
||||
use Symfony\Component\Security\Http\Logout\LogoutHandlerInterface;
|
||||
use Symfony\Component\Security\Http\Logout\LogoutSuccessHandlerInterface;
|
||||
use Symfony\Component\Security\Http\ParameterBagUtils;
|
||||
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
|
||||
|
||||
/**
|
||||
* LogoutListener logout users.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
class LogoutListener extends AbstractListener
|
||||
{
|
||||
private $tokenStorage;
|
||||
private $options;
|
||||
private $httpUtils;
|
||||
private $csrfTokenManager;
|
||||
private $eventDispatcher;
|
||||
|
||||
/**
|
||||
* @param EventDispatcherInterface $eventDispatcher
|
||||
* @param array $options An array of options to process a logout attempt
|
||||
*/
|
||||
public function __construct(TokenStorageInterface $tokenStorage, HttpUtils $httpUtils, $eventDispatcher, array $options = [], CsrfTokenManagerInterface $csrfTokenManager = null)
|
||||
{
|
||||
if (!$eventDispatcher instanceof EventDispatcherInterface) {
|
||||
trigger_deprecation('symfony/security-http', '5.1', 'Passing a logout success handler to "%s" is deprecated, pass an instance of "%s" instead.', __METHOD__, EventDispatcherInterface::class);
|
||||
|
||||
if (!$eventDispatcher instanceof LogoutSuccessHandlerInterface) {
|
||||
throw new \TypeError(sprintf('Argument 3 of "%s" must be instance of "%s" or "%s", "%s" given.', __METHOD__, EventDispatcherInterface::class, LogoutSuccessHandlerInterface::class, get_debug_type($eventDispatcher)));
|
||||
}
|
||||
|
||||
$successHandler = $eventDispatcher;
|
||||
$eventDispatcher = new EventDispatcher();
|
||||
$eventDispatcher->addListener(LogoutEvent::class, function (LogoutEvent $event) use ($successHandler) {
|
||||
$event->setResponse($r = $successHandler->onLogoutSuccess($event->getRequest()));
|
||||
});
|
||||
}
|
||||
|
||||
$this->tokenStorage = $tokenStorage;
|
||||
$this->httpUtils = $httpUtils;
|
||||
$this->options = array_merge([
|
||||
'csrf_parameter' => '_csrf_token',
|
||||
'csrf_token_id' => 'logout',
|
||||
'logout_path' => '/logout',
|
||||
], $options);
|
||||
$this->csrfTokenManager = $csrfTokenManager;
|
||||
$this->eventDispatcher = $eventDispatcher;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated since Symfony 5.1
|
||||
*/
|
||||
public function addHandler(LogoutHandlerInterface $handler)
|
||||
{
|
||||
trigger_deprecation('symfony/security-http', '5.1', 'Calling "%s" is deprecated, register a listener on the "%s" event instead.', __METHOD__, LogoutEvent::class);
|
||||
|
||||
$this->eventDispatcher->addListener(LogoutEvent::class, function (LogoutEvent $event) use ($handler) {
|
||||
if (null === $event->getResponse()) {
|
||||
throw new LogicException(sprintf('No response was set for this logout action. Make sure the DefaultLogoutListener or another listener has set the response before "%s" is called.', __CLASS__));
|
||||
}
|
||||
|
||||
$handler->logout($event->getRequest(), $event->getResponse(), $event->getToken());
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function supports(Request $request): ?bool
|
||||
{
|
||||
return $this->requiresLogout($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the logout if requested.
|
||||
*
|
||||
* If a CsrfTokenManagerInterface instance is available, it will be used to
|
||||
* validate the request.
|
||||
*
|
||||
* @throws LogoutException if the CSRF token is invalid
|
||||
* @throws \RuntimeException if the LogoutSuccessHandlerInterface instance does not return a response
|
||||
*/
|
||||
public function authenticate(RequestEvent $event)
|
||||
{
|
||||
$request = $event->getRequest();
|
||||
|
||||
if (null !== $this->csrfTokenManager) {
|
||||
$csrfToken = ParameterBagUtils::getRequestParameterValue($request, $this->options['csrf_parameter']);
|
||||
|
||||
if (!\is_string($csrfToken) || false === $this->csrfTokenManager->isTokenValid(new CsrfToken($this->options['csrf_token_id'], $csrfToken))) {
|
||||
throw new LogoutException('Invalid CSRF token.');
|
||||
}
|
||||
}
|
||||
|
||||
$logoutEvent = new LogoutEvent($request, $this->tokenStorage->getToken());
|
||||
$this->eventDispatcher->dispatch($logoutEvent);
|
||||
|
||||
$response = $logoutEvent->getResponse();
|
||||
if (!$response instanceof Response) {
|
||||
throw new \RuntimeException('No logout listener set the Response, make sure at least the DefaultLogoutListener is registered.');
|
||||
}
|
||||
|
||||
$this->tokenStorage->setToken(null);
|
||||
|
||||
$event->setResponse($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this request is asking for logout.
|
||||
*
|
||||
* The default implementation only processed requests to a specific path,
|
||||
* but a subclass could change this to logout requests where
|
||||
* certain parameters is present.
|
||||
*/
|
||||
protected function requiresLogout(Request $request): bool
|
||||
{
|
||||
return isset($this->options['logout_path']) && $this->httpUtils->checkRequestPath($request, $this->options['logout_path']);
|
||||
}
|
||||
|
||||
public static function getPriority(): int
|
||||
{
|
||||
return -127;
|
||||
}
|
||||
}
|
130
vendor/symfony/security-http/Firewall/RememberMeListener.php
vendored
Normal file
130
vendor/symfony/security-http/Firewall/RememberMeListener.php
vendored
Normal file
@ -0,0 +1,130 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\Firewall;
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\Event\RequestEvent;
|
||||
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
|
||||
use Symfony\Component\Security\Core\Exception\AuthenticationException;
|
||||
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
|
||||
use Symfony\Component\Security\Http\RememberMe\RememberMeServicesInterface;
|
||||
use Symfony\Component\Security\Http\SecurityEvents;
|
||||
use Symfony\Component\Security\Http\Session\SessionAuthenticationStrategy;
|
||||
use Symfony\Component\Security\Http\Session\SessionAuthenticationStrategyInterface;
|
||||
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
|
||||
|
||||
trigger_deprecation('symfony/security-http', '5.3', 'The "%s" class is deprecated, use the new authenticator system instead.', RememberMeListener::class);
|
||||
|
||||
/**
|
||||
* RememberMeListener implements authentication capabilities via a cookie.
|
||||
*
|
||||
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
|
||||
*
|
||||
* @final
|
||||
*
|
||||
* @deprecated since Symfony 5.3, use the new authenticator system instead
|
||||
*/
|
||||
class RememberMeListener extends AbstractListener
|
||||
{
|
||||
private $tokenStorage;
|
||||
private $rememberMeServices;
|
||||
private $authenticationManager;
|
||||
private $logger;
|
||||
private $dispatcher;
|
||||
private $catchExceptions = true;
|
||||
private $sessionStrategy;
|
||||
|
||||
public function __construct(TokenStorageInterface $tokenStorage, RememberMeServicesInterface $rememberMeServices, AuthenticationManagerInterface $authenticationManager, LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null, bool $catchExceptions = true, SessionAuthenticationStrategyInterface $sessionStrategy = null)
|
||||
{
|
||||
$this->tokenStorage = $tokenStorage;
|
||||
$this->rememberMeServices = $rememberMeServices;
|
||||
$this->authenticationManager = $authenticationManager;
|
||||
$this->logger = $logger;
|
||||
$this->dispatcher = $dispatcher;
|
||||
$this->catchExceptions = $catchExceptions;
|
||||
$this->sessionStrategy = $sessionStrategy ?? new SessionAuthenticationStrategy(SessionAuthenticationStrategy::MIGRATE);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function supports(Request $request): ?bool
|
||||
{
|
||||
return null; // always run authenticate() lazily with lazy firewalls
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles remember-me cookie based authentication.
|
||||
*/
|
||||
public function authenticate(RequestEvent $event)
|
||||
{
|
||||
if (null !== $this->tokenStorage->getToken()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$request = $event->getRequest();
|
||||
try {
|
||||
if (null === $token = $this->rememberMeServices->autoLogin($request)) {
|
||||
return;
|
||||
}
|
||||
} catch (AuthenticationException $e) {
|
||||
if (null !== $this->logger) {
|
||||
$this->logger->warning(
|
||||
'The token storage was not populated with remember-me token as the'
|
||||
.' RememberMeServices was not able to create a token from the remember'
|
||||
.' me information.', ['exception' => $e]
|
||||
);
|
||||
}
|
||||
|
||||
$this->rememberMeServices->loginFail($request);
|
||||
|
||||
if (!$this->catchExceptions) {
|
||||
throw $e;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
$token = $this->authenticationManager->authenticate($token);
|
||||
if ($request->hasSession() && $request->getSession()->isStarted()) {
|
||||
$this->sessionStrategy->onAuthentication($request, $token);
|
||||
}
|
||||
$this->tokenStorage->setToken($token);
|
||||
|
||||
if (null !== $this->dispatcher) {
|
||||
$loginEvent = new InteractiveLoginEvent($request, $token);
|
||||
$this->dispatcher->dispatch($loginEvent, SecurityEvents::INTERACTIVE_LOGIN);
|
||||
}
|
||||
|
||||
if (null !== $this->logger) {
|
||||
$this->logger->debug('Populated the token storage with a remember-me token.');
|
||||
}
|
||||
} catch (AuthenticationException $e) {
|
||||
if (null !== $this->logger) {
|
||||
$this->logger->warning(
|
||||
'The token storage was not populated with remember-me token as the'
|
||||
.' AuthenticationManager rejected the AuthenticationToken returned'
|
||||
.' by the RememberMeServices.', ['exception' => $e]
|
||||
);
|
||||
}
|
||||
|
||||
$this->rememberMeServices->loginFail($request, $e);
|
||||
|
||||
if (!$this->catchExceptions) {
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
53
vendor/symfony/security-http/Firewall/RemoteUserAuthenticationListener.php
vendored
Normal file
53
vendor/symfony/security-http/Firewall/RemoteUserAuthenticationListener.php
vendored
Normal file
@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\Firewall;
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
|
||||
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
|
||||
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
|
||||
|
||||
trigger_deprecation('symfony/security-http', '5.3', 'The "%s" class is deprecated, use the new authenticator system instead.', RemoteUserAuthenticationListener::class);
|
||||
|
||||
/**
|
||||
* REMOTE_USER authentication listener.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Maxime Douailin <maxime.douailin@gmail.com>
|
||||
*
|
||||
* @deprecated since Symfony 5.3, use the new authenticator system instead
|
||||
*/
|
||||
class RemoteUserAuthenticationListener extends AbstractPreAuthenticatedListener
|
||||
{
|
||||
private $userKey;
|
||||
|
||||
public function __construct(TokenStorageInterface $tokenStorage, AuthenticationManagerInterface $authenticationManager, string $providerKey, string $userKey = 'REMOTE_USER', LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null)
|
||||
{
|
||||
parent::__construct($tokenStorage, $authenticationManager, $providerKey, $logger, $dispatcher);
|
||||
|
||||
$this->userKey = $userKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getPreAuthenticatedData(Request $request)
|
||||
{
|
||||
if (!$request->server->has($this->userKey)) {
|
||||
throw new BadCredentialsException(sprintf('User key was not found: "%s".', $this->userKey));
|
||||
}
|
||||
|
||||
return [$request->server->get($this->userKey), null];
|
||||
}
|
||||
}
|
235
vendor/symfony/security-http/Firewall/SwitchUserListener.php
vendored
Normal file
235
vendor/symfony/security-http/Firewall/SwitchUserListener.php
vendored
Normal file
@ -0,0 +1,235 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\Firewall;
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\Event\RequestEvent;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\SwitchUserToken;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||
use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface;
|
||||
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
|
||||
use Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException;
|
||||
use Symfony\Component\Security\Core\Exception\AuthenticationException;
|
||||
use Symfony\Component\Security\Core\User\UserCheckerInterface;
|
||||
use Symfony\Component\Security\Core\User\UserInterface;
|
||||
use Symfony\Component\Security\Core\User\UserProviderInterface;
|
||||
use Symfony\Component\Security\Http\Event\SwitchUserEvent;
|
||||
use Symfony\Component\Security\Http\SecurityEvents;
|
||||
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
|
||||
|
||||
/**
|
||||
* SwitchUserListener allows a user to impersonate another one temporarily
|
||||
* (like the Unix su command).
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
class SwitchUserListener extends AbstractListener
|
||||
{
|
||||
public const EXIT_VALUE = '_exit';
|
||||
|
||||
private $tokenStorage;
|
||||
private $provider;
|
||||
private $userChecker;
|
||||
private $firewallName;
|
||||
private $accessDecisionManager;
|
||||
private $usernameParameter;
|
||||
private $role;
|
||||
private $logger;
|
||||
private $dispatcher;
|
||||
private $stateless;
|
||||
|
||||
public function __construct(TokenStorageInterface $tokenStorage, UserProviderInterface $provider, UserCheckerInterface $userChecker, string $firewallName, AccessDecisionManagerInterface $accessDecisionManager, LoggerInterface $logger = null, string $usernameParameter = '_switch_user', string $role = 'ROLE_ALLOWED_TO_SWITCH', EventDispatcherInterface $dispatcher = null, bool $stateless = false)
|
||||
{
|
||||
if ('' === $firewallName) {
|
||||
throw new \InvalidArgumentException('$firewallName must not be empty.');
|
||||
}
|
||||
|
||||
$this->tokenStorage = $tokenStorage;
|
||||
$this->provider = $provider;
|
||||
$this->userChecker = $userChecker;
|
||||
$this->firewallName = $firewallName;
|
||||
$this->accessDecisionManager = $accessDecisionManager;
|
||||
$this->usernameParameter = $usernameParameter;
|
||||
$this->role = $role;
|
||||
$this->logger = $logger;
|
||||
$this->dispatcher = $dispatcher;
|
||||
$this->stateless = $stateless;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function supports(Request $request): ?bool
|
||||
{
|
||||
// usernames can be falsy
|
||||
$username = $request->get($this->usernameParameter);
|
||||
|
||||
if (null === $username || '' === $username) {
|
||||
$username = $request->headers->get($this->usernameParameter);
|
||||
}
|
||||
|
||||
// if it's still "empty", nothing to do.
|
||||
if (null === $username || '' === $username) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$request->attributes->set('_switch_user_username', $username);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the switch to another user.
|
||||
*
|
||||
* @throws \LogicException if switching to a user failed
|
||||
*/
|
||||
public function authenticate(RequestEvent $event)
|
||||
{
|
||||
$request = $event->getRequest();
|
||||
|
||||
$username = $request->attributes->get('_switch_user_username');
|
||||
$request->attributes->remove('_switch_user_username');
|
||||
|
||||
if (null === $this->tokenStorage->getToken()) {
|
||||
throw new AuthenticationCredentialsNotFoundException('Could not find original Token object.');
|
||||
}
|
||||
|
||||
if (self::EXIT_VALUE === $username) {
|
||||
$this->tokenStorage->setToken($this->attemptExitUser($request));
|
||||
} else {
|
||||
try {
|
||||
$this->tokenStorage->setToken($this->attemptSwitchUser($request, $username));
|
||||
} catch (AuthenticationException $e) {
|
||||
// Generate 403 in any conditions to prevent user enumeration vulnerabilities
|
||||
throw new AccessDeniedException('Switch User failed: '.$e->getMessage(), $e);
|
||||
}
|
||||
}
|
||||
|
||||
if (!$this->stateless) {
|
||||
$request->query->remove($this->usernameParameter);
|
||||
$request->server->set('QUERY_STRING', http_build_query($request->query->all(), '', '&'));
|
||||
$response = new RedirectResponse($request->getUri(), 302);
|
||||
|
||||
$event->setResponse($response);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to switch to another user and returns the new token if successfully switched.
|
||||
*
|
||||
* @throws \LogicException
|
||||
* @throws AccessDeniedException
|
||||
*/
|
||||
private function attemptSwitchUser(Request $request, string $username): ?TokenInterface
|
||||
{
|
||||
$token = $this->tokenStorage->getToken();
|
||||
$originalToken = $this->getOriginalToken($token);
|
||||
|
||||
if (null !== $originalToken) {
|
||||
// @deprecated since Symfony 5.3, change to $token->getUserIdentifier() in 6.0
|
||||
if ((method_exists($token, 'getUserIdentifier') ? $token->getUserIdentifier() : $token->getUsername()) === $username) {
|
||||
return $token;
|
||||
}
|
||||
|
||||
// User already switched, exit before seamlessly switching to another user
|
||||
$token = $this->attemptExitUser($request);
|
||||
}
|
||||
|
||||
// @deprecated since Symfony 5.3, change to $token->getUserIdentifier() in 6.0
|
||||
$currentUsername = method_exists($token, 'getUserIdentifier') ? $token->getUserIdentifier() : $token->getUsername();
|
||||
$nonExistentUsername = '_'.md5(random_bytes(8).$username);
|
||||
|
||||
// To protect against user enumeration via timing measurements
|
||||
// we always load both successfully and unsuccessfully
|
||||
$methodName = 'loadUserByIdentifier';
|
||||
if (!method_exists($this->provider, $methodName)) {
|
||||
trigger_deprecation('symfony/security-core', '5.3', 'Not implementing method "loadUserByIdentifier()" in user provider "%s" is deprecated. This method will replace "loadUserByUsername()" in Symfony 6.0.', get_debug_type($this->provider));
|
||||
|
||||
$methodName = 'loadUserByUsername';
|
||||
}
|
||||
try {
|
||||
$user = $this->provider->$methodName($username);
|
||||
|
||||
try {
|
||||
$this->provider->$methodName($nonExistentUsername);
|
||||
} catch (\Exception $e) {
|
||||
}
|
||||
} catch (AuthenticationException $e) {
|
||||
$this->provider->$methodName($currentUsername);
|
||||
|
||||
throw $e;
|
||||
}
|
||||
|
||||
if (false === $this->accessDecisionManager->decide($token, [$this->role], $user)) {
|
||||
$exception = new AccessDeniedException();
|
||||
$exception->setAttributes($this->role);
|
||||
|
||||
throw $exception;
|
||||
}
|
||||
|
||||
if (null !== $this->logger) {
|
||||
$this->logger->info('Attempting to switch to user.', ['username' => $username]);
|
||||
}
|
||||
|
||||
$this->userChecker->checkPostAuth($user);
|
||||
|
||||
$roles = $user->getRoles();
|
||||
$roles[] = 'ROLE_PREVIOUS_ADMIN';
|
||||
$originatedFromUri = str_replace('/&', '/?', preg_replace('#[&?]'.$this->usernameParameter.'=[^&]*#', '', $request->getRequestUri()));
|
||||
$token = new SwitchUserToken($user, $this->firewallName, $roles, $token, $originatedFromUri);
|
||||
|
||||
if (null !== $this->dispatcher) {
|
||||
$switchEvent = new SwitchUserEvent($request, $token->getUser(), $token);
|
||||
$this->dispatcher->dispatch($switchEvent, SecurityEvents::SWITCH_USER);
|
||||
// use the token from the event in case any listeners have replaced it.
|
||||
$token = $switchEvent->getToken();
|
||||
}
|
||||
|
||||
return $token;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to exit from an already switched user and returns the original token.
|
||||
*
|
||||
* @throws AuthenticationCredentialsNotFoundException
|
||||
*/
|
||||
private function attemptExitUser(Request $request): TokenInterface
|
||||
{
|
||||
if (null === ($currentToken = $this->tokenStorage->getToken()) || null === $original = $this->getOriginalToken($currentToken)) {
|
||||
throw new AuthenticationCredentialsNotFoundException('Could not find original Token object.');
|
||||
}
|
||||
|
||||
if (null !== $this->dispatcher && $original->getUser() instanceof UserInterface) {
|
||||
$user = $this->provider->refreshUser($original->getUser());
|
||||
$original->setUser($user);
|
||||
$switchEvent = new SwitchUserEvent($request, $user, $original);
|
||||
$this->dispatcher->dispatch($switchEvent, SecurityEvents::SWITCH_USER);
|
||||
$original = $switchEvent->getToken();
|
||||
}
|
||||
|
||||
return $original;
|
||||
}
|
||||
|
||||
private function getOriginalToken(TokenInterface $token): ?TokenInterface
|
||||
{
|
||||
if ($token instanceof SwitchUserToken) {
|
||||
return $token->getOriginalToken();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
110
vendor/symfony/security-http/Firewall/UsernamePasswordFormAuthenticationListener.php
vendored
Normal file
110
vendor/symfony/security-http/Firewall/UsernamePasswordFormAuthenticationListener.php
vendored
Normal file
@ -0,0 +1,110 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\Firewall;
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
|
||||
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
|
||||
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
|
||||
use Symfony\Component\Security\Core\Exception\InvalidCsrfTokenException;
|
||||
use Symfony\Component\Security\Core\Security;
|
||||
use Symfony\Component\Security\Csrf\CsrfToken;
|
||||
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
|
||||
use Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface;
|
||||
use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface;
|
||||
use Symfony\Component\Security\Http\HttpUtils;
|
||||
use Symfony\Component\Security\Http\ParameterBagUtils;
|
||||
use Symfony\Component\Security\Http\Session\SessionAuthenticationStrategyInterface;
|
||||
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
|
||||
|
||||
trigger_deprecation('symfony/security-http', '5.3', 'The "%s" class is deprecated, use the new authenticator system instead.', UsernamePasswordFormAuthenticationListener::class);
|
||||
|
||||
/**
|
||||
* UsernamePasswordFormAuthenticationListener is the default implementation of
|
||||
* an authentication via a simple form composed of a username and a password.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @deprecated since Symfony 5.3, use the new authenticator system instead
|
||||
*/
|
||||
class UsernamePasswordFormAuthenticationListener extends AbstractAuthenticationListener
|
||||
{
|
||||
private $csrfTokenManager;
|
||||
|
||||
public function __construct(TokenStorageInterface $tokenStorage, AuthenticationManagerInterface $authenticationManager, SessionAuthenticationStrategyInterface $sessionStrategy, HttpUtils $httpUtils, string $providerKey, AuthenticationSuccessHandlerInterface $successHandler, AuthenticationFailureHandlerInterface $failureHandler, array $options = [], LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null, CsrfTokenManagerInterface $csrfTokenManager = null)
|
||||
{
|
||||
parent::__construct($tokenStorage, $authenticationManager, $sessionStrategy, $httpUtils, $providerKey, $successHandler, $failureHandler, array_merge([
|
||||
'username_parameter' => '_username',
|
||||
'password_parameter' => '_password',
|
||||
'csrf_parameter' => '_csrf_token',
|
||||
'csrf_token_id' => 'authenticate',
|
||||
'post_only' => true,
|
||||
], $options), $logger, $dispatcher);
|
||||
|
||||
$this->csrfTokenManager = $csrfTokenManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function requiresAuthentication(Request $request)
|
||||
{
|
||||
if ($this->options['post_only'] && !$request->isMethod('POST')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return parent::requiresAuthentication($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function attemptAuthentication(Request $request)
|
||||
{
|
||||
if (null !== $this->csrfTokenManager) {
|
||||
$csrfToken = ParameterBagUtils::getRequestParameterValue($request, $this->options['csrf_parameter']);
|
||||
|
||||
if (!\is_string($csrfToken) || false === $this->csrfTokenManager->isTokenValid(new CsrfToken($this->options['csrf_token_id'], $csrfToken))) {
|
||||
throw new InvalidCsrfTokenException('Invalid CSRF token.');
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->options['post_only']) {
|
||||
$username = ParameterBagUtils::getParameterBagValue($request->request, $this->options['username_parameter']);
|
||||
$password = ParameterBagUtils::getParameterBagValue($request->request, $this->options['password_parameter']);
|
||||
} else {
|
||||
$username = ParameterBagUtils::getRequestParameterValue($request, $this->options['username_parameter']);
|
||||
$password = ParameterBagUtils::getRequestParameterValue($request, $this->options['password_parameter']);
|
||||
}
|
||||
|
||||
if (!\is_string($username) && (!\is_object($username) || !method_exists($username, '__toString'))) {
|
||||
throw new BadRequestHttpException(sprintf('The key "%s" must be a string, "%s" given.', $this->options['username_parameter'], get_debug_type($username)));
|
||||
}
|
||||
|
||||
$username = trim($username);
|
||||
|
||||
if (\strlen($username) > Security::MAX_USERNAME_LENGTH) {
|
||||
throw new BadCredentialsException('Invalid username.');
|
||||
}
|
||||
|
||||
if (null === $password) {
|
||||
throw new \LogicException(sprintf('The key "%s" cannot be null; check that the password field name of the form matches.', $this->options['password_parameter']));
|
||||
}
|
||||
|
||||
$request->getSession()->set(Security::LAST_USERNAME, $username);
|
||||
|
||||
return $this->authenticationManager->authenticate(new UsernamePasswordToken($username, $password, $this->providerKey));
|
||||
}
|
||||
}
|
235
vendor/symfony/security-http/Firewall/UsernamePasswordJsonAuthenticationListener.php
vendored
Normal file
235
vendor/symfony/security-http/Firewall/UsernamePasswordJsonAuthenticationListener.php
vendored
Normal file
@ -0,0 +1,235 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\Firewall;
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\Event\RequestEvent;
|
||||
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
|
||||
use Symfony\Component\PropertyAccess\Exception\AccessException;
|
||||
use Symfony\Component\PropertyAccess\PropertyAccess;
|
||||
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
|
||||
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
|
||||
use Symfony\Component\Security\Core\Exception\AuthenticationException;
|
||||
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
|
||||
use Symfony\Component\Security\Core\Security;
|
||||
use Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface;
|
||||
use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface;
|
||||
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
|
||||
use Symfony\Component\Security\Http\HttpUtils;
|
||||
use Symfony\Component\Security\Http\SecurityEvents;
|
||||
use Symfony\Component\Security\Http\Session\SessionAuthenticationStrategyInterface;
|
||||
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
trigger_deprecation('symfony/security-http', '5.3', 'The "%s" class is deprecated, use the new authenticator system instead.', UsernamePasswordJsonAuthenticationListener::class);
|
||||
|
||||
/**
|
||||
* UsernamePasswordJsonAuthenticationListener is a stateless implementation of
|
||||
* an authentication via a JSON document composed of a username and a password.
|
||||
*
|
||||
* @author Kévin Dunglas <dunglas@gmail.com>
|
||||
*
|
||||
* @deprecated since Symfony 5.3, use the new authenticator system instead
|
||||
*/
|
||||
class UsernamePasswordJsonAuthenticationListener extends AbstractListener
|
||||
{
|
||||
private $tokenStorage;
|
||||
private $authenticationManager;
|
||||
private $httpUtils;
|
||||
private $providerKey;
|
||||
private $successHandler;
|
||||
private $failureHandler;
|
||||
private $options;
|
||||
private $logger;
|
||||
private $eventDispatcher;
|
||||
private $propertyAccessor;
|
||||
private $sessionStrategy;
|
||||
|
||||
/**
|
||||
* @var TranslatorInterface|null
|
||||
*/
|
||||
private $translator;
|
||||
|
||||
public function __construct(TokenStorageInterface $tokenStorage, AuthenticationManagerInterface $authenticationManager, HttpUtils $httpUtils, string $providerKey, AuthenticationSuccessHandlerInterface $successHandler = null, AuthenticationFailureHandlerInterface $failureHandler = null, array $options = [], LoggerInterface $logger = null, EventDispatcherInterface $eventDispatcher = null, PropertyAccessorInterface $propertyAccessor = null)
|
||||
{
|
||||
$this->tokenStorage = $tokenStorage;
|
||||
$this->authenticationManager = $authenticationManager;
|
||||
$this->httpUtils = $httpUtils;
|
||||
$this->providerKey = $providerKey;
|
||||
$this->successHandler = $successHandler;
|
||||
$this->failureHandler = $failureHandler;
|
||||
$this->logger = $logger;
|
||||
$this->eventDispatcher = $eventDispatcher;
|
||||
$this->options = array_merge(['username_path' => 'username', 'password_path' => 'password'], $options);
|
||||
$this->propertyAccessor = $propertyAccessor ?: PropertyAccess::createPropertyAccessor();
|
||||
}
|
||||
|
||||
public function supports(Request $request): ?bool
|
||||
{
|
||||
if (!str_contains($request->getRequestFormat() ?? '', 'json')
|
||||
&& !str_contains($request->getContentType() ?? '', 'json')
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isset($this->options['check_path']) && !$this->httpUtils->checkRequestPath($request, $this->options['check_path'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function authenticate(RequestEvent $event)
|
||||
{
|
||||
$request = $event->getRequest();
|
||||
$data = json_decode($request->getContent());
|
||||
|
||||
try {
|
||||
if (!$data instanceof \stdClass) {
|
||||
throw new BadRequestHttpException('Invalid JSON.');
|
||||
}
|
||||
|
||||
try {
|
||||
$username = $this->propertyAccessor->getValue($data, $this->options['username_path']);
|
||||
} catch (AccessException $e) {
|
||||
throw new BadRequestHttpException(sprintf('The key "%s" must be provided.', $this->options['username_path']), $e);
|
||||
}
|
||||
|
||||
try {
|
||||
$password = $this->propertyAccessor->getValue($data, $this->options['password_path']);
|
||||
} catch (AccessException $e) {
|
||||
throw new BadRequestHttpException(sprintf('The key "%s" must be provided.', $this->options['password_path']), $e);
|
||||
}
|
||||
|
||||
if (!\is_string($username)) {
|
||||
throw new BadRequestHttpException(sprintf('The key "%s" must be a string.', $this->options['username_path']));
|
||||
}
|
||||
|
||||
if (\strlen($username) > Security::MAX_USERNAME_LENGTH) {
|
||||
throw new BadCredentialsException('Invalid username.');
|
||||
}
|
||||
|
||||
if (!\is_string($password)) {
|
||||
throw new BadRequestHttpException(sprintf('The key "%s" must be a string.', $this->options['password_path']));
|
||||
}
|
||||
|
||||
$token = new UsernamePasswordToken($username, $password, $this->providerKey);
|
||||
|
||||
$authenticatedToken = $this->authenticationManager->authenticate($token);
|
||||
$response = $this->onSuccess($request, $authenticatedToken);
|
||||
} catch (AuthenticationException $e) {
|
||||
$response = $this->onFailure($request, $e);
|
||||
} catch (BadRequestHttpException $e) {
|
||||
$request->setRequestFormat('json');
|
||||
|
||||
throw $e;
|
||||
}
|
||||
|
||||
if (null === $response) {
|
||||
return;
|
||||
}
|
||||
|
||||
$event->setResponse($response);
|
||||
}
|
||||
|
||||
private function onSuccess(Request $request, TokenInterface $token): ?Response
|
||||
{
|
||||
if (null !== $this->logger) {
|
||||
// @deprecated since Symfony 5.3, change to $token->getUserIdentifier() in 6.0
|
||||
$this->logger->info('User has been authenticated successfully.', ['username' => method_exists($token, 'getUserIdentifier') ? $token->getUserIdentifier() : $token->getUsername()]);
|
||||
}
|
||||
|
||||
$this->migrateSession($request, $token);
|
||||
|
||||
$this->tokenStorage->setToken($token);
|
||||
|
||||
if (null !== $this->eventDispatcher) {
|
||||
$loginEvent = new InteractiveLoginEvent($request, $token);
|
||||
$this->eventDispatcher->dispatch($loginEvent, SecurityEvents::INTERACTIVE_LOGIN);
|
||||
}
|
||||
|
||||
if (!$this->successHandler) {
|
||||
return null; // let the original request succeeds
|
||||
}
|
||||
|
||||
$response = $this->successHandler->onAuthenticationSuccess($request, $token);
|
||||
|
||||
if (!$response instanceof Response) {
|
||||
throw new \RuntimeException('Authentication Success Handler did not return a Response.');
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
private function onFailure(Request $request, AuthenticationException $failed): Response
|
||||
{
|
||||
if (null !== $this->logger) {
|
||||
$this->logger->info('Authentication request failed.', ['exception' => $failed]);
|
||||
}
|
||||
|
||||
$token = $this->tokenStorage->getToken();
|
||||
if ($token instanceof UsernamePasswordToken && $this->providerKey === $token->getFirewallName()) {
|
||||
$this->tokenStorage->setToken(null);
|
||||
}
|
||||
|
||||
if (!$this->failureHandler) {
|
||||
if (null !== $this->translator) {
|
||||
$errorMessage = $this->translator->trans($failed->getMessageKey(), $failed->getMessageData(), 'security');
|
||||
} else {
|
||||
$errorMessage = strtr($failed->getMessageKey(), $failed->getMessageData());
|
||||
}
|
||||
|
||||
return new JsonResponse(['error' => $errorMessage], 401);
|
||||
}
|
||||
|
||||
$response = $this->failureHandler->onAuthenticationFailure($request, $failed);
|
||||
|
||||
if (!$response instanceof Response) {
|
||||
throw new \RuntimeException('Authentication Failure Handler did not return a Response.');
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Call this method if your authentication token is stored to a session.
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
public function setSessionAuthenticationStrategy(SessionAuthenticationStrategyInterface $sessionStrategy)
|
||||
{
|
||||
$this->sessionStrategy = $sessionStrategy;
|
||||
}
|
||||
|
||||
public function setTranslator(TranslatorInterface $translator)
|
||||
{
|
||||
$this->translator = $translator;
|
||||
}
|
||||
|
||||
private function migrateSession(Request $request, TokenInterface $token)
|
||||
{
|
||||
if (!$this->sessionStrategy || !$request->hasSession() || !$request->hasPreviousSession()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->sessionStrategy->onAuthentication($request, $token);
|
||||
}
|
||||
}
|
64
vendor/symfony/security-http/Firewall/X509AuthenticationListener.php
vendored
Normal file
64
vendor/symfony/security-http/Firewall/X509AuthenticationListener.php
vendored
Normal file
@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\Firewall;
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
|
||||
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
|
||||
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
|
||||
|
||||
trigger_deprecation('symfony/security-http', '5.3', 'The "%s" class is deprecated, use the new authenticator system instead.', X509AuthenticationListener::class);
|
||||
|
||||
/**
|
||||
* X509 authentication listener.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @deprecated since Symfony 5.3, use the new authenticator system instead
|
||||
*/
|
||||
class X509AuthenticationListener extends AbstractPreAuthenticatedListener
|
||||
{
|
||||
private $userKey;
|
||||
private $credentialKey;
|
||||
|
||||
public function __construct(TokenStorageInterface $tokenStorage, AuthenticationManagerInterface $authenticationManager, string $providerKey, string $userKey = 'SSL_CLIENT_S_DN_Email', string $credentialKey = 'SSL_CLIENT_S_DN', LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null)
|
||||
{
|
||||
parent::__construct($tokenStorage, $authenticationManager, $providerKey, $logger, $dispatcher);
|
||||
|
||||
$this->userKey = $userKey;
|
||||
$this->credentialKey = $credentialKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getPreAuthenticatedData(Request $request)
|
||||
{
|
||||
$user = null;
|
||||
if ($request->server->has($this->userKey)) {
|
||||
$user = $request->server->get($this->userKey);
|
||||
} elseif (
|
||||
$request->server->has($this->credentialKey)
|
||||
&& preg_match('#emailAddress=([^,/@]++@[^,/]++)#', $request->server->get($this->credentialKey), $matches)
|
||||
) {
|
||||
$user = $matches[1];
|
||||
}
|
||||
|
||||
if (null === $user) {
|
||||
throw new BadCredentialsException(sprintf('SSL credentials not found: "%s", "%s".', $this->userKey, $this->credentialKey));
|
||||
}
|
||||
|
||||
return [$user, $request->server->get($this->credentialKey, '')];
|
||||
}
|
||||
}
|
53
vendor/symfony/security-http/FirewallMap.php
vendored
Normal file
53
vendor/symfony/security-http/FirewallMap.php
vendored
Normal file
@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\RequestMatcherInterface;
|
||||
use Symfony\Component\Security\Http\Firewall\ExceptionListener;
|
||||
use Symfony\Component\Security\Http\Firewall\LogoutListener;
|
||||
|
||||
/**
|
||||
* FirewallMap allows configuration of different firewalls for specific parts
|
||||
* of the website.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class FirewallMap implements FirewallMapInterface
|
||||
{
|
||||
/**
|
||||
* @var list<array{RequestMatcherInterface, list<callable>, ExceptionListener|null, LogoutListener|null}>
|
||||
*/
|
||||
private $map = [];
|
||||
|
||||
/**
|
||||
* @param list<callable> $listeners
|
||||
*/
|
||||
public function add(RequestMatcherInterface $requestMatcher = null, array $listeners = [], ExceptionListener $exceptionListener = null, LogoutListener $logoutListener = null)
|
||||
{
|
||||
$this->map[] = [$requestMatcher, $listeners, $exceptionListener, $logoutListener];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getListeners(Request $request)
|
||||
{
|
||||
foreach ($this->map as $elements) {
|
||||
if (null === $elements[0] || $elements[0]->matches($request)) {
|
||||
return [$elements[1], $elements[2], $elements[3]];
|
||||
}
|
||||
}
|
||||
|
||||
return [[], null, null];
|
||||
}
|
||||
}
|
41
vendor/symfony/security-http/FirewallMapInterface.php
vendored
Normal file
41
vendor/symfony/security-http/FirewallMapInterface.php
vendored
Normal file
@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\Security\Http\Firewall\ExceptionListener;
|
||||
use Symfony\Component\Security\Http\Firewall\LogoutListener;
|
||||
|
||||
/**
|
||||
* This interface must be implemented by firewall maps.
|
||||
*
|
||||
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
|
||||
*/
|
||||
interface FirewallMapInterface
|
||||
{
|
||||
/**
|
||||
* Returns the authentication listeners, and the exception listener to use
|
||||
* for the given request.
|
||||
*
|
||||
* If there are no authentication listeners, the first inner array must be
|
||||
* empty.
|
||||
*
|
||||
* If there is no exception listener, the second element of the outer array
|
||||
* must be null.
|
||||
*
|
||||
* If there is no logout listener, the third element of the outer array
|
||||
* must be null.
|
||||
*
|
||||
* @return array{iterable<mixed, callable>, ExceptionListener, LogoutListener}
|
||||
*/
|
||||
public function getListeners(Request $request);
|
||||
}
|
180
vendor/symfony/security-http/HttpUtils.php
vendored
Normal file
180
vendor/symfony/security-http/HttpUtils.php
vendored
Normal file
@ -0,0 +1,180 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http;
|
||||
|
||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\Routing\Exception\MethodNotAllowedException;
|
||||
use Symfony\Component\Routing\Exception\ResourceNotFoundException;
|
||||
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
|
||||
use Symfony\Component\Routing\Matcher\RequestMatcherInterface;
|
||||
use Symfony\Component\Routing\Matcher\UrlMatcherInterface;
|
||||
use Symfony\Component\Security\Core\Security;
|
||||
|
||||
/**
|
||||
* Encapsulates the logic needed to create sub-requests, redirect the user, and match URLs.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class HttpUtils
|
||||
{
|
||||
private $urlGenerator;
|
||||
private $urlMatcher;
|
||||
private $domainRegexp;
|
||||
private $secureDomainRegexp;
|
||||
|
||||
/**
|
||||
* @param UrlMatcherInterface|RequestMatcherInterface $urlMatcher The URL or Request matcher
|
||||
* @param string|null $domainRegexp A regexp the target of HTTP redirections must match, scheme included
|
||||
* @param string|null $secureDomainRegexp A regexp the target of HTTP redirections must match when the scheme is "https"
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function __construct(UrlGeneratorInterface $urlGenerator = null, $urlMatcher = null, string $domainRegexp = null, string $secureDomainRegexp = null)
|
||||
{
|
||||
$this->urlGenerator = $urlGenerator;
|
||||
if (null !== $urlMatcher && !$urlMatcher instanceof UrlMatcherInterface && !$urlMatcher instanceof RequestMatcherInterface) {
|
||||
throw new \InvalidArgumentException('Matcher must either implement UrlMatcherInterface or RequestMatcherInterface.');
|
||||
}
|
||||
$this->urlMatcher = $urlMatcher;
|
||||
$this->domainRegexp = $domainRegexp;
|
||||
$this->secureDomainRegexp = $secureDomainRegexp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a redirect Response.
|
||||
*
|
||||
* @param string $path A path (an absolute path (/foo), an absolute URL (http://...), or a route name (foo))
|
||||
* @param int $status The status code
|
||||
*
|
||||
* @return RedirectResponse
|
||||
*/
|
||||
public function createRedirectResponse(Request $request, string $path, int $status = 302)
|
||||
{
|
||||
if (null !== $this->secureDomainRegexp && 'https' === $this->urlMatcher->getContext()->getScheme() && preg_match('#^https?:[/\\\\]{2,}+[^/]++#i', $path, $host) && !preg_match(sprintf($this->secureDomainRegexp, preg_quote($request->getHttpHost())), $host[0])) {
|
||||
$path = '/';
|
||||
}
|
||||
if (null !== $this->domainRegexp && preg_match('#^https?:[/\\\\]{2,}+[^/]++#i', $path, $host) && !preg_match(sprintf($this->domainRegexp, preg_quote($request->getHttpHost())), $host[0])) {
|
||||
$path = '/';
|
||||
}
|
||||
|
||||
return new RedirectResponse($this->generateUri($request, $path), $status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Request.
|
||||
*
|
||||
* @param string $path A path (an absolute path (/foo), an absolute URL (http://...), or a route name (foo))
|
||||
*
|
||||
* @return Request
|
||||
*/
|
||||
public function createRequest(Request $request, string $path)
|
||||
{
|
||||
$newRequest = Request::create($this->generateUri($request, $path), 'get', [], $request->cookies->all(), [], $request->server->all());
|
||||
|
||||
static $setSession;
|
||||
|
||||
if (null === $setSession) {
|
||||
$setSession = \Closure::bind(static function ($newRequest, $request) { $newRequest->session = $request->session; }, null, Request::class);
|
||||
}
|
||||
$setSession($newRequest, $request);
|
||||
|
||||
if ($request->attributes->has(Security::AUTHENTICATION_ERROR)) {
|
||||
$newRequest->attributes->set(Security::AUTHENTICATION_ERROR, $request->attributes->get(Security::AUTHENTICATION_ERROR));
|
||||
}
|
||||
if ($request->attributes->has(Security::ACCESS_DENIED_ERROR)) {
|
||||
$newRequest->attributes->set(Security::ACCESS_DENIED_ERROR, $request->attributes->get(Security::ACCESS_DENIED_ERROR));
|
||||
}
|
||||
if ($request->attributes->has(Security::LAST_USERNAME)) {
|
||||
$newRequest->attributes->set(Security::LAST_USERNAME, $request->attributes->get(Security::LAST_USERNAME));
|
||||
}
|
||||
|
||||
if ($request->get('_format')) {
|
||||
$newRequest->attributes->set('_format', $request->get('_format'));
|
||||
}
|
||||
if ($request->getDefaultLocale() !== $request->getLocale()) {
|
||||
$newRequest->setLocale($request->getLocale());
|
||||
}
|
||||
|
||||
return $newRequest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that a given path matches the Request.
|
||||
*
|
||||
* @param string $path A path (an absolute path (/foo), an absolute URL (http://...), or a route name (foo))
|
||||
*
|
||||
* @return bool true if the path is the same as the one from the Request, false otherwise
|
||||
*/
|
||||
public function checkRequestPath(Request $request, string $path)
|
||||
{
|
||||
if ('/' !== $path[0]) {
|
||||
try {
|
||||
// matching a request is more powerful than matching a URL path + context, so try that first
|
||||
if ($this->urlMatcher instanceof RequestMatcherInterface) {
|
||||
$parameters = $this->urlMatcher->matchRequest($request);
|
||||
} else {
|
||||
$parameters = $this->urlMatcher->match($request->getPathInfo());
|
||||
}
|
||||
|
||||
return isset($parameters['_route']) && $path === $parameters['_route'];
|
||||
} catch (MethodNotAllowedException $e) {
|
||||
return false;
|
||||
} catch (ResourceNotFoundException $e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return $path === rawurldecode($request->getPathInfo());
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a URI, based on the given path or absolute URL.
|
||||
*
|
||||
* @param string $path A path (an absolute path (/foo), an absolute URL (http://...), or a route name (foo))
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @throws \LogicException
|
||||
*/
|
||||
public function generateUri(Request $request, string $path)
|
||||
{
|
||||
if (str_starts_with($path, 'http') || !$path) {
|
||||
return $path;
|
||||
}
|
||||
|
||||
if ('/' === $path[0]) {
|
||||
return $request->getUriForPath($path);
|
||||
}
|
||||
|
||||
if (null === $this->urlGenerator) {
|
||||
throw new \LogicException('You must provide a UrlGeneratorInterface instance to be able to use routes.');
|
||||
}
|
||||
|
||||
$url = $this->urlGenerator->generate($path, $request->attributes->all(), UrlGeneratorInterface::ABSOLUTE_URL);
|
||||
|
||||
// unnecessary query string parameters must be removed from URL
|
||||
// (ie. query parameters that are presents in $attributes)
|
||||
// fortunately, they all are, so we have to remove entire query string
|
||||
$position = strpos($url, '?');
|
||||
if (false !== $position) {
|
||||
$fragment = parse_url($url, \PHP_URL_FRAGMENT);
|
||||
$url = substr($url, 0, $position);
|
||||
// fragment must be preserved
|
||||
if ($fragment) {
|
||||
$url .= "#$fragment";
|
||||
}
|
||||
}
|
||||
|
||||
return $url;
|
||||
}
|
||||
}
|
76
vendor/symfony/security-http/Impersonate/ImpersonateUrlGenerator.php
vendored
Normal file
76
vendor/symfony/security-http/Impersonate/ImpersonateUrlGenerator.php
vendored
Normal file
@ -0,0 +1,76 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\Impersonate;
|
||||
|
||||
use Symfony\Bundle\SecurityBundle\Security\FirewallMap;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\SwitchUserToken;
|
||||
use Symfony\Component\Security\Http\Firewall\SwitchUserListener;
|
||||
|
||||
/**
|
||||
* Provides generator functions for the impersonate url exit.
|
||||
*
|
||||
* @author Amrouche Hamza <hamza.simperfit@gmail.com>
|
||||
* @author Damien Fayet <damienf1521@gmail.com>
|
||||
*/
|
||||
class ImpersonateUrlGenerator
|
||||
{
|
||||
private $requestStack;
|
||||
private $tokenStorage;
|
||||
private $firewallMap;
|
||||
|
||||
public function __construct(RequestStack $requestStack, FirewallMap $firewallMap, TokenStorageInterface $tokenStorage)
|
||||
{
|
||||
$this->requestStack = $requestStack;
|
||||
$this->tokenStorage = $tokenStorage;
|
||||
$this->firewallMap = $firewallMap;
|
||||
}
|
||||
|
||||
public function generateExitPath(string $targetUri = null): string
|
||||
{
|
||||
return $this->buildExitPath($targetUri);
|
||||
}
|
||||
|
||||
public function generateExitUrl(string $targetUri = null): string
|
||||
{
|
||||
if (null === $request = $this->requestStack->getCurrentRequest()) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return $request->getUriForPath($this->buildExitPath($targetUri));
|
||||
}
|
||||
|
||||
private function isImpersonatedUser(): bool
|
||||
{
|
||||
return $this->tokenStorage->getToken() instanceof SwitchUserToken;
|
||||
}
|
||||
|
||||
private function buildExitPath(string $targetUri = null): string
|
||||
{
|
||||
if (null === ($request = $this->requestStack->getCurrentRequest()) || !$this->isImpersonatedUser()) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (null === $switchUserConfig = $this->firewallMap->getFirewallConfig($request)->getSwitchUser()) {
|
||||
throw new \LogicException('Unable to generate the impersonate exit URL without a firewall configured for the user switch.');
|
||||
}
|
||||
|
||||
if (null === $targetUri) {
|
||||
$targetUri = $request->getRequestUri();
|
||||
}
|
||||
|
||||
$targetUri .= (parse_url($targetUri, \PHP_URL_QUERY) ? '&' : '?').http_build_query([$switchUserConfig['parameter'] => SwitchUserListener::EXIT_VALUE], '', '&');
|
||||
|
||||
return $targetUri;
|
||||
}
|
||||
}
|
19
vendor/symfony/security-http/LICENSE
vendored
Normal file
19
vendor/symfony/security-http/LICENSE
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
Copyright (c) 2004-2022 Fabien Potencier
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is furnished
|
||||
to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
21
vendor/symfony/security-http/LoginLink/Exception/ExpiredLoginLinkException.php
vendored
Normal file
21
vendor/symfony/security-http/LoginLink/Exception/ExpiredLoginLinkException.php
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\LoginLink\Exception;
|
||||
|
||||
use Symfony\Component\Security\Core\Signature\Exception\ExpiredSignatureException;
|
||||
|
||||
/**
|
||||
* @author Ryan Weaver <ryan@symfonycasts.com>
|
||||
*/
|
||||
class ExpiredLoginLinkException extends ExpiredSignatureException implements InvalidLoginLinkExceptionInterface
|
||||
{
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user