From c3235553ddc2bb5965f6fe00e750cfe4aac9ccdf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20L=C5=93uillet?= Date: Sat, 31 Jan 2015 15:14:10 +0100 Subject: first implementation of security --- .../Authentication/Provider/WsseProvider.php | 59 ++++++++++++++++++++++ .../Authentication/Token/WsseUserToken.php | 23 +++++++++ .../CoreBundle/Security/Firewall/WsseListener.php | 58 +++++++++++++++++++++ 3 files changed, 140 insertions(+) create mode 100644 src/Wallabag/CoreBundle/Security/Authentication/Provider/WsseProvider.php create mode 100644 src/Wallabag/CoreBundle/Security/Authentication/Token/WsseUserToken.php create mode 100644 src/Wallabag/CoreBundle/Security/Firewall/WsseListener.php (limited to 'src/Wallabag/CoreBundle/Security') diff --git a/src/Wallabag/CoreBundle/Security/Authentication/Provider/WsseProvider.php b/src/Wallabag/CoreBundle/Security/Authentication/Provider/WsseProvider.php new file mode 100644 index 00000000..ac57e27d --- /dev/null +++ b/src/Wallabag/CoreBundle/Security/Authentication/Provider/WsseProvider.php @@ -0,0 +1,59 @@ +userProvider = $userProvider; + $this->cacheDir = $cacheDir; + } + + public function authenticate(TokenInterface $token) + { + $user = $this->userProvider->loadUserByUsername($token->getUsername()); + + if ($user && $this->validateDigest($token->digest, $token->nonce, $token->created, $user->getPassword())) { + $authenticatedToken = new WsseUserToken($user->getRoles()); + $authenticatedToken->setUser($user); + + return $authenticatedToken; + } + + throw new AuthenticationException('The WSSE authentication failed.'); + } + + protected function validateDigest($digest, $nonce, $created, $secret) + { + // Expire le timestamp après 5 minutes + if (time() - strtotime($created) > 300) { + return false; + } + + // Valide que le nonce est unique dans les 5 minutes + if (file_exists($this->cacheDir.'/'.$nonce) && file_get_contents($this->cacheDir.'/'.$nonce) + 300 > time()) { + throw new NonceExpiredException('Previously used nonce detected'); + } + file_put_contents($this->cacheDir.'/'.$nonce, time()); + + // Valide le Secret + $expected = base64_encode(sha1(base64_decode($nonce).$created.$secret, true)); + + return $digest === $expected; + } + + public function supports(TokenInterface $token) + { + return $token instanceof WsseUserToken; + } +} \ No newline at end of file diff --git a/src/Wallabag/CoreBundle/Security/Authentication/Token/WsseUserToken.php b/src/Wallabag/CoreBundle/Security/Authentication/Token/WsseUserToken.php new file mode 100644 index 00000000..b189e22a --- /dev/null +++ b/src/Wallabag/CoreBundle/Security/Authentication/Token/WsseUserToken.php @@ -0,0 +1,23 @@ +setAuthenticated(count($roles) > 0); + } + + public function getCredentials() + { + return ''; + } +} \ No newline at end of file diff --git a/src/Wallabag/CoreBundle/Security/Firewall/WsseListener.php b/src/Wallabag/CoreBundle/Security/Firewall/WsseListener.php new file mode 100644 index 00000000..b2474785 --- /dev/null +++ b/src/Wallabag/CoreBundle/Security/Firewall/WsseListener.php @@ -0,0 +1,58 @@ +securityContext = $securityContext; + $this->authenticationManager = $authenticationManager; + } + + public function handle(GetResponseEvent $event) + { + $request = $event->getRequest(); + + $wsseRegex = '/UsernameToken Username="([^"]+)", PasswordDigest="([^"]+)", Nonce="([^"]+)", Created="([^"]+)"/'; + if (!$request->headers->has('x-wsse') || 1 !== preg_match($wsseRegex, $request->headers->get('x-wsse'), $matches)) { + return; + } + + $token = new WsseUserToken(); + $token->setUser($matches[1]); + + $token->digest = $matches[2]; + $token->nonce = $matches[3]; + $token->created = $matches[4]; + + try { + $authToken = $this->authenticationManager->authenticate($token); + + $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; + + // Deny authentication with a '403 Forbidden' HTTP response + $response = new Response(); + $response->setStatusCode(403); + $event->setResponse($response); + + } + } +} \ No newline at end of file -- cgit v1.2.3