From 0ac38198ab1c00dfb290d5631fa7c1cf5ac2a48a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20L=C5=93uillet?= Date: Mon, 9 Feb 2015 13:59:48 +0100 Subject: authentication on API --- .../CoreBundle/Security/Authentication/Provider/WsseProvider.php | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src') diff --git a/src/Wallabag/CoreBundle/Security/Authentication/Provider/WsseProvider.php b/src/Wallabag/CoreBundle/Security/Authentication/Provider/WsseProvider.php index 5499f400..eaad9c63 100644 --- a/src/Wallabag/CoreBundle/Security/Authentication/Provider/WsseProvider.php +++ b/src/Wallabag/CoreBundle/Security/Authentication/Provider/WsseProvider.php @@ -44,6 +44,12 @@ class WsseProvider implements AuthenticationProviderInterface if (file_exists($this->cacheDir.'/'.$nonce) && file_get_contents($this->cacheDir.'/'.$nonce) + 300 > time()) { throw new NonceExpiredException('Previously used nonce detected'); } + + // If cache directory does not exist we create it + if (!is_dir($this->cacheDir)) { + mkdir($this->cacheDir, 0777, true); + } + file_put_contents($this->cacheDir.'/'.$nonce, time()); // Valide le Secret -- cgit v1.2.3 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: log for authentication on API --- .../CoreBundle/Controller/EntryController.php | 1 - .../CoreBundle/Repository/EntryRepository.php | 12 ++++++------ .../CoreBundle/Resources/config/services.xml | 2 ++ .../Authentication/Provider/WsseProvider.php | 21 +++++++++++++++++---- .../CoreBundle/Security/Firewall/WsseListener.php | 20 ++++++++++++++------ src/Wallabag/CoreBundle/Tests/WallabagTestCase.php | 2 -- 6 files changed, 39 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/Wallabag/CoreBundle/Controller/EntryController.php b/src/Wallabag/CoreBundle/Controller/EntryController.php index e0697ca3..5378486a 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 5ae1337a..1805cf3f 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 859665ca..ca2ba383 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 eaad9c63..c9b9b692 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 + // Check created time is not in the future + if (strtotime($created) > time()) { + throw new AuthenticationException("Back to the future..."); + } + + // Expire timestamp after 5 minutes if (time() - strtotime($created) > 300) { - return false; + throw new AuthenticationException("Too late for this timestamp... Watch your watch."); } - // Valide que le nonce est unique dans les 5 minutes + // 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 4d4f2145..d815d536 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 5f092318..edc7d992 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 { -- cgit v1.2.3 From d29bfaf139975fae71b73ebb316da4ce2205fc92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20L=C5=93uillet?= Date: Mon, 9 Feb 2015 22:40:20 +0100 Subject: fix return on API call and fix id in clear for user --- src/Wallabag/CoreBundle/Controller/WallabagRestController.php | 4 ++-- src/Wallabag/CoreBundle/Security/Firewall/WsseListener.php | 7 ++----- 2 files changed, 4 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/Wallabag/CoreBundle/Controller/WallabagRestController.php b/src/Wallabag/CoreBundle/Controller/WallabagRestController.php index 1df18247..75e5204e 100644 --- a/src/Wallabag/CoreBundle/Controller/WallabagRestController.php +++ b/src/Wallabag/CoreBundle/Controller/WallabagRestController.php @@ -43,7 +43,7 @@ class WallabagRestController extends Controller $entries = $this ->getDoctrine() ->getRepository('WallabagCoreBundle:Entry') - ->findEntries(1, $isArchived, $isStarred, $isDeleted, $sort, $order); + ->findEntries($this->getUser()->getId(), $isArchived, $isStarred, $isDeleted, $sort, $order); if (!is_array($entries)) { throw $this->createNotFoundException(); @@ -86,7 +86,7 @@ class WallabagRestController extends Controller $content = Extractor::extract($url); $entry = new Entry(); - $entry->setUserId(1); + $entry->setUserId($this->getUser()->getId()); $entry->setUrl($url); $entry->setTitle($request->request->get('title') ?: $content->getTitle()); $entry->setContent($content->getBody()); diff --git a/src/Wallabag/CoreBundle/Security/Firewall/WsseListener.php b/src/Wallabag/CoreBundle/Security/Firewall/WsseListener.php index d815d536..1296cb1f 100644 --- a/src/Wallabag/CoreBundle/Security/Firewall/WsseListener.php +++ b/src/Wallabag/CoreBundle/Security/Firewall/WsseListener.php @@ -44,6 +44,8 @@ class WsseListener implements ListenerInterface $authToken = $this->authenticationManager->authenticate($token); $this->securityContext->setToken($authToken); + + return; } catch (AuthenticationException $failed) { $failedMessage = 'WSSE Login failed for '.$token->getUsername().'. Why ? '.$failed->getMessage(); $this->logger->err($failedMessage); @@ -56,10 +58,5 @@ class WsseListener implements ListenerInterface return; } - - // By default deny authorization - $response = new Response(); - $response->setStatusCode(403); - $event->setResponse($response); } } -- cgit v1.2.3 From 5078e8360a69faef6a8a5fa1646cb3a15f0e78b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20L=C5=93uillet?= Date: Mon, 9 Feb 2015 22:43:06 +0100 Subject: PSR 3 --- src/Wallabag/CoreBundle/Security/Firewall/WsseListener.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/Wallabag/CoreBundle/Security/Firewall/WsseListener.php b/src/Wallabag/CoreBundle/Security/Firewall/WsseListener.php index 1296cb1f..6ffdfaf0 100644 --- a/src/Wallabag/CoreBundle/Security/Firewall/WsseListener.php +++ b/src/Wallabag/CoreBundle/Security/Firewall/WsseListener.php @@ -9,7 +9,7 @@ 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; +use Psr\Log\LoggerInterface; class WsseListener implements ListenerInterface { -- cgit v1.2.3 From 7ffb1e80bff2c54fe3fe4343484d377eda660c3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20L=C5=93uillet?= Date: Mon, 9 Feb 2015 22:54:29 +0100 Subject: replace services.xml into services.yml --- .../DependencyInjection/WallabagCoreExtension.php | 6 ++--- .../CoreBundle/Resources/config/services.xml | 29 ---------------------- .../CoreBundle/Resources/config/services.yml | 15 +++++++++++ 3 files changed, 18 insertions(+), 32 deletions(-) delete mode 100644 src/Wallabag/CoreBundle/Resources/config/services.xml create mode 100644 src/Wallabag/CoreBundle/Resources/config/services.yml (limited to 'src') diff --git a/src/Wallabag/CoreBundle/DependencyInjection/WallabagCoreExtension.php b/src/Wallabag/CoreBundle/DependencyInjection/WallabagCoreExtension.php index 7cc4165e..c6ecc99e 100644 --- a/src/Wallabag/CoreBundle/DependencyInjection/WallabagCoreExtension.php +++ b/src/Wallabag/CoreBundle/DependencyInjection/WallabagCoreExtension.php @@ -3,7 +3,7 @@ namespace Wallabag\CoreBundle\DependencyInjection; use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Loader\XmlFileLoader; +use Symfony\Component\DependencyInjection\Loader\YamlFileLoader; use Symfony\Component\HttpKernel\DependencyInjection\Extension; use Symfony\Component\Config\FileLocator; @@ -11,8 +11,8 @@ class WallabagCoreExtension extends Extension { public function load(array $configs, ContainerBuilder $container) { - $loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config')); - $loader->load('services.xml'); + $loader = new YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config')); + $loader->load('services.yml'); } public function getAlias() diff --git a/src/Wallabag/CoreBundle/Resources/config/services.xml b/src/Wallabag/CoreBundle/Resources/config/services.xml deleted file mode 100644 index ca2ba383..00000000 --- a/src/Wallabag/CoreBundle/Resources/config/services.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - - - - %kernel.cache_dir%/security/nonces - - - - - - - - - - - diff --git a/src/Wallabag/CoreBundle/Resources/config/services.yml b/src/Wallabag/CoreBundle/Resources/config/services.yml new file mode 100644 index 00000000..b066c1a3 --- /dev/null +++ b/src/Wallabag/CoreBundle/Resources/config/services.yml @@ -0,0 +1,15 @@ +services: + wallabag_core.twig.wallabag: + class: Wallabag\CoreBundle\Twig\Extension\WallabagExtension + tags: + - { name: twig.extension } + wsse.security.authentication.provider: + class: Wallabag\CoreBundle\Security\Authentication\Provider\WsseProvider + public: false + arguments: ['', '%kernel.cache_dir%/security/nonces'] + wsse.security.authentication.listener: + class: Wallabag\CoreBundle\Security\Firewall\WsseListener + public: false + tags: + - { name: monolog.logger, channel: wsse } + arguments: ['@security.context', '@security.authentication.manager', '@logger'] -- cgit v1.2.3 From c5e8ba25bb0d6d59b3275480f406b5ce3fa83b75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20L=C5=93uillet?= Date: Tue, 10 Feb 2015 08:35:43 +0100 Subject: getSalt method --- .../Controller/WallabagRestController.php | 27 ++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/Wallabag/CoreBundle/Controller/WallabagRestController.php b/src/Wallabag/CoreBundle/Controller/WallabagRestController.php index 75e5204e..96d2529a 100644 --- a/src/Wallabag/CoreBundle/Controller/WallabagRestController.php +++ b/src/Wallabag/CoreBundle/Controller/WallabagRestController.php @@ -8,10 +8,34 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Wallabag\CoreBundle\Entity\Entry; use Wallabag\CoreBundle\Entity\Tags; +use Wallabag\CoreBundle\Entity\User; use Wallabag\CoreBundle\Service\Extractor; class WallabagRestController extends Controller { + /** + * Retrieve salt for a giver user. + * + * @ApiDoc( + * parameters={ + * {"name"="username", "dataType"="string", "required"=true, "description"="username"} + * } + * ) + * @return string + */ + public function getSaltAction($username) + { + $user = $this + ->getDoctrine() + ->getRepository('WallabagCoreBundle:User') + ->findOneByUsername($username); + + if (is_null($user)) { + throw $this->createNotFoundException(); + } + + return $user->getSalt(); + } /** * Retrieve all entries. It could be filtered by many options. * @@ -85,8 +109,7 @@ class WallabagRestController extends Controller $url = $request->request->get('url'); $content = Extractor::extract($url); - $entry = new Entry(); - $entry->setUserId($this->getUser()->getId()); + $entry = new Entry($this->getUser()->getId()); $entry->setUrl($url); $entry->setTitle($request->request->get('title') ?: $content->getTitle()); $entry->setContent($content->getBody()); -- cgit v1.2.3 From d4c029f46ee3a3ea9715c388f6f9c9a1e65edf50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20L=C5=93uillet?= Date: Tue, 10 Feb 2015 12:12:44 +0100 Subject: review from @j0k3r --- src/Wallabag/CoreBundle/Controller/WallabagRestController.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src') diff --git a/src/Wallabag/CoreBundle/Controller/WallabagRestController.php b/src/Wallabag/CoreBundle/Controller/WallabagRestController.php index 96d2529a..ddb1f8a5 100644 --- a/src/Wallabag/CoreBundle/Controller/WallabagRestController.php +++ b/src/Wallabag/CoreBundle/Controller/WallabagRestController.php @@ -8,7 +8,6 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Wallabag\CoreBundle\Entity\Entry; use Wallabag\CoreBundle\Entity\Tags; -use Wallabag\CoreBundle\Entity\User; use Wallabag\CoreBundle\Service\Extractor; class WallabagRestController extends Controller @@ -109,7 +108,7 @@ class WallabagRestController extends Controller $url = $request->request->get('url'); $content = Extractor::extract($url); - $entry = new Entry($this->getUser()->getId()); + $entry = new Entry($this->getUser()); $entry->setUrl($url); $entry->setTitle($request->request->get('title') ?: $content->getTitle()); $entry->setContent($content->getBody()); -- cgit v1.2.3 From 92504e0dd489c0d11abc87bee42ffca717db0480 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20L=C5=93uillet?= Date: Tue, 10 Feb 2015 13:35:34 +0100 Subject: move dir check into constructor --- .../Security/Authentication/Provider/WsseProvider.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/Wallabag/CoreBundle/Security/Authentication/Provider/WsseProvider.php b/src/Wallabag/CoreBundle/Security/Authentication/Provider/WsseProvider.php index c9b9b692..7e6a5dfb 100644 --- a/src/Wallabag/CoreBundle/Security/Authentication/Provider/WsseProvider.php +++ b/src/Wallabag/CoreBundle/Security/Authentication/Provider/WsseProvider.php @@ -17,6 +17,11 @@ class WsseProvider implements AuthenticationProviderInterface { $this->userProvider = $userProvider; $this->cacheDir = $cacheDir; + + // If cache directory does not exist we create it + if (!is_dir($this->cacheDir)) { + mkdir($this->cacheDir, 0777, true); + } } public function authenticate(TokenInterface $token) @@ -54,11 +59,6 @@ class WsseProvider implements AuthenticationProviderInterface throw new NonceExpiredException('Previously used nonce detected'); } - // If cache directory does not exist we create it - if (!is_dir($this->cacheDir)) { - mkdir($this->cacheDir, 0777, true); - } - file_put_contents($this->cacheDir.'/'.$nonce, time()); // Validate Secret -- cgit v1.2.3