From 3657aef20853465956fcc53b9a7c3476fcb02aae Mon Sep 17 00:00:00 2001 From: sundowndev Date: Thu, 26 Jul 2018 15:49:29 +0200 Subject: [PATCH] Session authentication and logout --- server/src/Controller/SessionController.php | 73 ++++++---- server/src/Repository/SessionRepository.php | 142 ++++++++++++++++++++ server/src/Service/Session.php | 29 ++-- 3 files changed, 202 insertions(+), 42 deletions(-) diff --git a/server/src/Controller/SessionController.php b/server/src/Controller/SessionController.php index 9216276..01ebe63 100644 --- a/server/src/Controller/SessionController.php +++ b/server/src/Controller/SessionController.php @@ -2,6 +2,7 @@ namespace App\Controller; +use App\Repository\SessionRepository; use App\Repository\UserRepository; use App\Service\Database; use App\Service\JsonResponse; @@ -12,6 +13,7 @@ class SessionController { private $db; private $jsonResponse; + private $sessionRepository; private $request; private $session; private $security; @@ -24,6 +26,7 @@ class SessionController $this->jsonResponse = new JsonResponse(); $this->session = new Session($this->db, $this->jsonResponse); $this->security = $this->session->security; + $this->sessionRepository = new SessionRepository($this->db, $this->security); $this->userRepository = new UserRepository($this->db); } @@ -32,69 +35,89 @@ class SessionController */ public function auth() { - $content = $this->request->getContentAsArray(); + $body = $this->request->getContent()->jsonToArray(); - if (empty($content['username']) || empty($content['password'])) { + if (empty($body['username']) || empty($body['password'])) { print $this->jsonResponse->create(400, 'Please provide an username and password.'); exit(); } - $user = $this->userRepository->findOneByUsername($content['username']); + $user = $this->userRepository->findOneByUsername($body['username']); - if (!$this->security->passwordVerify($content['password'], $user['password'])) { + if (is_null($user) || !$this->security->passwordVerify($body['password'], $user['password'])) { print $this->jsonResponse->create(403, 'Bad credentials.'); exit(); } - $token = $this->security->generateToken(); + $token = $this->security->generateToken($user['id']); $expire_at = new \DateTime(); - $expire_at->add(new \DateInterval('P1D')); // Expire in 1 day + $expire_at->modify('+1 Day'); // Expire in 1 day - $stmt = $this->db->getConnection()->prepare('INSERT INTO Session (`user_id`, `token`, `issued_at`, `expire_at`) VALUES(:user_id, :token, NOW(), :expire_at)'); - $stmt->bindParam(':user_id', $user['id']); - $stmt->bindParam(':token', $token); - $stmt->bindParam(':expire_at', date_format($expire_at, 'Y-m-d')); - $stmt->execute(); + $this->sessionRepository->create($user['id'], $token, $expire_at->format('Y-m-d H:i:s')); print $this->jsonResponse->create(200, 'Welcome ' . $user['name'], [ - 'jwt_token' => $token, + 'token' => $token, 'expire_at' => $expire_at, ]); } - /** + /**db * Register route */ public function signup() { - $content = json_decode(trim(file_get_contents("php://input")), true); + $body = $this->request->getContent()->jsonToArray(); - if (empty($content['username']) || empty($content['email']) || empty($content['password'])) { + if (empty($body['username']) || empty($body['email']) || empty($body['password'])) { print $this->jsonResponse->create(400, 'Please provide an username, email and password.'); exit(); } $user = [ - 'username' => $content['username'], - 'email' => $content['email'], - 'password' => $this->security->passwordHash($content['password']), + 'username' => $body['username'], + 'email' => $body['email'], + 'password' => $this->security->passwordHash($body['password']), ]; - $stmt = $this->db->getConnection()->prepare('INSERT INTO User (`name`, `email`, `password`) VALUES(:name, :email, :password)'); - $stmt->bindParam(':name', $user['username']); - $stmt->bindParam(':email', $user['email']); - $stmt->bindParam(':password', $user['password']); - $stmt->execute(); + if (!is_null($this->userRepository->findOneByEmail($user['email']))) { + print $this->jsonResponse->create(403, 'Email already registered!'); + exit(); + } - print $this->jsonResponse->create(200, 'Success! Now send your credentials to /auth to sign in.', [ + $this->userRepository->create($user['username'], $user['email'], $user['password']); + + print $this->jsonResponse->create(200, 'Success. Now send your credentials to /auth to sign in.', [ 'username' => $user['username'], 'email' => $user['email'], ]); } + /** + * Signout + */ public function signout() { - // logout + if (!$this->security->isLogged()) { + print $this->security->NotAllowedRequest(); + exit(); + } + + $this->sessionRepository->deleteByToken($this->security->getBearerToken()); + + print $this->jsonResponse->create(200, 'Good bye.', []); + } + + /** + * Whois route + */ + public function me() + { + if (!$this->security->isLogged()) { + print $this->security->NotAllowedRequest(); + exit(); + } + + print $this->jsonResponse->create(200, 'hello!', $this->session->getUser()); } } \ No newline at end of file diff --git a/server/src/Repository/SessionRepository.php b/server/src/Repository/SessionRepository.php index e69de29..a01a4b2 100644 --- a/server/src/Repository/SessionRepository.php +++ b/server/src/Repository/SessionRepository.php @@ -0,0 +1,142 @@ +db = $db; + $this->security = $security; + $this->tableName = 'Session'; + } + + /** + * @return mixed + */ + public function findAll() + { + $stmt = $this->db->getConnection()->prepare('SELECT * FROM ' . $this->tableName . ' ORDER BY id DESC'); + $stmt->execute(); + + return $stmt->fetchAll(\PDO::FETCH_ASSOC); + } + + /** + * @param $id + * @return null + */ + public function findOneById($id) + { + $stmt = $this->db->getConnection()->prepare('SELECT * FROM ' . $this->tableName . ' WHERE id = :id'); + $stmt->bindParam(':id', $id, \PDO::PARAM_INT); + $stmt->execute(); + + $task = $stmt->fetch(\PDO::FETCH_ASSOC); + + if (!$task) { + return null; + } else { + return $task; + } + } + + public function findUserBySessionToken($token) + { + $stmt = $this->db->getConnection()->prepare('SELECT s.token, s.expire_at, u.id, u.name, u.email FROM ' . $this->tableName . ' AS s INNER JOIN User as u ON s.user_id = u.id WHERE s.token = :token'); + $stmt->bindParam(':token', $token, \PDO::PARAM_STR); + $stmt->execute(); + + return $stmt->fetch(\PDO::FETCH_ASSOC); + } + + /** + * @param $user_id + * @param $csrf + * @param $cookie + */ + public function create($user_id, $token, $expiration) + { + $stmt = $this->db->getConnection()->prepare('INSERT INTO Session (`user_id`, `token`, `issued_at`, `expire_at`) VALUES(:user_id, :token, NOW(), :expire_at)'); + $stmt->bindParam(':user_id', $user_id); + $stmt->bindParam(':token', $token); + $stmt->bindParam(':expire_at', $expiration); + $stmt->execute(); + } + + /** + * @param $id + * @param $data + * @return mixed + */ + public function updateById($id, $data) + { + $session = $this->findOneById($id); + + /*$stmt = $this->db->getConnection()->prepare('UPDATE ' . $this->tableName . ' SET user_id = :user_id, title = :title, description = :description, creation_date = :creation_date, status = :status'); + $stmt->bindParam(':user_id', $data['user_id'] ?? $task['user_id'], \PDO::PARAM_INT); + $stmt->bindParam(':title', $data['title'] ?? $task['title'], \PDO::PARAM_STR); + $stmt->bindParam(':description', $data['description'] ?? $task['description'], \PDO::PARAM_STR); + $stmt->bindParam(':creation_date', $data['creation_date'] ?? $task['creation_date']); + $stmt->bindParam(':status', $data['status'] ?? $task['status'], \PDO::PARAM_INT); + $stmt->execute(); + + return $data;*/ + } + + /** + * @param $id + */ + public function deleteById($id) + { + $stmt = $this->db->getConnection()->prepare('DELETE FROM ' . $this->tableName . ' WHERE id = :id'); + $stmt->bindParam(':id', $id, \PDO::PARAM_INT); + $stmt->execute(); + } + + /** + * @param $token + */ + public function deleteByToken($token) + { + $stmt = $this->db->getConnection()->prepare('DELETE FROM ' . $this->tableName . ' WHERE token = :token'); + $stmt->bindParam(':token', $token, \PDO::PARAM_STR); + $stmt->execute(); + } + + /** + * @param $userId + */ + public function deleteByUserId($userId) + { + $stmt = $this->db->getConnection()->prepare('DELETE FROM ' . $this->tableName . ' WHERE user_id = :user_id'); + $stmt->bindParam(':user_id', $userId, \PDO::PARAM_INT); + $stmt->execute(); + } +} \ No newline at end of file diff --git a/server/src/Service/Session.php b/server/src/Service/Session.php index 090efb6..5cc09d5 100644 --- a/server/src/Service/Session.php +++ b/server/src/Service/Session.php @@ -2,6 +2,8 @@ namespace App\Service; +use App\Repository\SessionRepository; + /** * Class Session * @package App\Service @@ -9,6 +11,7 @@ namespace App\Service; class Session { private $db; + private $sessionRepository; public $security; /** @@ -18,23 +21,7 @@ class Session { $this->db = $database; $this->security = new Security($this, $jsonResponse); - } - - /** - * @param $user_id - * @param $csrf - * @param $cookie - */ - public function create($user_id) - { - $token = $this->security->generateToken(); - $expire_at = new \DateTime(); - - $stmt = $this->db->getConnection()->prepare('INSERT INTO Session (user_id, token, issued_at, expire_at) VALUES(:user_id, :token, NOW(), :expire_at)'); - $stmt->bindParam(':user_id', $user_id, \PDO::PARAM_INT); - $stmt->bindParam(':token', $token, \PDO::PARAM_STR); - $stmt->bindParam(':expire_at', $expire_at); - $stmt->execute(); + $this->sessionRepository = new SessionRepository($this->db, $this->security); } /** @@ -55,4 +42,12 @@ class Session return $session; } } + + /** + * @return array + */ + public function getUser() + { + return $this->sessionRepository->findUserBySessionToken($this->security->getBearerToken()); + } } \ No newline at end of file