Loading classes/OAuth2RequestHandler.php +20 −0 Original line number Diff line number Diff line Loading @@ -151,4 +151,24 @@ class OAuth2RequestHandler { return $expTime - $now; } public function validateToken(): void { $headers = apache_request_headers(); if (!isset($headers['Authorization'])) { throw new BadRequestException("Missing Authorization header"); } $authorizationHeader = explode(" ", $headers['Authorization']); if ($authorizationHeader[0] === "Bearer") { $bearer_token = $authorizationHeader[1]; } else { throw new BadRequestException("Invalid token type"); } $accessToken = $this->locator->getAccessTokenDAO()->getAccessToken($bearer_token); if ($accessToken->expired) { throw new UnauthorizedException("Access token is expired"); } } } classes/datalayer/mysql/MySQLAccessTokenDAO.php +16 −8 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ class MySQLAccessTokenDAO extends BaseMySQLDAO implements AccessTokenDAO { ); if ($stmt->execute($params)) { $accessToken->expired = false; return $accessToken; } else { error_log($stmt->errorInfo()[2]); Loading @@ -42,13 +43,18 @@ class MySQLAccessTokenDAO extends BaseMySQLDAO implements AccessTokenDAO { $dbh = $this->getDBHandler(); // Access token can be retrieved from code in 1 minute from the creation $stmt = $dbh->prepare("SELECT token, code, user_id, redirect_uri, client_id, creation_time, expiration_time, scope" . " FROM access_token WHERE code = :code"); // AND CURRENT_TIMESTAMP < TIMESTAMPADD(MINUTE, 1, creation_time) $stmt = $dbh->prepare("SELECT token, code, user_id, redirect_uri, client_id, creation_time, expiration_time, scope," . " (expiration_time < CURRENT_TIMESTAMP) AS expired " . " FROM access_token WHERE code = :code AND CURRENT_TIMESTAMP < TIMESTAMPADD(MINUTE, 1, creation_time)"); $stmt->bindParam(':code', $code); $stmt->execute(); $row = $stmt->fetch(); if (!$row) { return null; } return $this->getAccessTokenFromRow($row); } Loading @@ -56,22 +62,23 @@ class MySQLAccessTokenDAO extends BaseMySQLDAO implements AccessTokenDAO { $dbh = $this->getDBHandler(); $stmt = $dbh->prepare("SELECT token, code, user_id, redirect_uri, client_id, creation_time, expiration_time, scope" $stmt = $dbh->prepare("SELECT token, code, user_id, redirect_uri, client_id, creation_time, expiration_time, scope," . " (expiration_time < CURRENT_TIMESTAMP) AS expired " . " FROM access_token WHERE token = :token"); $stmt->bindParam(':token', $token); $stmt->execute(); $row = $stmt->fetch(); return $this->getAccessTokenFromRow($row); if (!$row) { return null; } private function getAccessTokenFromRow(?array $row): ?AccessToken { if ($row === null) { return null; return $this->getAccessTokenFromRow($row); } private function getAccessTokenFromRow(array $row): ?AccessToken { $token = new AccessToken(); $token->token = $row['token']; $token->code = $row['code']; Loading @@ -80,6 +87,7 @@ class MySQLAccessTokenDAO extends BaseMySQLDAO implements AccessTokenDAO { $token->clientId = $row['client_id']; $token->creationTime = $row['creation_time']; $token->expirationTime = $row['expiration_time']; $token->expired = $row['expired'] === "1"; $scope = null; if (isset($row['scope'])) { Loading classes/exceptions/UnauthorizedException.php 0 → 100644 +13 −0 Original line number Diff line number Diff line <?php namespace RAP; class UnauthorizedException extends \Exception { public $message; public function __construct($message) { $this->message = $message; } } classes/model/AccessToken.php +1 −0 Original line number Diff line number Diff line Loading @@ -9,6 +9,7 @@ class AccessToken { public $userId; public $creationTime; public $expirationTime; public $expired; public $redirectUri; public $clientId; public $scope; Loading include/rest-web-service.php +34 −13 Original line number Diff line number Diff line Loading @@ -42,9 +42,11 @@ Flight::route('GET ' . $WS_PREFIX . '/user-info', function() { */ Flight::route('GET ' . $WS_PREFIX . '/user/@userId', function($userId) { global $dao; global $locator; $locator->getOAuth2RequestHandler()->validateToken(); $user = $dao->findUserById($userId); $user = $locator->getUserDAO()->findUserById($userId); if ($user !== null) { Flight::json($user); } else { Loading @@ -58,19 +60,26 @@ Flight::route('GET ' . $WS_PREFIX . '/user/@userId', function($userId) { */ Flight::route('GET ' . $WS_PREFIX . '/user', function() { global $dao; global $locator; $locator->getOAuth2RequestHandler()->validateToken(); $searchText = Flight::request()->query['search']; $users = $dao->searchUser($searchText); $users = $locator->getUserDAO()->searchUser($searchText); Flight::json($users); }); /** * Create new user from identity data. Return the new user encoded in JSON. * This can be used to automatically import users without they explicitly * register (this is done for INAF eduGAIN users readling directly from LDAP). */ Flight::route('POST ' . $WS_PREFIX . '/user', function() { global $userHandler; global $locator; $locator->getOAuth2RequestHandler()->validateToken(); $postData = Flight::request()->data; Loading @@ -95,7 +104,7 @@ Flight::route('POST ' . $WS_PREFIX . '/user', function() { $user->addIdentity($identity); $userHandler->saveUser($user); $locator->getUserHandler()->saveUser($user); Flight::json($user); }); Loading @@ -105,15 +114,27 @@ Flight::route('POST ' . $WS_PREFIX . '/user', function() { */ Flight::route('POST ' . $WS_PREFIX . '/join', function() { global $userHandler; global $locator; $locator->getOAuth2RequestHandler()->validateToken(); $postData = Flight::request()->data; $userHandler->joinUsers($postData['user1'], $postData['user2']); $userId1 = $postData['user1']; $userId2 = $postData['user2']; // if the join has success, returns the remaining user id echo $postData['user1']; }); $user1 = $locator->getUserDAO()->findUserById($userId1); if ($user1 === null) { throw new BadRequestException("User " . $userId1 . " doesn't exists"); } Flight::route('GET ' . $WS_PREFIX . '/test', function() { $user2 = $locator->getUserDAO()->findUserById($userId2); if ($user2 === null) { throw new BadRequestException("User " . $userId2 . " doesn't exists"); } $locator->getUserHandler()->joinUsers($user1, $user2); // if the join has success, returns the remaining user id echo $userId1; }); Loading
classes/OAuth2RequestHandler.php +20 −0 Original line number Diff line number Diff line Loading @@ -151,4 +151,24 @@ class OAuth2RequestHandler { return $expTime - $now; } public function validateToken(): void { $headers = apache_request_headers(); if (!isset($headers['Authorization'])) { throw new BadRequestException("Missing Authorization header"); } $authorizationHeader = explode(" ", $headers['Authorization']); if ($authorizationHeader[0] === "Bearer") { $bearer_token = $authorizationHeader[1]; } else { throw new BadRequestException("Invalid token type"); } $accessToken = $this->locator->getAccessTokenDAO()->getAccessToken($bearer_token); if ($accessToken->expired) { throw new UnauthorizedException("Access token is expired"); } } }
classes/datalayer/mysql/MySQLAccessTokenDAO.php +16 −8 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ class MySQLAccessTokenDAO extends BaseMySQLDAO implements AccessTokenDAO { ); if ($stmt->execute($params)) { $accessToken->expired = false; return $accessToken; } else { error_log($stmt->errorInfo()[2]); Loading @@ -42,13 +43,18 @@ class MySQLAccessTokenDAO extends BaseMySQLDAO implements AccessTokenDAO { $dbh = $this->getDBHandler(); // Access token can be retrieved from code in 1 minute from the creation $stmt = $dbh->prepare("SELECT token, code, user_id, redirect_uri, client_id, creation_time, expiration_time, scope" . " FROM access_token WHERE code = :code"); // AND CURRENT_TIMESTAMP < TIMESTAMPADD(MINUTE, 1, creation_time) $stmt = $dbh->prepare("SELECT token, code, user_id, redirect_uri, client_id, creation_time, expiration_time, scope," . " (expiration_time < CURRENT_TIMESTAMP) AS expired " . " FROM access_token WHERE code = :code AND CURRENT_TIMESTAMP < TIMESTAMPADD(MINUTE, 1, creation_time)"); $stmt->bindParam(':code', $code); $stmt->execute(); $row = $stmt->fetch(); if (!$row) { return null; } return $this->getAccessTokenFromRow($row); } Loading @@ -56,22 +62,23 @@ class MySQLAccessTokenDAO extends BaseMySQLDAO implements AccessTokenDAO { $dbh = $this->getDBHandler(); $stmt = $dbh->prepare("SELECT token, code, user_id, redirect_uri, client_id, creation_time, expiration_time, scope" $stmt = $dbh->prepare("SELECT token, code, user_id, redirect_uri, client_id, creation_time, expiration_time, scope," . " (expiration_time < CURRENT_TIMESTAMP) AS expired " . " FROM access_token WHERE token = :token"); $stmt->bindParam(':token', $token); $stmt->execute(); $row = $stmt->fetch(); return $this->getAccessTokenFromRow($row); if (!$row) { return null; } private function getAccessTokenFromRow(?array $row): ?AccessToken { if ($row === null) { return null; return $this->getAccessTokenFromRow($row); } private function getAccessTokenFromRow(array $row): ?AccessToken { $token = new AccessToken(); $token->token = $row['token']; $token->code = $row['code']; Loading @@ -80,6 +87,7 @@ class MySQLAccessTokenDAO extends BaseMySQLDAO implements AccessTokenDAO { $token->clientId = $row['client_id']; $token->creationTime = $row['creation_time']; $token->expirationTime = $row['expiration_time']; $token->expired = $row['expired'] === "1"; $scope = null; if (isset($row['scope'])) { Loading
classes/exceptions/UnauthorizedException.php 0 → 100644 +13 −0 Original line number Diff line number Diff line <?php namespace RAP; class UnauthorizedException extends \Exception { public $message; public function __construct($message) { $this->message = $message; } }
classes/model/AccessToken.php +1 −0 Original line number Diff line number Diff line Loading @@ -9,6 +9,7 @@ class AccessToken { public $userId; public $creationTime; public $expirationTime; public $expired; public $redirectUri; public $clientId; public $scope; Loading
include/rest-web-service.php +34 −13 Original line number Diff line number Diff line Loading @@ -42,9 +42,11 @@ Flight::route('GET ' . $WS_PREFIX . '/user-info', function() { */ Flight::route('GET ' . $WS_PREFIX . '/user/@userId', function($userId) { global $dao; global $locator; $locator->getOAuth2RequestHandler()->validateToken(); $user = $dao->findUserById($userId); $user = $locator->getUserDAO()->findUserById($userId); if ($user !== null) { Flight::json($user); } else { Loading @@ -58,19 +60,26 @@ Flight::route('GET ' . $WS_PREFIX . '/user/@userId', function($userId) { */ Flight::route('GET ' . $WS_PREFIX . '/user', function() { global $dao; global $locator; $locator->getOAuth2RequestHandler()->validateToken(); $searchText = Flight::request()->query['search']; $users = $dao->searchUser($searchText); $users = $locator->getUserDAO()->searchUser($searchText); Flight::json($users); }); /** * Create new user from identity data. Return the new user encoded in JSON. * This can be used to automatically import users without they explicitly * register (this is done for INAF eduGAIN users readling directly from LDAP). */ Flight::route('POST ' . $WS_PREFIX . '/user', function() { global $userHandler; global $locator; $locator->getOAuth2RequestHandler()->validateToken(); $postData = Flight::request()->data; Loading @@ -95,7 +104,7 @@ Flight::route('POST ' . $WS_PREFIX . '/user', function() { $user->addIdentity($identity); $userHandler->saveUser($user); $locator->getUserHandler()->saveUser($user); Flight::json($user); }); Loading @@ -105,15 +114,27 @@ Flight::route('POST ' . $WS_PREFIX . '/user', function() { */ Flight::route('POST ' . $WS_PREFIX . '/join', function() { global $userHandler; global $locator; $locator->getOAuth2RequestHandler()->validateToken(); $postData = Flight::request()->data; $userHandler->joinUsers($postData['user1'], $postData['user2']); $userId1 = $postData['user1']; $userId2 = $postData['user2']; // if the join has success, returns the remaining user id echo $postData['user1']; }); $user1 = $locator->getUserDAO()->findUserById($userId1); if ($user1 === null) { throw new BadRequestException("User " . $userId1 . " doesn't exists"); } Flight::route('GET ' . $WS_PREFIX . '/test', function() { $user2 = $locator->getUserDAO()->findUserById($userId2); if ($user2 === null) { throw new BadRequestException("User " . $userId2 . " doesn't exists"); } $locator->getUserHandler()->joinUsers($user1, $user2); // if the join has success, returns the remaining user id echo $userId1; });