diff --git a/src/Symfony/Bundle/SecurityBundle/Resources/config/authenticators.xml b/src/Symfony/Bundle/SecurityBundle/Resources/config/authenticators.xml
index e4fa9008dd..f752f923ca 100644
--- a/src/Symfony/Bundle/SecurityBundle/Resources/config/authenticators.xml
+++ b/src/Symfony/Bundle/SecurityBundle/Resources/config/authenticators.xml
@@ -20,7 +20,7 @@
realm name
user provider
@@ -29,7 +29,7 @@
@@ -39,7 +39,7 @@
diff --git a/src/Symfony/Bundle/SecurityBundle/Resources/config/security.xml b/src/Symfony/Bundle/SecurityBundle/Resources/config/security.xml
index 99d8550e1b..5e31b492f0 100644
--- a/src/Symfony/Bundle/SecurityBundle/Resources/config/security.xml
+++ b/src/Symfony/Bundle/SecurityBundle/Resources/config/security.xml
@@ -52,7 +52,7 @@
-
+
%security.authentication.manager.erase_credentials%
diff --git a/src/Symfony/Component/Security/Core/Authentication/Token/PreAuthenticationGuardToken.php b/src/Symfony/Component/Security/Core/Authentication/Token/PreAuthenticationGuardToken.php
new file mode 100644
index 0000000000..b19b82e066
--- /dev/null
+++ b/src/Symfony/Component/Security/Core/Authentication/Token/PreAuthenticationGuardToken.php
@@ -0,0 +1,71 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Security\Core\Authentication\Token;
+
+/**
+ * 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
+ */
+class PreAuthenticationGuardToken extends AbstractToken
+{
+ private $credentials;
+ private $guardProviderKey;
+ private $providerKey;
+
+ /**
+ * @param mixed $credentials
+ * @param string $guardProviderKey Unique key that bind this token to a specific AuthenticatorInterface
+ * @param string|null $providerKey The general provider key (when using with HTTP, this is the firewall name)
+ */
+ public function __construct($credentials, string $guardProviderKey, ?string $providerKey = null)
+ {
+ $this->credentials = $credentials;
+ $this->guardProviderKey = $guardProviderKey;
+ $this->providerKey = $providerKey;
+
+ parent::__construct([]);
+
+ // never authenticated
+ parent::setAuthenticated(false);
+ }
+
+ public function getProviderKey(): ?string
+ {
+ return $this->providerKey;
+ }
+
+ 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 The user credentials
+ */
+ public function getCredentials()
+ {
+ return $this->credentials;
+ }
+
+ public function setAuthenticated(bool $authenticated)
+ {
+ throw new \LogicException('The PreAuthenticationGuardToken is *never* authenticated.');
+ }
+}
diff --git a/src/Symfony/Component/Security/Core/Tests/Authentication/Authenticator/HttpBasicAuthenticatorTest.php b/src/Symfony/Component/Security/Core/Tests/Authentication/Authenticator/HttpBasicAuthenticatorTest.php
index 9e923364ea..c0265cd55a 100644
--- a/src/Symfony/Component/Security/Core/Tests/Authentication/Authenticator/HttpBasicAuthenticatorTest.php
+++ b/src/Symfony/Component/Security/Core/Tests/Authentication/Authenticator/HttpBasicAuthenticatorTest.php
@@ -5,7 +5,7 @@ namespace Symfony\Component\Security\Core\Tests\Authentication\Authenticator;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Symfony\Component\HttpFoundation\Request;
-use Symfony\Component\Security\Core\Authentication\Authenticator\HttpBasicAuthenticator;
+use Symfony\Component\Security\Http\Authentication\Authenticator\HttpBasicAuthenticator;
use Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface;
use Symfony\Component\Security\Core\Encoder\PasswordEncoderInterface;
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
diff --git a/src/Symfony/Component/Security/Core/composer.json b/src/Symfony/Component/Security/Core/composer.json
index 83b082bdde..fc500b285f 100644
--- a/src/Symfony/Component/Security/Core/composer.json
+++ b/src/Symfony/Component/Security/Core/composer.json
@@ -20,7 +20,6 @@
"symfony/event-dispatcher-contracts": "^1.1|^2",
"symfony/polyfill-php80": "^1.15",
"symfony/service-contracts": "^1.1.6|^2",
- "symfony/security-guard": "^4.4",
"symfony/deprecation-contracts": "^2.1"
},
"require-dev": {
diff --git a/src/Symfony/Component/Security/Guard/Firewall/GuardAuthenticationListener.php b/src/Symfony/Component/Security/Guard/Firewall/GuardAuthenticationListener.php
index d30a95fdd7..7ffad32454 100644
--- a/src/Symfony/Component/Security/Guard/Firewall/GuardAuthenticationListener.php
+++ b/src/Symfony/Component/Security/Guard/Firewall/GuardAuthenticationListener.php
@@ -15,9 +15,12 @@ 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\PreAuthenticationGuardToken;
use Symfony\Component\Security\Guard\AuthenticatorInterface;
use Symfony\Component\Security\Guard\GuardAuthenticatorHandler;
+use Symfony\Component\Security\Guard\Token\PreAuthenticationGuardToken as GuardPreAuthenticationGuardToken;
use Symfony\Component\Security\Http\Firewall\AbstractListener;
+use Symfony\Component\Security\Http\Firewall\GuardManagerListenerTrait;
use Symfony\Component\Security\Http\RememberMe\RememberMeServicesInterface;
/**
@@ -30,7 +33,7 @@ use Symfony\Component\Security\Http\RememberMe\RememberMeServicesInterface;
*/
class GuardAuthenticationListener extends AbstractListener
{
- use GuardAuthenticatorListenerTrait;
+ use GuardManagerListenerTrait;
private $guardHandler;
private $authenticationManager;
@@ -101,6 +104,11 @@ class GuardAuthenticationListener extends AbstractListener
$this->rememberMeServices = $rememberMeServices;
}
+ protected function createPreAuthenticatedToken($credentials, string $uniqueGuardKey, string $providerKey): PreAuthenticationGuardToken
+ {
+ return new GuardPreAuthenticationGuardToken($credentials, $uniqueGuardKey, $providerKey);
+ }
+
protected function getGuardKey(string $key): string
{
// get a key that's unique to *this* guard authenticator
diff --git a/src/Symfony/Component/Security/Guard/GuardAuthenticatorHandler.php b/src/Symfony/Component/Security/Guard/GuardAuthenticatorHandler.php
index d2c0d298d2..2f16dfa140 100644
--- a/src/Symfony/Component/Security/Guard/GuardAuthenticatorHandler.php
+++ b/src/Symfony/Component/Security/Guard/GuardAuthenticatorHandler.php
@@ -11,17 +11,7 @@
namespace Symfony\Component\Security\Guard;
-use Symfony\Component\HttpFoundation\Request;
-use Symfony\Component\HttpFoundation\Response;
-use Symfony\Component\Security\Core\Authentication\Authenticator\AuthenticatorInterface as CoreAuthenticatorInterface;
-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;
+use Symfony\Component\Security\Http\Authentication\GuardAuthenticatorHandler as CoreAuthenticatorHandlerAlias;
/**
* A utility class that does much of the *work* during the guard authentication process.
@@ -33,116 +23,6 @@ use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
*
* @final
*/
-class GuardAuthenticatorHandler
+class GuardAuthenticatorHandler extends CoreAuthenticatorHandlerAlias
{
- 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.
- *
- * @param CoreAuthenticatorInterface|AuthenticatorInterface $guardAuthenticator
- */
- public function handleAuthenticationSuccess(TokenInterface $token, Request $request, $guardAuthenticator, string $providerKey): ?Response
- {
- if (!$guardAuthenticator instanceof AuthenticatorInterface && !$guardAuthenticator instanceof CoreAuthenticatorInterface) {
- throw new \UnexpectedValueException('Invalid guard authenticator passed to '.__METHOD__.'. Expected AuthenticatorInterface of either Security Core or Security Guard.');
- }
-
- $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.
- *
- * @param CoreAuthenticatorInterface|AuthenticatorInterface $authenticator
- */
- public function authenticateUserAndHandleSuccess(UserInterface $user, Request $request, $authenticator, string $providerKey): ?Response
- {
- if (!$authenticator instanceof AuthenticatorInterface && !$authenticator instanceof CoreAuthenticatorInterface) {
- throw new \UnexpectedValueException('Invalid guard authenticator passed to '.__METHOD__.'. Expected AuthenticatorInterface of either Security Core or Security Guard.');
- }
-
- // 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.
- *
- * @param CoreAuthenticatorInterface|AuthenticatorInterface $guardAuthenticator
- */
- public function handleAuthenticationFailure(AuthenticationException $authenticationException, Request $request, $guardAuthenticator, string $providerKey): ?Response
- {
- if (!$guardAuthenticator instanceof AuthenticatorInterface && !$guardAuthenticator instanceof CoreAuthenticatorInterface) {
- throw new \UnexpectedValueException('Invalid guard authenticator passed to '.__METHOD__.'. Expected AuthenticatorInterface of either Security Core or Security Guard.');
- }
-
- $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);
- }
}
diff --git a/src/Symfony/Component/Security/Guard/Provider/GuardAuthenticationProvider.php b/src/Symfony/Component/Security/Guard/Provider/GuardAuthenticationProvider.php
index 04085aaa05..01f70e9b4e 100644
--- a/src/Symfony/Component/Security/Guard/Provider/GuardAuthenticationProvider.php
+++ b/src/Symfony/Component/Security/Guard/Provider/GuardAuthenticationProvider.php
@@ -11,6 +11,7 @@
namespace Symfony\Component\Security\Guard\Provider;
+use Symfony\Component\Security\Http\Authentication\GuardAuthenticationManagerTrait;
use Symfony\Component\Security\Core\Authentication\Provider\AuthenticationProviderInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
@@ -30,7 +31,7 @@ use Symfony\Component\Security\Guard\Token\PreAuthenticationGuardToken;
*/
class GuardAuthenticationProvider implements AuthenticationProviderInterface
{
- use GuardAuthenticationProviderTrait;
+ use GuardAuthenticationManagerTrait;
/**
* @var AuthenticatorInterface[]
diff --git a/src/Symfony/Component/Security/Guard/Token/PreAuthenticationGuardToken.php b/src/Symfony/Component/Security/Guard/Token/PreAuthenticationGuardToken.php
index 460dcf9bda..69013599f3 100644
--- a/src/Symfony/Component/Security/Guard/Token/PreAuthenticationGuardToken.php
+++ b/src/Symfony/Component/Security/Guard/Token/PreAuthenticationGuardToken.php
@@ -11,7 +11,7 @@
namespace Symfony\Component\Security\Guard\Token;
-use Symfony\Component\Security\Core\Authentication\Token\AbstractToken;
+use Symfony\Component\Security\Core\Authentication\Token\PreAuthenticationGuardToken as CorePreAuthenticationGuardToken;
/**
* The token used by the guard auth system before authentication.
@@ -22,52 +22,6 @@ use Symfony\Component\Security\Core\Authentication\Token\AbstractToken;
*
* @author Ryan Weaver
*/
-class PreAuthenticationGuardToken extends AbstractToken implements GuardTokenInterface
+class PreAuthenticationGuardToken extends CorePreAuthenticationGuardToken implements GuardTokenInterface
{
- private $credentials;
- private $guardProviderKey;
- private $providerKey;
-
- /**
- * @param mixed $credentials
- * @param string $guardProviderKey Unique key that bind this token to a specific AuthenticatorInterface
- * @param string|null $providerKey The general provider key (when using with HTTP, this is the firewall name)
- */
- public function __construct($credentials, string $guardProviderKey, ?string $providerKey = null)
- {
- $this->credentials = $credentials;
- $this->guardProviderKey = $guardProviderKey;
- $this->providerKey = $providerKey;
-
- parent::__construct([]);
-
- // never authenticated
- parent::setAuthenticated(false);
- }
-
- public function getProviderKey(): ?string
- {
- return $this->providerKey;
- }
-
- 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 The user credentials
- */
- public function getCredentials()
- {
- return $this->credentials;
- }
-
- public function setAuthenticated(bool $authenticated)
- {
- throw new \LogicException('The PreAuthenticationGuardToken is *never* authenticated.');
- }
}
diff --git a/src/Symfony/Component/Security/Guard/composer.json b/src/Symfony/Component/Security/Guard/composer.json
index 1b2337f829..f129233640 100644
--- a/src/Symfony/Component/Security/Guard/composer.json
+++ b/src/Symfony/Component/Security/Guard/composer.json
@@ -17,7 +17,7 @@
],
"require": {
"php": "^7.2.5",
- "symfony/security-core": "^5.0",
+ "symfony/security-core": "^5.1",
"symfony/security-http": "^4.4.1|^5.0.1",
"symfony/polyfill-php80": "^1.15"
},
diff --git a/src/Symfony/Component/Security/Core/Authentication/Authenticator/AbstractAuthenticator.php b/src/Symfony/Component/Security/Http/Authentication/Authenticator/AbstractAuthenticator.php
similarity index 94%
rename from src/Symfony/Component/Security/Core/Authentication/Authenticator/AbstractAuthenticator.php
rename to src/Symfony/Component/Security/Http/Authentication/Authenticator/AbstractAuthenticator.php
index 1127fb6781..ce22dce368 100644
--- a/src/Symfony/Component/Security/Core/Authentication/Authenticator/AbstractAuthenticator.php
+++ b/src/Symfony/Component/Security/Http/Authentication/Authenticator/AbstractAuthenticator.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\Component\Security\Core\Authentication\Authenticator;
+namespace Symfony\Component\Security\Http\Authentication\Authenticator;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\User\UserInterface;
diff --git a/src/Symfony/Component/Security/Core/Authentication/Authenticator/AbstractFormLoginAuthenticator.php b/src/Symfony/Component/Security/Http/Authentication/Authenticator/AbstractFormLoginAuthenticator.php
similarity index 96%
rename from src/Symfony/Component/Security/Core/Authentication/Authenticator/AbstractFormLoginAuthenticator.php
rename to src/Symfony/Component/Security/Http/Authentication/Authenticator/AbstractFormLoginAuthenticator.php
index 27df412d28..5cc2f95414 100644
--- a/src/Symfony/Component/Security/Core/Authentication/Authenticator/AbstractFormLoginAuthenticator.php
+++ b/src/Symfony/Component/Security/Http/Authentication/Authenticator/AbstractFormLoginAuthenticator.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\Component\Security\Core\Authentication\Authenticator;
+namespace Symfony\Component\Security\Http\Authentication\Authenticator;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
diff --git a/src/Symfony/Component/Security/Core/Authentication/Authenticator/AnonymousAuthenticator.php b/src/Symfony/Component/Security/Http/Authentication/Authenticator/AnonymousAuthenticator.php
similarity index 97%
rename from src/Symfony/Component/Security/Core/Authentication/Authenticator/AnonymousAuthenticator.php
rename to src/Symfony/Component/Security/Http/Authentication/Authenticator/AnonymousAuthenticator.php
index 26a7d3102b..bec859e7a7 100644
--- a/src/Symfony/Component/Security/Core/Authentication/Authenticator/AnonymousAuthenticator.php
+++ b/src/Symfony/Component/Security/Http/Authentication/Authenticator/AnonymousAuthenticator.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\Component\Security\Core\Authentication\Authenticator;
+namespace Symfony\Component\Security\Http\Authentication\Authenticator;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
diff --git a/src/Symfony/Component/Security/Core/Authentication/Authenticator/AuthenticatorInterface.php b/src/Symfony/Component/Security/Http/Authentication/Authenticator/AuthenticatorInterface.php
similarity index 98%
rename from src/Symfony/Component/Security/Core/Authentication/Authenticator/AuthenticatorInterface.php
rename to src/Symfony/Component/Security/Http/Authentication/Authenticator/AuthenticatorInterface.php
index cf84ce1609..8bf38ac85a 100644
--- a/src/Symfony/Component/Security/Core/Authentication/Authenticator/AuthenticatorInterface.php
+++ b/src/Symfony/Component/Security/Http/Authentication/Authenticator/AuthenticatorInterface.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\Component\Security\Core\Authentication\Authenticator;
+namespace Symfony\Component\Security\Http\Authentication\Authenticator;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
diff --git a/src/Symfony/Component/Security/Core/Authentication/Authenticator/FormLoginAuthenticator.php b/src/Symfony/Component/Security/Http/Authentication/Authenticator/FormLoginAuthenticator.php
similarity index 98%
rename from src/Symfony/Component/Security/Core/Authentication/Authenticator/FormLoginAuthenticator.php
rename to src/Symfony/Component/Security/Http/Authentication/Authenticator/FormLoginAuthenticator.php
index 19c5b69029..2ff37f987b 100644
--- a/src/Symfony/Component/Security/Core/Authentication/Authenticator/FormLoginAuthenticator.php
+++ b/src/Symfony/Component/Security/Http/Authentication/Authenticator/FormLoginAuthenticator.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\Component\Security\Core\Authentication\Authenticator;
+namespace Symfony\Component\Security\Http\Authentication\Authenticator;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
diff --git a/src/Symfony/Component/Security/Core/Authentication/Authenticator/HttpBasicAuthenticator.php b/src/Symfony/Component/Security/Http/Authentication/Authenticator/HttpBasicAuthenticator.php
similarity index 97%
rename from src/Symfony/Component/Security/Core/Authentication/Authenticator/HttpBasicAuthenticator.php
rename to src/Symfony/Component/Security/Http/Authentication/Authenticator/HttpBasicAuthenticator.php
index 6ce74c6809..92cb130ec9 100644
--- a/src/Symfony/Component/Security/Core/Authentication/Authenticator/HttpBasicAuthenticator.php
+++ b/src/Symfony/Component/Security/Http/Authentication/Authenticator/HttpBasicAuthenticator.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\Component\Security\Core\Authentication\Authenticator;
+namespace Symfony\Component\Security\Http\Authentication\Authenticator;
use Psr\Log\LoggerInterface;
use Symfony\Component\HttpFoundation\Request;
diff --git a/src/Symfony/Component/Security/Core/Authentication/Authenticator/UsernamePasswordTrait.php b/src/Symfony/Component/Security/Http/Authentication/Authenticator/UsernamePasswordTrait.php
similarity index 96%
rename from src/Symfony/Component/Security/Core/Authentication/Authenticator/UsernamePasswordTrait.php
rename to src/Symfony/Component/Security/Http/Authentication/Authenticator/UsernamePasswordTrait.php
index 292ec370f8..bbfbc5af02 100644
--- a/src/Symfony/Component/Security/Core/Authentication/Authenticator/UsernamePasswordTrait.php
+++ b/src/Symfony/Component/Security/Http/Authentication/Authenticator/UsernamePasswordTrait.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\Component\Security\Core\Authentication\Authenticator;
+namespace Symfony\Component\Security\Http\Authentication\Authenticator;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
diff --git a/src/Symfony/Component/Security/Core/Authentication/GuardAuthenticationManager.php b/src/Symfony/Component/Security/Http/Authentication/GuardAuthenticationManager.php
similarity index 88%
rename from src/Symfony/Component/Security/Core/Authentication/GuardAuthenticationManager.php
rename to src/Symfony/Component/Security/Http/Authentication/GuardAuthenticationManager.php
index 8b4e2e6393..b62516168b 100644
--- a/src/Symfony/Component/Security/Core/Authentication/GuardAuthenticationManager.php
+++ b/src/Symfony/Component/Security/Http/Authentication/GuardAuthenticationManager.php
@@ -9,9 +9,11 @@
* file that was distributed with this source code.
*/
-namespace Symfony\Component\Security\Core\Authentication;
+namespace Symfony\Component\Security\Http\Authentication;
-use Symfony\Component\Security\Core\Authentication\Authenticator\AuthenticatorInterface;
+use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
+use Symfony\Component\Security\Http\Authentication\Authenticator\AuthenticatorInterface;
+use Symfony\Component\Security\Core\Authentication\Token\PreAuthenticationGuardToken;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\AuthenticationEvents;
use Symfony\Component\Security\Core\Event\AuthenticationFailureEvent;
@@ -20,9 +22,6 @@ use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\Exception\AuthenticationExpiredException;
use Symfony\Component\Security\Core\Exception\ProviderNotFoundException;
use Symfony\Component\Security\Core\User\UserCheckerInterface;
-use Symfony\Component\Security\Guard\Provider\GuardAuthenticationProviderTrait;
-use Symfony\Component\Security\Guard\Token\GuardTokenInterface;
-use Symfony\Component\Security\Guard\Token\PreAuthenticationGuardToken;
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
/**
@@ -33,7 +32,7 @@ use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
*/
class GuardAuthenticationManager implements AuthenticationManagerInterface
{
- use GuardAuthenticationProviderTrait;
+ use GuardAuthenticationManagerTrait;
private $guardAuthenticators;
private $userChecker;
@@ -58,10 +57,6 @@ class GuardAuthenticationManager implements AuthenticationManagerInterface
public function authenticate(TokenInterface $token)
{
- if (!$token instanceof GuardTokenInterface) {
- throw new \InvalidArgumentException('GuardAuthenticationManager only supports GuardTokenInterface.');
- }
-
if (!$token instanceof PreAuthenticationGuardToken) {
/*
* The listener *only* passes PreAuthenticationGuardToken instances.
diff --git a/src/Symfony/Component/Security/Guard/Provider/GuardAuthenticationProviderTrait.php b/src/Symfony/Component/Security/Http/Authentication/GuardAuthenticationManagerTrait.php
similarity index 95%
rename from src/Symfony/Component/Security/Guard/Provider/GuardAuthenticationProviderTrait.php
rename to src/Symfony/Component/Security/Http/Authentication/GuardAuthenticationManagerTrait.php
index 667c35d05e..7de91a75a3 100644
--- a/src/Symfony/Component/Security/Guard/Provider/GuardAuthenticationProviderTrait.php
+++ b/src/Symfony/Component/Security/Http/Authentication/GuardAuthenticationManagerTrait.php
@@ -9,9 +9,10 @@
* file that was distributed with this source code.
*/
-namespace Symfony\Component\Security\Guard\Provider;
+namespace Symfony\Component\Security\Http\Authentication;
-use Symfony\Component\Security\Core\Authentication\Authenticator\AuthenticatorInterface as CoreAuthenticatorInterface;
+use Symfony\Component\Security\Http\Authentication\Authenticator\AuthenticatorInterface as CoreAuthenticatorInterface;
+use Symfony\Component\Security\Core\Authentication\Token\PreAuthenticationGuardToken;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
use Symfony\Component\Security\Core\Exception\LogicException;
@@ -20,14 +21,13 @@ use Symfony\Component\Security\Core\User\PasswordUpgraderInterface;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Guard\AuthenticatorInterface;
use Symfony\Component\Security\Guard\PasswordAuthenticatedInterface;
-use Symfony\Component\Security\Guard\Token\PreAuthenticationGuardToken;
/**
* @author Ryan Weaver
*
* @internal
*/
-trait GuardAuthenticationProviderTrait
+trait GuardAuthenticationManagerTrait
{
/**
* @param CoreAuthenticatorInterface|AuthenticatorInterface $guardAuthenticator
diff --git a/src/Symfony/Component/Security/Http/Authentication/GuardAuthenticatorHandler.php b/src/Symfony/Component/Security/Http/Authentication/GuardAuthenticatorHandler.php
new file mode 100644
index 0000000000..d930df1896
--- /dev/null
+++ b/src/Symfony/Component/Security/Http/Authentication/GuardAuthenticatorHandler.php
@@ -0,0 +1,149 @@
+
+ *
+ * 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\Authentication\Authenticator\AuthenticatorInterface;
+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\Guard\AuthenticatorInterface as GuardAuthenticatorInterface;
+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;
+
+/**
+ * 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
+ *
+ * @internal
+ */
+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.
+ *
+ * @param AuthenticatorInterface|GuardAuthenticatorInterface $guardAuthenticator
+ */
+ public function handleAuthenticationSuccess(TokenInterface $token, Request $request, $guardAuthenticator, string $providerKey): ?Response
+ {
+ if (!$guardAuthenticator instanceof AuthenticatorInterface && !$guardAuthenticator instanceof GuardAuthenticatorInterface) {
+ throw new \UnexpectedValueException('Invalid guard authenticator passed to '.__METHOD__.'. Expected AuthenticatorInterface of either Security Core or Security Guard.');
+ }
+
+ $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.
+ *
+ * @param AuthenticatorInterface|GuardAuthenticatorInterface $authenticator
+ */
+ public function authenticateUserAndHandleSuccess(UserInterface $user, Request $request, $authenticator, string $providerKey): ?Response
+ {
+ if (!$authenticator instanceof AuthenticatorInterface && !$authenticator instanceof GuardAuthenticatorInterface) {
+ throw new \UnexpectedValueException('Invalid guard authenticator passed to '.__METHOD__.'. Expected AuthenticatorInterface of either Security Core or Security Guard.');
+ }
+
+ // 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.
+ *
+ * @param AuthenticatorInterface|GuardAuthenticatorInterface $guardAuthenticator
+ */
+ public function handleAuthenticationFailure(AuthenticationException $authenticationException, Request $request, $guardAuthenticator, string $providerKey): ?Response
+ {
+ if (!$guardAuthenticator instanceof AuthenticatorInterface && !$guardAuthenticator instanceof GuardAuthenticatorInterface) {
+ throw new \UnexpectedValueException('Invalid guard authenticator passed to '.__METHOD__.'. Expected AuthenticatorInterface of either Security Core or Security Guard.');
+ }
+
+ $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);
+ }
+}
diff --git a/src/Symfony/Component/Security/Http/Firewall/GuardManagerListener.php b/src/Symfony/Component/Security/Http/Firewall/GuardManagerListener.php
index 78681bd1e8..2367223657 100644
--- a/src/Symfony/Component/Security/Http/Firewall/GuardManagerListener.php
+++ b/src/Symfony/Component/Security/Http/Firewall/GuardManagerListener.php
@@ -14,8 +14,8 @@ namespace Symfony\Component\Security\Http\Firewall;
use Psr\Log\LoggerInterface;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
-use Symfony\Component\Security\Core\Authentication\Authenticator\AuthenticatorInterface;
-use Symfony\Component\Security\Guard\Firewall\GuardAuthenticatorListenerTrait;
+use Symfony\Component\Security\Http\Authentication\Authenticator\AuthenticatorInterface;
+use Symfony\Component\Security\Core\Authentication\Token\PreAuthenticationGuardToken;
use Symfony\Component\Security\Guard\GuardAuthenticatorHandler;
use Symfony\Component\Security\Http\RememberMe\RememberMeServicesInterface;
@@ -28,7 +28,7 @@ use Symfony\Component\Security\Http\RememberMe\RememberMeServicesInterface;
*/
class GuardManagerListener
{
- use GuardAuthenticatorListenerTrait;
+ use GuardManagerListenerTrait;
private $authenticationManager;
private $guardHandler;
@@ -65,6 +65,11 @@ class GuardManagerListener
$this->rememberMeServices = $rememberMeServices;
}
+ protected function createPreAuthenticatedToken($credentials, string $uniqueGuardKey, string $providerKey): PreAuthenticationGuardToken
+ {
+ return new PreAuthenticationGuardToken($credentials, $uniqueGuardKey, $providerKey);
+ }
+
protected function getGuardKey(string $key): string
{
// Guard authenticators in the GuardManagerListener are already indexed
diff --git a/src/Symfony/Component/Security/Guard/Firewall/GuardAuthenticatorListenerTrait.php b/src/Symfony/Component/Security/Http/Firewall/GuardManagerListenerTrait.php
similarity index 94%
rename from src/Symfony/Component/Security/Guard/Firewall/GuardAuthenticatorListenerTrait.php
rename to src/Symfony/Component/Security/Http/Firewall/GuardManagerListenerTrait.php
index 245f02c906..794d1dd133 100644
--- a/src/Symfony/Component/Security/Guard/Firewall/GuardAuthenticatorListenerTrait.php
+++ b/src/Symfony/Component/Security/Http/Firewall/GuardManagerListenerTrait.php
@@ -9,16 +9,16 @@
* file that was distributed with this source code.
*/
-namespace Symfony\Component\Security\Guard\Firewall;
+namespace Symfony\Component\Security\Http\Firewall;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\RequestEvent;
-use Symfony\Component\Security\Core\Authentication\Authenticator\AuthenticatorInterface as CoreAuthenticatorInterface;
+use Symfony\Component\Security\Http\Authentication\Authenticator\AuthenticatorInterface as CoreAuthenticatorInterface;
+use Symfony\Component\Security\Core\Authentication\Token\PreAuthenticationGuardToken;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Guard\AuthenticatorInterface;
-use Symfony\Component\Security\Guard\Token\PreAuthenticationGuardToken;
/**
* @author Ryan Weaver
@@ -26,7 +26,7 @@ use Symfony\Component\Security\Guard\Token\PreAuthenticationGuardToken;
*
* @internal
*/
-trait GuardAuthenticatorListenerTrait
+trait GuardManagerListenerTrait
{
protected function getSupportingGuardAuthenticators(Request $request): array
{
@@ -89,7 +89,7 @@ trait GuardAuthenticatorListenerTrait
}
// create a token with the unique key, so that the provider knows which authenticator to use
- $token = new PreAuthenticationGuardToken($credentials, $uniqueGuardKey, $this->providerKey);
+ $token = $this->createPreAuthenticatedToken($credentials, $uniqueGuardKey, $this->providerKey);
if (null !== $this->logger) {
$this->logger->debug('Passing guard token information to the GuardAuthenticationProvider', ['firewall_key' => $this->providerKey, 'authenticator' => \get_class($guardAuthenticator)]);
@@ -174,4 +174,6 @@ trait GuardAuthenticatorListenerTrait
}
abstract protected function getGuardKey(string $key): string;
+
+ abstract protected function createPreAuthenticatedToken($credentials, string $uniqueGuardKey, string $providerKey): PreAuthenticationGuardToken;
}
diff --git a/src/Symfony/Component/Security/Http/composer.json b/src/Symfony/Component/Security/Http/composer.json
index 376ee410fa..77a16c50ce 100644
--- a/src/Symfony/Component/Security/Http/composer.json
+++ b/src/Symfony/Component/Security/Http/composer.json
@@ -18,7 +18,7 @@
"require": {
"php": "^7.2.5",
"symfony/deprecation-contracts": "^2.1",
- "symfony/security-core": "^4.4.8|^5.0.8",
+ "symfony/security-core": "^5.1",
"symfony/http-foundation": "^4.4.7|^5.0.7",
"symfony/http-kernel": "^4.4|^5.0",
"symfony/polyfill-php80": "^1.15",