login consent app sql

This commit is contained in:
2022-05-03 08:54:45 +02:00
parent e7253acfd8
commit f9a6535906
1652 changed files with 187600 additions and 45 deletions

View File

@ -0,0 +1,40 @@
<?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\Guard;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Guard\Token\PostAuthenticationGuardToken;
/**
* An optional base class that creates a PostAuthenticationGuardToken for you.
*
* @author Ryan Weaver <ryan@knpuniversity.com>
*
* @deprecated since Symfony 5.3, use the new authenticator system instead
*/
abstract class AbstractGuardAuthenticator implements AuthenticatorInterface
{
/**
* Shortcut to create a PostAuthenticationGuardToken for you, if you don't really
* care about which authenticated token you're using.
*
* @return PostAuthenticationGuardToken
*/
public function createAuthenticatedToken(UserInterface $user, string $providerKey)
{
return new PostAuthenticationGuardToken(
$user,
$providerKey,
$user->getRoles()
);
}
}

View File

@ -0,0 +1,69 @@
<?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\Guard\Authenticator;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Security\Guard\AbstractGuardAuthenticator;
/**
* A base class to make form login authentication easier!
*
* @author Ryan Weaver <ryan@knpuniversity.com>
*
* @deprecated since Symfony 5.3, use the new authenticator system instead
*/
abstract class AbstractFormLoginAuthenticator extends AbstractGuardAuthenticator
{
/**
* Return the URL to the login page.
*
* @return string
*/
abstract protected function getLoginUrl();
/**
* Override to change what happens after a bad username/password is submitted.
*
* @return RedirectResponse
*/
public function onAuthenticationFailure(Request $request, AuthenticationException $exception)
{
if ($request->hasSession()) {
$request->getSession()->set(Security::AUTHENTICATION_ERROR, $exception);
}
$url = $this->getLoginUrl();
return new RedirectResponse($url);
}
public function supportsRememberMe()
{
return true;
}
/**
* Override to control what happens when the user hits a secure page
* but isn't logged in yet.
*
* @return RedirectResponse
*/
public function start(Request $request, AuthenticationException $authException = null)
{
$url = $this->getLoginUrl();
return new RedirectResponse($url);
}
}

View File

@ -0,0 +1,147 @@
<?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\Guard\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\Core\Exception\UserNotFoundException;
use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
use Symfony\Component\Security\Core\User\PasswordUpgraderInterface;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Guard\AuthenticatorInterface as GuardAuthenticatorInterface;
use Symfony\Component\Security\Guard\PasswordAuthenticatedInterface;
use Symfony\Component\Security\Http\Authenticator\InteractiveAuthenticatorInterface;
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\CustomCredentials;
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\EntryPoint\AuthenticationEntryPointInterface;
trigger_deprecation('symfony/security-guard', '5.3', 'The "%s" class is deprecated, use the new authenticator system instead.', GuardBridgeAuthenticator::class);
/**
* This authenticator is used to bridge Guard authenticators with
* the Symfony Authenticator system.
*
* @author Wouter de Jong <wouter@wouterj.nl>
*
* @deprecated since Symfony 5.3
*/
class GuardBridgeAuthenticator implements InteractiveAuthenticatorInterface, AuthenticationEntryPointInterface
{
private $guard;
private $userProvider;
public function __construct(GuardAuthenticatorInterface $guard, UserProviderInterface $userProvider)
{
$this->guard = $guard;
$this->userProvider = $userProvider;
}
public function start(Request $request, AuthenticationException $authException = null)
{
return $this->guard->start($request, $authException);
}
public function supports(Request $request): ?bool
{
return $this->guard->supports($request);
}
public function authenticate(Request $request): PassportInterface
{
$credentials = $this->guard->getCredentials($request);
if (null === $credentials) {
throw new \UnexpectedValueException(sprintf('The return value of "%1$s::getCredentials()" must not be null. Return false from "%1$s::supports()" instead.', get_debug_type($this->guard)));
}
// get the user from the GuardAuthenticator
if (class_exists(UserBadge::class)) {
$user = new UserBadge('guard_authenticator_'.md5(serialize($credentials)), function () use ($credentials) { return $this->getUser($credentials); });
} else {
// BC with symfony/security-http:5.1
$user = $this->getUser($credentials);
}
if ($this->guard instanceof PasswordAuthenticatedInterface && !$user instanceof PasswordAuthenticatedUserInterface) {
trigger_deprecation('symfony/security-guard', '5.3', 'Not implementing the "%s" interface in class "%s" while using password-based guard authenticators is deprecated.', PasswordAuthenticatedUserInterface::class, get_debug_type($user));
}
$passport = new Passport($user, new CustomCredentials([$this->guard, 'checkCredentials'], $credentials));
if ($this->userProvider instanceof PasswordUpgraderInterface && $this->guard instanceof PasswordAuthenticatedInterface && (null !== $password = $this->guard->getPassword($credentials))) {
$passport->addBadge(new PasswordUpgradeBadge($password, $this->userProvider));
}
if ($this->guard->supportsRememberMe()) {
$passport->addBadge(new RememberMeBadge());
}
return $passport;
}
public function getGuardAuthenticator(): GuardAuthenticatorInterface
{
return $this->guard;
}
private function getUser($credentials): UserInterface
{
$user = $this->guard->getUser($credentials, $this->userProvider);
if (null === $user) {
throw new UserNotFoundException(sprintf('Null returned from "%s::getUser()".', get_debug_type($this->guard)));
}
if (!$user instanceof UserInterface) {
throw new \UnexpectedValueException(sprintf('The "%s::getUser()" method must return a UserInterface. You returned "%s".', get_debug_type($this->guard), get_debug_type($user)));
}
return $user;
}
public function createAuthenticatedToken(PassportInterface $passport, string $firewallName): TokenInterface
{
if (!$passport instanceof UserPassportInterface) {
throw new \LogicException(sprintf('"%s" does not support non-user passports.', __CLASS__));
}
return $this->guard->createAuthenticatedToken($passport->getUser(), $firewallName);
}
public function createToken(Passport $passport, string $firewallName): TokenInterface
{
return $this->guard->createAuthenticatedToken($passport->getUser(), $firewallName);
}
public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response
{
return $this->guard->onAuthenticationSuccess($request, $token, $firewallName);
}
public function onAuthenticationFailure(Request $request, AuthenticationException $exception): ?Response
{
return $this->guard->onAuthenticationFailure($request, $exception);
}
public function isInteractive(): bool
{
// the GuardAuthenticationHandler always dispatches the InteractiveLoginEvent
return true;
}
}

View File

@ -0,0 +1,155 @@
<?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\Guard;
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\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Guard\Token\GuardTokenInterface;
use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface;
/**
* The interface for all "guard" authenticators.
*
* The methods on this interface are called throughout the guard authentication
* process to give you the power to control most parts of the process from
* one location.
*
* @author Ryan Weaver <ryan@knpuniversity.com>
* @author Amaury Leroux de Lens <amaury@lerouxdelens.com>
*
* @deprecated since Symfony 5.3, use the new authenticator system instead
*/
interface AuthenticatorInterface extends AuthenticationEntryPointInterface
{
/**
* Does the authenticator support the given Request?
*
* If this returns false, the authenticator will be skipped.
*
* @return bool
*/
public function supports(Request $request);
/**
* Get the authentication credentials from the request and return them
* as any type (e.g. an associate array).
*
* Whatever value you return here will be passed to getUser() and checkCredentials()
*
* For example, for a form login, you might:
*
* return [
* 'username' => $request->request->get('_username'),
* 'password' => $request->request->get('_password'),
* ];
*
* Or for an API token that's on a header, you might use:
*
* return ['api_key' => $request->headers->get('X-API-TOKEN')];
*
* @return mixed Any non-null value
*
* @throws \UnexpectedValueException If null is returned
*/
public function getCredentials(Request $request);
/**
* Return a UserInterface object based on the credentials.
*
* The *credentials* are the return value from getCredentials()
*
* You may throw an AuthenticationException if you wish. If you return
* null, then a UserNotFoundException is thrown for you.
*
* @param mixed $credentials
*
* @throws AuthenticationException
*
* @return UserInterface|null
*/
public function getUser($credentials, UserProviderInterface $userProvider);
/**
* Returns true if the credentials are valid.
*
* If false is returned, authentication will fail. You may also throw
* an AuthenticationException if you wish to cause authentication to fail.
*
* The *credentials* are the return value from getCredentials()
*
* @param mixed $credentials
*
* @return bool
*
* @throws AuthenticationException
*/
public function checkCredentials($credentials, UserInterface $user);
/**
* 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 AbstractGuardAuthenticator class from your authenticator.
*
* @see AbstractGuardAuthenticator
*
* @return GuardTokenInterface
*/
public function createAuthenticatedToken(UserInterface $user, string $providerKey);
/**
* 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 401 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.
*
* @return Response|null
*/
public function onAuthenticationFailure(Request $request, AuthenticationException $exception);
/**
* 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.
*
* @return Response|null
*/
public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $providerKey);
/**
* Does this method support remember me cookies?
*
* Remember me cookie will be set if *all* of the following are met:
* A) This method returns true
* 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
* D) The onAuthenticationSuccess method returns a Response object
*
* @return bool
*/
public function supportsRememberMe();
}

View File

@ -0,0 +1,7 @@
CHANGELOG
=========
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

View File

@ -0,0 +1,242 @@
<?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\Guard\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\TokenInterface;
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\Guard\AuthenticatorInterface;
use Symfony\Component\Security\Guard\GuardAuthenticatorHandler;
use Symfony\Component\Security\Guard\Token\PreAuthenticationGuardToken;
use Symfony\Component\Security\Http\Firewall\AbstractListener;
use Symfony\Component\Security\Http\RememberMe\RememberMeServicesInterface;
trigger_deprecation('symfony/security-guard', '5.3', 'The "%s" class is deprecated, use the new authenticator system instead.', GuardAuthenticationListener::class);
/**
* Authentication listener for the "guard" system.
*
* @author Ryan Weaver <ryan@knpuniversity.com>
* @author Amaury Leroux de Lens <amaury@lerouxdelens.com>
*
* @final
*
* @deprecated since Symfony 5.3, use the new authenticator system instead
*/
class GuardAuthenticationListener extends AbstractListener
{
private $guardHandler;
private $authenticationManager;
private $providerKey;
private $guardAuthenticators;
private $logger;
private $rememberMeServices;
private $hideUserNotFoundExceptions;
/**
* @param string $providerKey The provider (i.e. firewall) key
* @param iterable<array-key, AuthenticatorInterface> $guardAuthenticators The authenticators, with keys that match what's passed to GuardAuthenticationProvider
*/
public function __construct(GuardAuthenticatorHandler $guardHandler, AuthenticationManagerInterface $authenticationManager, string $providerKey, iterable $guardAuthenticators, LoggerInterface $logger = null, bool $hideUserNotFoundExceptions = true)
{
if (empty($providerKey)) {
throw new \InvalidArgumentException('$providerKey must not be empty.');
}
$this->guardHandler = $guardHandler;
$this->authenticationManager = $authenticationManager;
$this->providerKey = $providerKey;
$this->guardAuthenticators = $guardAuthenticators;
$this->logger = $logger;
$this->hideUserNotFoundExceptions = $hideUserNotFoundExceptions;
}
/**
* {@inheritdoc}
*/
public function supports(Request $request): ?bool
{
if (null !== $this->logger) {
$context = ['firewall_key' => $this->providerKey];
if ($this->guardAuthenticators instanceof \Countable || \is_array($this->guardAuthenticators)) {
$context['authenticators'] = \count($this->guardAuthenticators);
}
$this->logger->debug('Checking for guard authentication credentials.', $context);
}
$guardAuthenticators = [];
foreach ($this->guardAuthenticators as $key => $guardAuthenticator) {
if (null !== $this->logger) {
$this->logger->debug('Checking support on guard authenticator.', ['firewall_key' => $this->providerKey, 'authenticator' => \get_class($guardAuthenticator)]);
}
if ($guardAuthenticator->supports($request)) {
$guardAuthenticators[$key] = $guardAuthenticator;
} elseif (null !== $this->logger) {
$this->logger->debug('Guard authenticator does not support the request.', ['firewall_key' => $this->providerKey, 'authenticator' => \get_class($guardAuthenticator)]);
}
}
if (!$guardAuthenticators) {
return false;
}
$request->attributes->set('_guard_authenticators', $guardAuthenticators);
return true;
}
/**
* Iterates over each authenticator to see if each wants to authenticate the request.
*/
public function authenticate(RequestEvent $event)
{
$request = $event->getRequest();
$guardAuthenticators = $request->attributes->get('_guard_authenticators');
$request->attributes->remove('_guard_authenticators');
foreach ($guardAuthenticators as $key => $guardAuthenticator) {
// get a key that's unique to *this* guard authenticator
// this MUST be the same as GuardAuthenticationProvider
$uniqueGuardKey = $this->providerKey.'_'.$key;
$this->executeGuardAuthenticator($uniqueGuardKey, $guardAuthenticator, $event);
if ($event->hasResponse()) {
if (null !== $this->logger) {
$this->logger->debug('The "{authenticator}" authenticator set the response. Any later authenticator will not be called', ['authenticator' => \get_class($guardAuthenticator)]);
}
break;
}
}
}
private function executeGuardAuthenticator(string $uniqueGuardKey, AuthenticatorInterface $guardAuthenticator, RequestEvent $event)
{
$request = $event->getRequest();
try {
if (null !== $this->logger) {
$this->logger->debug('Calling getCredentials() on guard authenticator.', ['firewall_key' => $this->providerKey, 'authenticator' => \get_class($guardAuthenticator)]);
}
// allow the authenticator to fetch authentication info from the request
$credentials = $guardAuthenticator->getCredentials($request);
if (null === $credentials) {
throw new \UnexpectedValueException(sprintf('The return value of "%1$s::getCredentials()" must not be null. Return false from "%1$s::supports()" instead.', get_debug_type($guardAuthenticator)));
}
// create a token with the unique key, so that the provider knows which authenticator to use
$token = new PreAuthenticationGuardToken($credentials, $uniqueGuardKey);
if (null !== $this->logger) {
$this->logger->debug('Passing guard token information to the GuardAuthenticationProvider', ['firewall_key' => $this->providerKey, 'authenticator' => \get_class($guardAuthenticator)]);
}
// pass the token into the AuthenticationManager system
// this indirectly calls GuardAuthenticationProvider::authenticate()
$token = $this->authenticationManager->authenticate($token);
if (null !== $this->logger) {
$this->logger->info('Guard authentication successful!', ['token' => $token, 'authenticator' => \get_class($guardAuthenticator)]);
}
// sets the token on the token storage, etc
$this->guardHandler->authenticateWithToken($token, $request, $this->providerKey);
} catch (AuthenticationException $e) {
// oh no! Authentication failed!
if (null !== $this->logger) {
$this->logger->info('Guard authentication failed.', ['exception' => $e, 'authenticator' => \get_class($guardAuthenticator)]);
}
// 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
if ($this->hideUserNotFoundExceptions && ($e instanceof UsernameNotFoundException || ($e instanceof AccountStatusException && !$e instanceof CustomUserMessageAccountStatusException))) {
$e = new BadCredentialsException('Bad credentials.', 0, $e);
}
$response = $this->guardHandler->handleAuthenticationFailure($e, $request, $guardAuthenticator, $this->providerKey);
if ($response instanceof Response) {
$event->setResponse($response);
}
return;
}
// success!
$response = $this->guardHandler->handleAuthenticationSuccess($token, $request, $guardAuthenticator, $this->providerKey);
if ($response instanceof Response) {
if (null !== $this->logger) {
$this->logger->debug('Guard authenticator set success response.', ['response' => $response, 'authenticator' => \get_class($guardAuthenticator)]);
}
$event->setResponse($response);
} else {
if (null !== $this->logger) {
$this->logger->debug('Guard authenticator set no success response: request continues.', ['authenticator' => \get_class($guardAuthenticator)]);
}
}
// attempt to trigger the remember me functionality
$this->triggerRememberMe($guardAuthenticator, $request, $token, $response);
}
/**
* Should be called if this listener will support remember me.
*/
public function setRememberMeServices(RememberMeServicesInterface $rememberMeServices)
{
$this->rememberMeServices = $rememberMeServices;
}
/**
* Checks to see if remember me is supported in the authenticator and
* on the firewall. If it is, the RememberMeServicesInterface is notified.
*/
private function triggerRememberMe(AuthenticatorInterface $guardAuthenticator, Request $request, TokenInterface $token, Response $response = null)
{
if (null === $this->rememberMeServices) {
if (null !== $this->logger) {
$this->logger->debug('Remember me skipped: it is not configured for the firewall.', ['authenticator' => \get_class($guardAuthenticator)]);
}
return;
}
if (!$guardAuthenticator->supportsRememberMe()) {
if (null !== $this->logger) {
$this->logger->debug('Remember me skipped: your authenticator does not support it.', ['authenticator' => \get_class($guardAuthenticator)]);
}
return;
}
if (!$response instanceof Response) {
throw new \LogicException(sprintf('"%s::onAuthenticationSuccess()" *must* return a Response if you want to use the remember me functionality. Return a Response, or set remember_me to false under the guard configuration.', get_debug_type($guardAuthenticator)));
}
$this->rememberMeServices->loginSuccess($request, $response, $token);
}
}

View File

@ -0,0 +1,133 @@
<?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\Guard;
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\Exception\AuthenticationException;
use Symfony\Component\Security\Core\User\UserInterface;
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-guard', '5.3', 'The "%s" class is deprecated, use the new authenticator system instead.', GuardAuthenticatorHandler::class);
/**
* A utility class that does much of the *work* during the guard authentication process.
*
* By having the logic here instead of the listener, more of the process
* can be called directly (e.g. for manual authentication) or overridden.
*
* @author Ryan Weaver <ryan@knpuniversity.com>
*
* @final
*
* @deprecated since Symfony 5.3, use the new authenticator system instead
*/
class GuardAuthenticatorHandler
{
private $tokenStorage;
private $dispatcher;
private $sessionStrategy;
private $statelessProviderKeys;
/**
* @param array $statelessProviderKeys An array of provider/firewall keys that are "stateless" and so do not need the session migrated on success
*/
public function __construct(TokenStorageInterface $tokenStorage, EventDispatcherInterface $eventDispatcher = null, array $statelessProviderKeys = [])
{
$this->tokenStorage = $tokenStorage;
$this->dispatcher = $eventDispatcher;
$this->statelessProviderKeys = $statelessProviderKeys;
}
/**
* Authenticates the given token in the system.
*/
public function authenticateWithToken(TokenInterface $token, Request $request, string $providerKey = null)
{
$this->migrateSession($request, $token, $providerKey);
$this->tokenStorage->setToken($token);
if (null !== $this->dispatcher) {
$loginEvent = new InteractiveLoginEvent($request, $token);
$this->dispatcher->dispatch($loginEvent, SecurityEvents::INTERACTIVE_LOGIN);
}
}
/**
* Returns the "on success" response for the given GuardAuthenticator.
*/
public function handleAuthenticationSuccess(TokenInterface $token, Request $request, AuthenticatorInterface $guardAuthenticator, string $providerKey): ?Response
{
$response = $guardAuthenticator->onAuthenticationSuccess($request, $token, $providerKey);
// check that it's a Response or null
if ($response instanceof Response || null === $response) {
return $response;
}
throw new \UnexpectedValueException(sprintf('The "%s::onAuthenticationSuccess()" method must return null or a Response object. You returned "%s".', \get_class($guardAuthenticator), get_debug_type($response)));
}
/**
* Convenience method for authenticating the user and returning the
* Response *if any* for success.
*/
public function authenticateUserAndHandleSuccess(UserInterface $user, Request $request, AuthenticatorInterface $authenticator, string $providerKey): ?Response
{
// create an authenticated token for the User
$token = $authenticator->createAuthenticatedToken($user, $providerKey);
// authenticate this in the system
$this->authenticateWithToken($token, $request, $providerKey);
// return the success metric
return $this->handleAuthenticationSuccess($token, $request, $authenticator, $providerKey);
}
/**
* Handles an authentication failure and returns the Response for the
* GuardAuthenticator.
*/
public function handleAuthenticationFailure(AuthenticationException $authenticationException, Request $request, AuthenticatorInterface $guardAuthenticator, string $providerKey): ?Response
{
$response = $guardAuthenticator->onAuthenticationFailure($request, $authenticationException);
if ($response instanceof Response || null === $response) {
// returning null is ok, it means they want the request to continue
return $response;
}
throw new \UnexpectedValueException(sprintf('The "%s::onAuthenticationFailure()" method must return null or a Response object. You returned "%s".', \get_class($guardAuthenticator), get_debug_type($response)));
}
/**
* 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, ?string $providerKey)
{
if (\in_array($providerKey, $this->statelessProviderKeys, true) || !$this->sessionStrategy || !$request->hasSession() || !$request->hasPreviousSession()) {
return;
}
$this->sessionStrategy->onAuthentication($request, $token);
}
}

19
vendor/symfony/security-guard/LICENSE vendored Normal file
View 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.

View File

@ -0,0 +1,29 @@
<?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\Guard;
trigger_deprecation('symfony/security-guard', '5.3', 'The "%s" class is deprecated, use the new authenticator system instead.', PasswordAuthenticatedInterface::class);
/**
* An optional interface for "guard" authenticators that deal with user passwords.
*
* @deprecated since Symfony 5.3, use the new authenticator system instead
*/
interface PasswordAuthenticatedInterface
{
/**
* Returns the clear-text password contained in credentials if any.
*
* @param mixed $credentials The user credentials
*/
public function getPassword($credentials): ?string;
}

View File

@ -0,0 +1,185 @@
<?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\Guard\Provider;
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
use Symfony\Component\Security\Core\Authentication\Provider\AuthenticationProviderInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\Exception\AuthenticationExpiredException;
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
use Symfony\Component\Security\Core\Exception\UserNotFoundException;
use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
use Symfony\Component\Security\Core\User\PasswordUpgraderInterface;
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\Guard\AuthenticatorInterface;
use Symfony\Component\Security\Guard\PasswordAuthenticatedInterface;
use Symfony\Component\Security\Guard\Token\GuardTokenInterface;
use Symfony\Component\Security\Guard\Token\PreAuthenticationGuardToken;
trigger_deprecation('symfony/security-guard', '5.3', 'The "%s" class is deprecated, use the new authenticator system instead.', GuardAuthenticationProvider::class);
/**
* Responsible for accepting the PreAuthenticationGuardToken and calling
* the correct authenticator to retrieve the authenticated token.
*
* @author Ryan Weaver <ryan@knpuniversity.com>
*
* @deprecated since Symfony 5.3, use the new authenticator system instead
*/
class GuardAuthenticationProvider implements AuthenticationProviderInterface
{
private $guardAuthenticators;
private $userProvider;
private $providerKey;
private $userChecker;
private $passwordHasher;
/**
* @param iterable<array-key, AuthenticatorInterface> $guardAuthenticators The authenticators, with keys that match what's passed to GuardAuthenticationListener
* @param string $providerKey The provider (i.e. firewall) key
* @param UserPasswordHasherInterface $passwordHasher
*/
public function __construct(iterable $guardAuthenticators, UserProviderInterface $userProvider, string $providerKey, UserCheckerInterface $userChecker, $passwordHasher = null)
{
$this->guardAuthenticators = $guardAuthenticators;
$this->userProvider = $userProvider;
$this->providerKey = $providerKey;
$this->userChecker = $userChecker;
$this->passwordHasher = $passwordHasher;
if ($passwordHasher instanceof UserPasswordEncoderInterface) {
trigger_deprecation('symfony/security-core', '5.3', sprintf('Passing a "%s" instance to the "%s" constructor is deprecated, use "%s" instead.', UserPasswordEncoderInterface::class, __CLASS__, UserPasswordHasherInterface::class));
}
}
/**
* Finds the correct authenticator for the token and calls it.
*
* @param GuardTokenInterface $token
*
* @return TokenInterface
*/
public function authenticate(TokenInterface $token)
{
if (!$token instanceof GuardTokenInterface) {
throw new \InvalidArgumentException('GuardAuthenticationProvider only supports GuardTokenInterface.');
}
if (!$token instanceof PreAuthenticationGuardToken) {
/*
* The listener *only* passes PreAuthenticationGuardToken instances.
* This means that an authenticated token (e.g. PostAuthenticationGuardToken)
* is being passed here, which happens if that token becomes
* "not authenticated" (e.g. happens if the user changes between
* requests). In this case, the user should be logged out, so
* we will return an AnonymousToken to accomplish that.
*/
// this should never happen - but technically, the token is
// authenticated... so it could just be returned
if ($token->isAuthenticated(false)) {
return $token;
}
// this causes the user to be logged out
throw new AuthenticationExpiredException();
}
$guardAuthenticator = $this->findOriginatingAuthenticator($token);
if (null === $guardAuthenticator) {
throw new AuthenticationException(sprintf('Token with provider key "%s" did not originate from any of the guard authenticators of provider "%s".', $token->getGuardProviderKey(), $this->providerKey));
}
return $this->authenticateViaGuard($guardAuthenticator, $token);
}
private function authenticateViaGuard(AuthenticatorInterface $guardAuthenticator, PreAuthenticationGuardToken $token): GuardTokenInterface
{
// get the user from the GuardAuthenticator
$user = $guardAuthenticator->getUser($token->getCredentials(), $this->userProvider);
if (null === $user) {
$e = new UserNotFoundException(sprintf('Null returned from "%s::getUser()".', get_debug_type($guardAuthenticator)));
// @deprecated since Symfony 5.3, change to $token->getUserIdentifier() in 6.0
$e->setUserIdentifier(method_exists($token, 'getUserIdentifier') ? $token->getUserIdentifier() : $token->getUsername());
throw $e;
}
if (!$user instanceof UserInterface) {
throw new \UnexpectedValueException(sprintf('The "%s::getUser()" method must return a UserInterface. You returned "%s".', get_debug_type($guardAuthenticator), get_debug_type($user)));
}
if ($guardAuthenticator instanceof PasswordAuthenticatedInterface && !$user instanceof PasswordAuthenticatedUserInterface) {
trigger_deprecation('symfony/security-guard', '5.3', 'Not implementing the "%s" interface in class "%s" while using password-based guard authenticators is deprecated.', PasswordAuthenticatedUserInterface::class, get_debug_type($user));
}
$this->userChecker->checkPreAuth($user);
if (true !== $checkCredentialsResult = $guardAuthenticator->checkCredentials($token->getCredentials(), $user)) {
if (false !== $checkCredentialsResult) {
throw new \TypeError(sprintf('"%s::checkCredentials()" must return a boolean value.', get_debug_type($guardAuthenticator)));
}
throw new BadCredentialsException(sprintf('Authentication failed because "%s::checkCredentials()" did not return true.', get_debug_type($guardAuthenticator)));
}
if ($this->userProvider instanceof PasswordUpgraderInterface && $guardAuthenticator instanceof PasswordAuthenticatedInterface && null !== $this->passwordHasher && (null !== $password = $guardAuthenticator->getPassword($token->getCredentials())) && $this->passwordHasher->needsRehash($user)) {
if ($this->passwordHasher instanceof UserPasswordEncoderInterface) {
// @deprecated since Symfony 5.3
$this->userProvider->upgradePassword($user, $this->passwordHasher->encodePassword($user, $password));
} else {
$this->userProvider->upgradePassword($user, $this->passwordHasher->hashPassword($user, $password));
}
}
$this->userChecker->checkPostAuth($user);
// turn the UserInterface into a TokenInterface
$authenticatedToken = $guardAuthenticator->createAuthenticatedToken($user, $this->providerKey);
if (!$authenticatedToken instanceof TokenInterface) {
throw new \UnexpectedValueException(sprintf('The "%s::createAuthenticatedToken()" method must return a TokenInterface. You returned "%s".', get_debug_type($guardAuthenticator), get_debug_type($authenticatedToken)));
}
return $authenticatedToken;
}
private function findOriginatingAuthenticator(PreAuthenticationGuardToken $token): ?AuthenticatorInterface
{
// find the *one* GuardAuthenticator that this token originated from
foreach ($this->guardAuthenticators as $key => $guardAuthenticator) {
// get a key that's unique to *this* guard authenticator
// this MUST be the same as GuardAuthenticationListener
$uniqueGuardKey = $this->providerKey.'_'.$key;
if ($uniqueGuardKey === $token->getGuardProviderKey()) {
return $guardAuthenticator;
}
}
// no matching authenticator found - but there will be multiple GuardAuthenticationProvider
// instances that will be checked if you have multiple firewalls.
return null;
}
public function supports(TokenInterface $token)
{
if ($token instanceof PreAuthenticationGuardToken) {
return null !== $this->findOriginatingAuthenticator($token);
}
return $token instanceof GuardTokenInterface;
}
}

30
vendor/symfony/security-guard/README.md vendored Normal file
View File

@ -0,0 +1,30 @@
Security Component - Guard
==========================
The Guard component brings many layers of authentication together, making
it much easier to create complex authentication systems where you have
total control.
Sponsor
-------
The Security component for Symfony 5.4/6.0 is [backed][1] by [SymfonyCasts][2].
Learn Symfony faster by watching real projects being built and actively coding
along with them. SymfonyCasts bridges that learning gap, bringing you video
tutorials and coding challenges. Code on!
Help Symfony by [sponsoring][3] its development!
Resources
---------
* [Documentation](https://symfony.com/doc/current/components/security.html)
* [Contributing](https://symfony.com/doc/current/contributing/index.html)
* [Report issues](https://github.com/symfony/symfony/issues) and
[send Pull Requests](https://github.com/symfony/symfony/pulls)
in the [main Symfony repository](https://github.com/symfony/symfony)
[1]: https://symfony.com/backers
[2]: https://symfonycasts.com
[3]: https://symfony.com/sponsor

View 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\Guard\Token;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
trigger_deprecation('symfony/security-guard', '5.3', 'The "%s" class is deprecated, use the new authenticator system instead.', GuardTokenInterface::class);
/**
* A marker interface that both guard tokens implement.
*
* Any tokens passed to GuardAuthenticationProvider (i.e. any tokens that
* are handled by the guard auth system) must implement this
* interface.
*
* @author Ryan Weaver <ryan@knpuniversity.com>
*
* @deprecated since Symfony 5.3, use the new authenticator system instead
*/
interface GuardTokenInterface extends TokenInterface
{
}

View File

@ -0,0 +1,98 @@
<?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\Guard\Token;
use Symfony\Component\Security\Core\Authentication\Token\AbstractToken;
use Symfony\Component\Security\Core\User\UserInterface;
trigger_deprecation('symfony/security-guard', '5.3', 'The "%s" class is deprecated, use the new authenticator system instead.', PostAuthenticationGuardToken::class);
/**
* Used as an "authenticated" token, though it could be set to not-authenticated later.
*
* If you're using Guard authentication, you *must* use a class that implements
* GuardTokenInterface as your authenticated token (like this class).
*
* @author Ryan Weaver <ryan@knpuniversity.com>
*
* @deprecated since Symfony 5.3, use the new authenticator system instead
*/
class PostAuthenticationGuardToken extends AbstractToken implements GuardTokenInterface
{
private $providerKey;
/**
* @param string $providerKey The provider (firewall) key
* @param string[] $roles An array of roles
*
* @throws \InvalidArgumentException
*/
public function __construct(UserInterface $user, string $providerKey, array $roles)
{
parent::__construct($roles);
if (empty($providerKey)) {
throw new \InvalidArgumentException('$providerKey (i.e. firewall key) must not be empty.');
}
$this->setUser($user);
$this->providerKey = $providerKey;
// this token is meant to be used after authentication success, so it is always authenticated
// you could set it as non authenticated later if you need to
$this->setAuthenticated(true, false);
}
/**
* This is meant to be only an authenticated token, where credentials
* have already been used and are thus cleared.
*
* {@inheritdoc}
*/
public function getCredentials()
{
return [];
}
/**
* Returns the provider (firewall) key.
*
* @return string
*/
public function getProviderKey()
{
return $this->providerKey;
}
public function getFirewallName(): string
{
return $this->getProviderKey();
}
/**
* {@inheritdoc}
*/
public function __serialize(): array
{
return [$this->providerKey, parent::__serialize()];
}
/**
* {@inheritdoc}
*/
public function __unserialize(array $data): void
{
[$this->providerKey, $parentData] = $data;
$parentData = \is_array($parentData) ? $parentData : unserialize($parentData);
parent::__unserialize($parentData);
}
}

View File

@ -0,0 +1,72 @@
<?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\Guard\Token;
use Symfony\Component\Security\Core\Authentication\Token\AbstractToken;
trigger_deprecation('symfony/security-guard', '5.3', 'The "%s" class is deprecated, use the new authenticator system instead.', PreAuthenticationGuardToken::class);
/**
* The token used by the guard auth system before authentication.
*
* The GuardAuthenticationListener creates this, which is then consumed
* immediately by the GuardAuthenticationProvider. If authentication is
* successful, a different authenticated token is returned
*
* @author Ryan Weaver <ryan@knpuniversity.com>
*
* @deprecated since Symfony 5.3, use the new authenticator system instead
*/
class PreAuthenticationGuardToken extends AbstractToken implements GuardTokenInterface
{
private $credentials;
private $guardProviderKey;
/**
* @param mixed $credentials
* @param string $guardProviderKey Unique key that bind this token to a specific AuthenticatorInterface
*/
public function __construct($credentials, string $guardProviderKey)
{
$this->credentials = $credentials;
$this->guardProviderKey = $guardProviderKey;
parent::__construct([]);
// @deprecated since Symfony 5.4
parent::setAuthenticated(false);
}
public function getGuardProviderKey()
{
return $this->guardProviderKey;
}
/**
* Returns the user credentials, which might be an array of anything you
* wanted to put in there (e.g. username, password, favoriteColor).
*
* @return mixed
*/
public function getCredentials()
{
return $this->credentials;
}
/**
* @deprecated since Symfony 5.4
*/
public function setAuthenticated(bool $authenticated)
{
throw new \LogicException('The PreAuthenticationGuardToken is *never* authenticated.');
}
}

View File

@ -0,0 +1,34 @@
{
"name": "symfony/security-guard",
"type": "library",
"description": "Symfony Security Component - Guard",
"keywords": [],
"homepage": "https://symfony.com",
"license": "MIT",
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"require": {
"php": ">=7.2.5",
"symfony/security-core": "^5.0",
"symfony/security-http": "^5.3",
"symfony/polyfill-php80": "^1.15"
},
"require-dev": {
"psr/log": "^1|^2|^3"
},
"autoload": {
"psr-4": { "Symfony\\Component\\Security\\Guard\\": "" },
"exclude-from-classmap": [
"/Tests/"
]
},
"minimum-stability": "dev"
}