summaryrefslogtreecommitdiffstats
path: root/Http
diff options
context:
space:
mode:
Diffstat (limited to 'Http')
-rw-r--r--Http/EntryPoint/AuthenticationEntryPointInterface.php12
-rw-r--r--Http/Firewall/DigestAuthenticationListener.php9
-rw-r--r--Http/Firewall/RememberMeListener.php8
-rw-r--r--Http/RememberMe/PersistentTokenBasedRememberMeServices.php3
-rw-r--r--Http/RememberMe/TokenBasedRememberMeServices.php28
5 files changed, 27 insertions, 33 deletions
diff --git a/Http/EntryPoint/AuthenticationEntryPointInterface.php b/Http/EntryPoint/AuthenticationEntryPointInterface.php
index 0d7595d..c8e43e5 100644
--- a/Http/EntryPoint/AuthenticationEntryPointInterface.php
+++ b/Http/EntryPoint/AuthenticationEntryPointInterface.php
@@ -24,7 +24,17 @@ use Symfony\Component\HttpFoundation\Response;
interface AuthenticationEntryPointInterface
{
/**
- * Starts the authentication scheme.
+ * 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:
+ * A) For a form login, you might redirect to the login page
+ * return new RedirectResponse('/login');
+ * B) For an API token authentication system, you return a 401 response
+ * return new Response('Auth header required', 401);
*
* @param Request $request The request that resulted in an AuthenticationException
* @param AuthenticationException $authException The exception that started the authentication process
diff --git a/Http/Firewall/DigestAuthenticationListener.php b/Http/Firewall/DigestAuthenticationListener.php
index a88250b..4e57667 100644
--- a/Http/Firewall/DigestAuthenticationListener.php
+++ b/Http/Firewall/DigestAuthenticationListener.php
@@ -13,6 +13,7 @@ namespace Symfony\Component\Security\Http\Firewall;
use Symfony\Component\Security\Core\SecurityContextInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
+use Symfony\Component\Security\Core\Util\StringUtils;
use Symfony\Component\Security\Http\EntryPoint\DigestAuthenticationEntryPoint;
use Psr\Log\LoggerInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
@@ -99,7 +100,7 @@ class DigestAuthenticationListener implements ListenerInterface
return;
}
- if ($serverDigestMd5 !== $digestAuth->getResponse()) {
+ if (!StringUtils::equals($serverDigestMd5, $digestAuth->getResponse())) {
if (null !== $this->logger) {
$this->logger->debug(sprintf('Expected response: "%s" but received: "%s"; is AuthenticationDao returning clear text passwords?', $serverDigestMd5, $digestAuth->getResponse()));
}
@@ -171,10 +172,8 @@ class DigestData
throw new BadCredentialsException(sprintf('Missing mandatory digest value; received header "%s" (%s)', $this->header, implode(', ', $keys)));
}
- if ('auth' === $this->elements['qop']) {
- if (!isset($this->elements['nc']) || !isset($this->elements['cnonce'])) {
- throw new BadCredentialsException(sprintf('Missing mandatory digest value; received header "%s"', $this->header));
- }
+ if ('auth' === $this->elements['qop'] && !isset($this->elements['nc'], $this->elements['cnonce'])) {
+ throw new BadCredentialsException(sprintf('Missing mandatory digest value; received header "%s"', $this->header));
}
if ($expectedRealm !== $this->elements['realm']) {
diff --git a/Http/Firewall/RememberMeListener.php b/Http/Firewall/RememberMeListener.php
index 942e537..52a231c 100644
--- a/Http/Firewall/RememberMeListener.php
+++ b/Http/Firewall/RememberMeListener.php
@@ -20,6 +20,7 @@ use Symfony\Component\Security\Http\RememberMe\RememberMeServicesInterface;
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
use Symfony\Component\Security\Http\SecurityEvents;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
+use Symfony\Component\Security\Http\Session\SessionAuthenticationStrategy;
/**
* RememberMeListener implements authentication capabilities via a cookie.
@@ -33,6 +34,7 @@ class RememberMeListener implements ListenerInterface
private $authenticationManager;
private $logger;
private $dispatcher;
+ private $sessionStrategy;
/**
* Constructor.
@@ -50,6 +52,7 @@ class RememberMeListener implements ListenerInterface
$this->authenticationManager = $authenticationManager;
$this->logger = $logger;
$this->dispatcher = $dispatcher;
+ $this->sessionStrategy = new SessionAuthenticationStrategy(SessionAuthenticationStrategy::MIGRATE);
}
/**
@@ -70,6 +73,11 @@ class RememberMeListener implements ListenerInterface
try {
$token = $this->authenticationManager->authenticate($token);
+
+ if ($request->hasSession() && $request->getSession()->isStarted()) {
+ $this->sessionStrategy->onAuthentication($request, $token);
+ }
+
$this->securityContext->setToken($token);
if (null !== $this->dispatcher) {
diff --git a/Http/RememberMe/PersistentTokenBasedRememberMeServices.php b/Http/RememberMe/PersistentTokenBasedRememberMeServices.php
index f800668..0fffbfe 100644
--- a/Http/RememberMe/PersistentTokenBasedRememberMeServices.php
+++ b/Http/RememberMe/PersistentTokenBasedRememberMeServices.php
@@ -21,6 +21,7 @@ use Symfony\Component\Security\Core\Authentication\RememberMe\PersistentToken;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Util\SecureRandomInterface;
use Psr\Log\LoggerInterface;
+use Symfony\Component\Security\Core\Util\StringUtils;
/**
* Concrete implementation of the RememberMeServicesInterface which needs
@@ -90,7 +91,7 @@ class PersistentTokenBasedRememberMeServices extends AbstractRememberMeServices
list($series, $tokenValue) = $cookieParts;
$persistentToken = $this->tokenProvider->loadTokenBySeries($series);
- if ($persistentToken->getTokenValue() !== $tokenValue) {
+ if (!StringUtils::equals($persistentToken->getTokenValue(), $tokenValue)) {
throw new CookieTheftException('This token was already used. The account is possibly compromised.');
}
diff --git a/Http/RememberMe/TokenBasedRememberMeServices.php b/Http/RememberMe/TokenBasedRememberMeServices.php
index de662fb..1aea5fd 100644
--- a/Http/RememberMe/TokenBasedRememberMeServices.php
+++ b/Http/RememberMe/TokenBasedRememberMeServices.php
@@ -17,6 +17,7 @@ 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\Util\StringUtils;
/**
* Concrete implementation of the RememberMeServicesInterface providing
@@ -53,7 +54,7 @@ class TokenBasedRememberMeServices extends AbstractRememberMeServices
throw new \RuntimeException(sprintf('The UserProviderInterface implementation must return an instance of UserInterface, but returned "%s".', get_class($user)));
}
- if (true !== $this->compareHashes($hash, $this->generateCookieHash($class, $username, $expires, $user->getPassword()))) {
+ if (!StringUtils::equals($this->generateCookieHash($class, $username, $expires, $user->getPassword()), $hash)) {
throw new AuthenticationException('The cookie\'s hash is invalid.');
}
@@ -65,31 +66,6 @@ class TokenBasedRememberMeServices extends AbstractRememberMeServices
}
/**
- * Compares two hashes using a constant-time algorithm to avoid (remote)
- * timing attacks.
- *
- * This is the same implementation as used in the BasePasswordEncoder.
- *
- * @param string $hash1 The first hash
- * @param string $hash2 The second hash
- *
- * @return bool true if the two hashes are the same, false otherwise
- */
- private function compareHashes($hash1, $hash2)
- {
- if (strlen($hash1) !== $c = strlen($hash2)) {
- return false;
- }
-
- $result = 0;
- for ($i = 0; $i < $c; ++$i) {
- $result |= ord($hash1[$i]) ^ ord($hash2[$i]);
- }
-
- return 0 === $result;
- }
-
- /**
* {@inheritdoc}
*/
protected function onLoginSuccess(Request $request, Response $response, TokenInterface $token)