From 2a94b1d1b74b4e776e76a522621b67b45d115fe7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20L=C5=93uillet?= Date: Mon, 9 Feb 2015 22:07:39 +0100 Subject: [PATCH] log for authentication on API --- app/config/config_prod.yml | 5 ++++ .../CoreBundle/Controller/EntryController.php | 1 - .../CoreBundle/Repository/EntryRepository.php | 12 +++++----- .../CoreBundle/Resources/config/services.xml | 2 ++ .../Authentication/Provider/WsseProvider.php | 23 +++++++++++++++---- .../Security/Firewall/WsseListener.php | 20 +++++++++++----- .../CoreBundle/Tests/WallabagTestCase.php | 2 -- 7 files changed, 45 insertions(+), 20 deletions(-) diff --git a/app/config/config_prod.yml b/app/config/config_prod.yml index 342837a03..c45f0fa66 100644 --- a/app/config/config_prod.yml +++ b/app/config/config_prod.yml @@ -17,6 +17,11 @@ monolog: type: fingers_crossed action_level: error handler: nested + wsse: + type: stream + path: %kernel.logs_dir%/%kernel.environment%.wsse.log + level: error + channels: [wsse] nested: type: stream path: "%kernel.logs_dir%/%kernel.environment%.log" diff --git a/src/Wallabag/CoreBundle/Controller/EntryController.php b/src/Wallabag/CoreBundle/Controller/EntryController.php index e0697ca3e..5378486ae 100644 --- a/src/Wallabag/CoreBundle/Controller/EntryController.php +++ b/src/Wallabag/CoreBundle/Controller/EntryController.php @@ -6,7 +6,6 @@ use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Component\HttpFoundation\Request; use Wallabag\CoreBundle\Entity\Entry; -use Wallabag\CoreBundle\Repository; use Wallabag\CoreBundle\Service\Extractor; use Wallabag\CoreBundle\Helper\Url; diff --git a/src/Wallabag/CoreBundle/Repository/EntryRepository.php b/src/Wallabag/CoreBundle/Repository/EntryRepository.php index 5ae1337a8..1805cf3f4 100644 --- a/src/Wallabag/CoreBundle/Repository/EntryRepository.php +++ b/src/Wallabag/CoreBundle/Repository/EntryRepository.php @@ -91,12 +91,12 @@ class EntryRepository extends EntityRepository /** * Find Entries * - * @param int $userId - * @param bool $isArchived - * @param bool $isStarred - * @param bool $isDeleted - * @param string $sort - * @param string $order + * @param int $userId + * @param bool $isArchived + * @param bool $isStarred + * @param bool $isDeleted + * @param string $sort + * @param string $order * * @return ArrayCollection */ diff --git a/src/Wallabag/CoreBundle/Resources/config/services.xml b/src/Wallabag/CoreBundle/Resources/config/services.xml index 859665ca9..ca2ba3830 100644 --- a/src/Wallabag/CoreBundle/Resources/config/services.xml +++ b/src/Wallabag/CoreBundle/Resources/config/services.xml @@ -21,6 +21,8 @@ class="Wallabag\CoreBundle\Security\Firewall\WsseListener" public="false"> + + diff --git a/src/Wallabag/CoreBundle/Security/Authentication/Provider/WsseProvider.php b/src/Wallabag/CoreBundle/Security/Authentication/Provider/WsseProvider.php index eaad9c633..c9b9b692f 100644 --- a/src/Wallabag/CoreBundle/Security/Authentication/Provider/WsseProvider.php +++ b/src/Wallabag/CoreBundle/Security/Authentication/Provider/WsseProvider.php @@ -23,6 +23,10 @@ class WsseProvider implements AuthenticationProviderInterface { $user = $this->userProvider->loadUserByUsername($token->getUsername()); + if (!$user) { + throw new AuthenticationException("Bad credentials. Did you forgot your username?"); + } + if ($user && $this->validateDigest($token->digest, $token->nonce, $token->created, $user->getPassword())) { $authenticatedToken = new WsseUserToken($user->getRoles()); $authenticatedToken->setUser($user); @@ -35,12 +39,17 @@ class WsseProvider implements AuthenticationProviderInterface protected function validateDigest($digest, $nonce, $created, $secret) { - // Expire le timestamp après 5 minutes - if (time() - strtotime($created) > 300) { - return false; + // Check created time is not in the future + if (strtotime($created) > time()) { + throw new AuthenticationException("Back to the future..."); } - // Valide que le nonce est unique dans les 5 minutes + // Expire timestamp after 5 minutes + if (time() - strtotime($created) > 300) { + throw new AuthenticationException("Too late for this timestamp... Watch your watch."); + } + + // Validate nonce is unique within 5 minutes if (file_exists($this->cacheDir.'/'.$nonce) && file_get_contents($this->cacheDir.'/'.$nonce) + 300 > time()) { throw new NonceExpiredException('Previously used nonce detected'); } @@ -52,9 +61,13 @@ class WsseProvider implements AuthenticationProviderInterface file_put_contents($this->cacheDir.'/'.$nonce, time()); - // Valide le Secret + // Validate Secret $expected = base64_encode(sha1(base64_decode($nonce).$created.$secret, true)); + if ($digest !== $expected) { + throw new AuthenticationException("Bad credentials ! Digest is not as expected."); + } + return $digest === $expected; } diff --git a/src/Wallabag/CoreBundle/Security/Firewall/WsseListener.php b/src/Wallabag/CoreBundle/Security/Firewall/WsseListener.php index 4d4f2145c..d815d5362 100644 --- a/src/Wallabag/CoreBundle/Security/Firewall/WsseListener.php +++ b/src/Wallabag/CoreBundle/Security/Firewall/WsseListener.php @@ -9,16 +9,19 @@ use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\Security\Core\SecurityContextInterface; use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface; use Wallabag\CoreBundle\Security\Authentication\Token\WsseUserToken; +use Symfony\Component\HttpKernel\Log\LoggerInterface; class WsseListener implements ListenerInterface { protected $securityContext; protected $authenticationManager; + protected $logger; - public function __construct(SecurityContextInterface $securityContext, AuthenticationManagerInterface $authenticationManager) + public function __construct(SecurityContextInterface $securityContext, AuthenticationManagerInterface $authenticationManager, LoggerInterface $logger) { $this->securityContext = $securityContext; $this->authenticationManager = $authenticationManager; + $this->logger = $logger; } public function handle(GetResponseEvent $event) @@ -42,16 +45,21 @@ class WsseListener implements ListenerInterface $this->securityContext->setToken($authToken); } catch (AuthenticationException $failed) { - // ... you might log something here - - // To deny the authentication clear the token. This will redirect to the login page. - // $this->securityContext->setToken(null); - // return; + $failedMessage = 'WSSE Login failed for '.$token->getUsername().'. Why ? '.$failed->getMessage(); + $this->logger->err($failedMessage); // Deny authentication with a '403 Forbidden' HTTP response $response = new Response(); $response->setStatusCode(403); + $response->setContent($failedMessage); $event->setResponse($response); + + return; } + + // By default deny authorization + $response = new Response(); + $response->setStatusCode(403); + $event->setResponse($response); } } diff --git a/src/Wallabag/CoreBundle/Tests/WallabagTestCase.php b/src/Wallabag/CoreBundle/Tests/WallabagTestCase.php index 5f0923181..edc7d9927 100644 --- a/src/Wallabag/CoreBundle/Tests/WallabagTestCase.php +++ b/src/Wallabag/CoreBundle/Tests/WallabagTestCase.php @@ -3,8 +3,6 @@ namespace Wallabag\CoreBundle\Tests; use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; -use Symfony\Component\BrowserKit\Cookie; -use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken; class WallabagTestCase extends WebTestCase {