summaryrefslogtreecommitdiffstats
path: root/Http
diff options
context:
space:
mode:
authoralcaeus <git@alcaeus.org>2013-06-14 20:11:03 +0200
committeralcaeus <git@alcaeus.org>2013-07-19 23:56:43 +0200
commit73f4ea78eb4af288880ea99482f2542fa04b6c64 (patch)
treef9580fd9089f7e8be7c19380430b922d57361a5c /Http
parentb98d50b0b06fa2e4541c2a3ec59d69591418da80 (diff)
downloadsymfony-security-73f4ea78eb4af288880ea99482f2542fa04b6c64.zip
symfony-security-73f4ea78eb4af288880ea99482f2542fa04b6c64.tar.gz
symfony-security-73f4ea78eb4af288880ea99482f2542fa04b6c64.tar.bz2
[Security] fixed issue where authentication listeners clear unrelated tokens
This commit fixes an issue where authentication listeners clear all security tokens in case of authentication failure. This behavior makes it impossible to combine certain authentication mechanisms, notably x509 with form-based login.
Diffstat (limited to 'Http')
-rw-r--r--Http/Firewall/AbstractAuthenticationListener.php5
-rw-r--r--Http/Firewall/AbstractPreAuthenticatedListener.php19
-rw-r--r--Http/Firewall/BasicAuthenticationListener.php5
-rw-r--r--Http/Firewall/DigestAuthenticationListener.php5
4 files changed, 30 insertions, 4 deletions
diff --git a/Http/Firewall/AbstractAuthenticationListener.php b/Http/Firewall/AbstractAuthenticationListener.php
index d33c0f7..384f7ce 100644
--- a/Http/Firewall/AbstractAuthenticationListener.php
+++ b/Http/Firewall/AbstractAuthenticationListener.php
@@ -186,7 +186,10 @@ abstract class AbstractAuthenticationListener implements ListenerInterface
$this->logger->info(sprintf('Authentication request failed: %s', $failed->getMessage()));
}
- $this->securityContext->setToken(null);
+ $token = $this->securityContext->getToken();
+ if ($token instanceof UsernamePasswordToken && $this->providerKey === $token->getProviderKey()) {
+ $this->securityContext->setToken(null);
+ }
$response = $this->failureHandler->onAuthenticationFailure($request, $failed);
diff --git a/Http/Firewall/AbstractPreAuthenticatedListener.php b/Http/Firewall/AbstractPreAuthenticatedListener.php
index c6e47d0..28f6411 100644
--- a/Http/Firewall/AbstractPreAuthenticatedListener.php
+++ b/Http/Firewall/AbstractPreAuthenticatedListener.php
@@ -21,6 +21,7 @@ use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Psr\Log\LoggerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
+use Symfony\Component\Security\Core\Exception\BadCredentialsException;
/**
* AbstractPreAuthenticatedListener is the base class for all listener that
@@ -59,7 +60,12 @@ abstract class AbstractPreAuthenticatedListener implements ListenerInterface
$this->logger->debug(sprintf('Checking secure context token: %s', $this->securityContext->getToken()));
}
- list($user, $credentials) = $this->getPreAuthenticatedData($request);
+ try {
+ list($user, $credentials) = $this->getPreAuthenticatedData($request);
+ } catch (BadCredentialsException $exception) {
+ $this->clearToken();
+ return;
+ }
if (null !== $token = $this->securityContext->getToken()) {
if ($token instanceof PreAuthenticatedToken && $this->providerKey == $token->getProviderKey() && $token->isAuthenticated() && $token->getUsername() === $user) {
@@ -84,6 +90,17 @@ abstract class AbstractPreAuthenticatedListener implements ListenerInterface
$this->dispatcher->dispatch(SecurityEvents::INTERACTIVE_LOGIN, $loginEvent);
}
} catch (AuthenticationException $failed) {
+ $this->clearToken();
+ }
+ }
+
+ /**
+ * Clears a PreAuthenticatedToken for this provider (if present)
+ */
+ protected function clearToken()
+ {
+ $token = $this->securityContext->getToken();
+ if ($token instanceof PreAuthenticatedToken && $this->providerKey === $token->getProviderKey()) {
$this->securityContext->setToken(null);
if (null !== $this->logger) {
diff --git a/Http/Firewall/BasicAuthenticationListener.php b/Http/Firewall/BasicAuthenticationListener.php
index 5b1c8b3..bfc4abc 100644
--- a/Http/Firewall/BasicAuthenticationListener.php
+++ b/Http/Firewall/BasicAuthenticationListener.php
@@ -74,7 +74,10 @@ class BasicAuthenticationListener implements ListenerInterface
$token = $this->authenticationManager->authenticate(new UsernamePasswordToken($username, $request->headers->get('PHP_AUTH_PW'), $this->providerKey));
$this->securityContext->setToken($token);
} catch (AuthenticationException $failed) {
- $this->securityContext->setToken(null);
+ $token = $this->securityContext->getToken();
+ if ($token instanceof UsernamePasswordToken && $this->providerKey === $token->getProviderKey()) {
+ $this->securityContext->setToken(null);
+ }
if (null !== $this->logger) {
$this->logger->info(sprintf('Authentication request failed for user "%s": %s', $username, $failed->getMessage()));
diff --git a/Http/Firewall/DigestAuthenticationListener.php b/Http/Firewall/DigestAuthenticationListener.php
index 7ab3dcf..ea85e77 100644
--- a/Http/Firewall/DigestAuthenticationListener.php
+++ b/Http/Firewall/DigestAuthenticationListener.php
@@ -124,7 +124,10 @@ class DigestAuthenticationListener implements ListenerInterface
private function fail(GetResponseEvent $event, Request $request, AuthenticationException $authException)
{
- $this->securityContext->setToken(null);
+ $token = $this->securityContext->getToken();
+ if ($token instanceof UsernamePasswordToken && $this->providerKey === $token->getProviderKey()) {
+ $this->securityContext->setToken(null);
+ }
if (null !== $this->logger) {
$this->logger->info($authException);