diff options
| author | Philipp Schüttlöffel <schuettloeffel@zqs.uni-hannover.de> | 2024-09-24 10:53:31 +0200 |
|---|---|---|
| committer | Philipp Schüttlöffel <schuettloeffel@zqs.uni-hannover.de> | 2024-09-24 10:53:31 +0200 |
| commit | 4459dd7917f4d1c34f40bb68f0e991e9c3d53e4c (patch) | |
| tree | 5c07151ae61276d334e88f6309c30d439a85c12e /lib/classes/restapi/consumer | |
| parent | da0022e5c1abbf9825ae76debaabdff7e8623bb4 (diff) | |
| parent | 97a188592c679890a25c37ab78463add76a52ff7 (diff) | |
Merge branch 'main' into issue-3911issue-3911
Diffstat (limited to 'lib/classes/restapi/consumer')
| -rw-r--r-- | lib/classes/restapi/consumer/Base.php | 226 | ||||
| -rw-r--r-- | lib/classes/restapi/consumer/HTTP.php | 50 | ||||
| -rw-r--r-- | lib/classes/restapi/consumer/OAuth.php | 231 | ||||
| -rw-r--r-- | lib/classes/restapi/consumer/Studip.php | 36 |
4 files changed, 0 insertions, 543 deletions
diff --git a/lib/classes/restapi/consumer/Base.php b/lib/classes/restapi/consumer/Base.php deleted file mode 100644 index 50f3150..0000000 --- a/lib/classes/restapi/consumer/Base.php +++ /dev/null @@ -1,226 +0,0 @@ -<?php -namespace RESTAPI\Consumer; - -use AuthUserMd5; -use DBManager; -use DBManagerException; -use PDO; - -/** - * Base consumer class for the rest api - * - * Consumers provide means for authenticating a user and the access - * permissions for routes are bound to specific consumers. - * - * @author Jan-Hendrik Willms <tleilax+studip@gmail.com> - * @license GPL 2 or later - * @since Stud.IP 3.0 - * @deprecated Since Stud.IP 5.0. Will be removed in Stud.IP 6.0. - */ -abstract class Base extends \SimpleORMap -{ - /** - * Each consumer type has to implement a detect feature which - * should extract crucial information from the request and return - * an instance of itself if the consumer detects a valid signature - * it can respond to. - * - * @param mixed $request_type Type of request (optional; defaults to any) - * @return mixed Detected consumer object or false - */ - abstract public static function detect($request_type = null); - - /* Concrete */ - - /** - * Configures the model. - * - * @param array $config Configuration array - */ - protected static function configure($config = []) - { - $config['db_table'] = 'api_consumers'; - - parent::configure($config); - } - - /** - * Stores all known consumer types - */ - protected static $known_types = []; - - /** - * Add a consumer type to the list of consumer types - * - * @param String $type Name of the type - * @param String $class Associated consumer class - */ - public static function addType($type, $class) - { - self::$known_types[$type] = $class; - } - - /** - * Removes a consumer type from the list of consumer types - * - * @param String $type Name of the type - */ - public static function removeType($type) - { - unset(self::$known_types[$type]); - } - - /** - * Overloaded find method. Will return a concrete specialized consumer - * object of the associated type. - * - * @param String $id Id of the consumer - * @return \RESTAPI\Consumer\Base Associated consumer object (derived - * from consumer base type) - * @throws \Exception if either consumer id or consumer type is invalid - */ - public static function find($id) - { - $query = "SELECT consumer_type - FROM api_consumers - WHERE consumer_id = :id"; - $statement = DBManager::get()->prepare($query); - $statement->bindValue(':id', $id); - $statement->execute(); - $type = $statement->fetchColumn(); - - if (!isset(self::$known_types[$type])) { - throw new \Exception('Consumer #' . $id . ' is of unknown type "' . $type . '"'); - } - - return new self::$known_types[$type]($id); - } - - /** - * Returns a list of all known consumers. - * - * @return array List of all known consumers (as specialized consumer - * objects) - */ - public static function findAll() - { - $query = "SELECT consumer_id FROM api_consumers"; - $statement = DBManager::get()->query($query); - $ids = $statement->fetchAll(PDO::FETCH_COLUMN); - - return array_map([self::class, 'find'], $ids); - } - - /** - * Creates a new consumer of the given type. - * - * @param String $type Name of the type - * @return \RESTAPI\Consumer\Base Consumer object of the given (derived - * from consumer base type) - * @throws \Exception if type is invalid - */ - public static function create($type) - { - if (!isset(self::$known_types[$type])) { - throw new \Exception('Consumer is of unknown type "' . $type . '"'); - } - - return new self::$known_types[$type]; - } - - /** - * This method is used to detect a consumer (of a specific type) by - * executing the detect method on all known consumer types. - * - * @param mixed $type Name of the type (optional; defaults to all types) - * @param mixed $request_type Type of request (optional; defaults to any) - * @return mixed Either the detected consumer or false if no consumer - * was detected - * @throws \Exception if type is invalid - */ - public static function detectConsumer($type = null, $request_type = null) - { - $needles = $type === null - ? array_keys(self::$known_types) - : [$type]; - foreach ($needles as $needle) { - if (!isset(self::$known_types)) { - throw new \Exception('Trying to detect consumer of unkown type "' . $needle . '"'); - } - $consumer_class = self::$known_types[$needle]; - if ($consumer = $consumer_class::detect($request_type)) { - return $consumer; - } - } - return false; - } - - /** - * Contains user information - */ - protected $user = null; - - /** - * Extended SimpleORMap constructor. A certain user can be injected upon - * creation. - * - * @param mixed $id Id of the consumer or null to create a new one - * @param mixed $user Either a user object or id to inject to the consumer - * or null if no user should be injected - */ - public function __construct($id = null, $user = null) - { - parent::__construct($id); - - if ($user !== null) { - $this->setUser($user); - } - } - - /** - * Retrieve the api permissions associated with this consumer. - * - * @return \RESTAPI\ConsumerPermissions Permission object for this consumer - */ - public function getPermissions() - { - return \RESTAPI\ConsumerPermissions::get($this->id); - } - - /** - * Inject a user to this consumer. Injecting in this context refers to - * "having a user authenticated by this consumer". - * - * @param mixed $user Either a user object or a user id - * @return \RESTAPI\Consumer\Base Returns instance of self to allow - * chaining - */ - public function setUser($user) - { - if (!is_object($user)) { - $user = \User::findFull($user); - } - $this->user = $user; - return $this; - } - - /** - * Returns whether the consumer has an injected user or not. - * - * @return bool True if a valid user is found, false otherwise - */ - public function hasUser() - { - return $this->user !== null && $this->user->id && $this->user->id !== 'nobody'; - } - - /** - * Return the injected user. - * - * @param mixed User object or false if no user was injected - */ - public function getUser() - { - return $this->user; - } -} diff --git a/lib/classes/restapi/consumer/HTTP.php b/lib/classes/restapi/consumer/HTTP.php deleted file mode 100644 index 97b0657..0000000 --- a/lib/classes/restapi/consumer/HTTP.php +++ /dev/null @@ -1,50 +0,0 @@ -<?php -namespace RESTAPI\Consumer; -use StudipAuthAbstract, RESTAPI\RouterException; - -/** - * Basic HTTP Authentication consumer for the rest api - * - * @author Jan-Hendrik Willms <tleilax+studip@gmail.com> - * @license GPL 2 or later - * @since Stud.IP 3.0 - * @deprecated Since Stud.IP 5.0. Will be removed in Stud.IP 6.0. - */ -class HTTP extends Base -{ - /** - * Detects if a user is authenticated via basic http authentication. - * The only supported authentication for now is via the url: - * - * http://username:password@host/path?query - * - * @param mixed $request_type Type of request (optional; defaults to any) - * @return mixed Instance of self if authentication was detected, false - * otherwise - * @throws RouterException if authentication fails - * @todo Integrate and test HTTP_AUTHORIZATION header authentication - */ - public static function detect($request_type = null) - { - if ( - isset($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW']) - || isset($_SERVER['HTTP_AUTHORIZATION']) - ) { - $user_id = false; - - if (isset($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW'])) { - $username = $_SERVER['PHP_AUTH_USER']; - $password = $_SERVER['PHP_AUTH_PW']; - } elseif (isset($_SERVER['HTTP_AUTHORIZATION'])) { - list($username, $password) = explode(':', base64_decode(mb_substr($_SERVER['HTTP_AUTHORIZATION'], 6))); - } - - $check = StudipAuthAbstract::CheckAuthentication($username, $password); - if ($check['uid'] && $check['uid'] !== 'nobody') { - return new self(null, $check['uid']); - } - - } - return false; - } -} diff --git a/lib/classes/restapi/consumer/OAuth.php b/lib/classes/restapi/consumer/OAuth.php deleted file mode 100644 index caf51c2..0000000 --- a/lib/classes/restapi/consumer/OAuth.php +++ /dev/null @@ -1,231 +0,0 @@ -<?php -namespace RESTAPI\Consumer; -use StudipAutoloader, DBManager, OAuthRequestVerifier, OAuthStore, OAuthServer, Exception; -use \RESTAPI\UserPermissions; - -StudipAutoloader::addAutoloadPath($GLOBALS['STUDIP_BASE_PATH'] . DIRECTORY_SEPARATOR . 'vendor/oauth-php/library/'); - -/** - * OAuth consumer for the rest api - * - * @author Jan-Hendrik Willms <tleilax+studip@gmail.com> - * @license GPL 2 or later - * @since Stud.IP 3.0 - * @deprecated Since Stud.IP 5.0. Will be removed in Stud.IP 6.0. - */ -class OAuth extends Base -{ - /** - * Configures the model. - * - * @param array $config Configuration array - */ - protected static function configure($config = []) - { - $config['default_values']['consumer_type'] = 'oauth'; - - $config['registered_callbacks']['before_store'][] = 'before_store'; - - parent::configure($config); - } - - /** - * Detects whether the request is authenticated via OAuth. - * - * @param mixed $request_type Type of request (optional; defaults to any) - * @return mixed Instance of self if authentication was detected, false - * otherwise - */ - public static function detect($request_type = null) - { - if (OAuthRequestVerifier::requestIsSigned() && $request_type !== 'request') { - $user_id = false; - - $parameters = (in_array($_SERVER['REQUEST_METHOD'], ['GET', 'POST'])) - ? null - : $GLOBALS['_' . $_SERVER['REQUEST_METHOD']]; - - $req = new OAuthRequestVerifier(null, null, $parameters); - - // Check oauth timestamp and deny access if timestamp is outdated - if ($req->getParam('oauth_timestamp') < strtotime('-6 hours')) { - return false; - } - $result = $req->verifyExtended('access'); - - // @todo - # self::$consumer_key = $result['consumer_key']; - - $query = "SELECT user_id FROM api_oauth_user_mapping WHERE oauth_id = :oauth_id"; - $statement = DBManager::get()->prepare($query); - $statement->bindValue(':oauth_id', $result['user_id']); - $statement->execute(); - $user_id = $statement->fetchColumn(); - - if (!$user_id) { - return false; - } - - $consumer = reset(self::findByAuth_Key($result['consumer_key'])); - $consumer->setUser($user_id); - return $consumer; - } else { - try { - // Check if there is a valid request token in the current request - // Returns an array with the consumer key, consumer secret, token, token secret and token type. - $rs = self::getServer()->authorizeVerify(); - - $query = "SELECT consumer_id - FROM api_consumers - WHERE auth_key = :key"; - $statement = DBManager::get()->prepare($query); - $statement->bindValue(':key', $rs['consumer_key']); - $statement->execute(); - $id = $statement->fetchColumn(); - - if ($id) { - return new self($id); - } - } catch (Exception $e) { - } - } - return false; - } - - /** - * Returns a singleton instance of the oauth server. - * - * @return OAuthServer The server object - */ - public static function getServer() - { - static $server = null; - if ($server === null) { - $server = new OAuthServer(null, null, null, 'SESSION', [], [ - 'allowed_uri_schemes' => [] - ]); - } - return $server; - } - - /** - * "Before store" trigger. Creates a clone of the consumer in the - * tables for the vendor oauth library. - */ - protected function before_store() - { - static $mapping = [ - 'auth_key' => 'consumer_key', - 'auth_secret' => 'consumer_secret', - 'active' => 'enabled', - 'contact' => 'requester_name', - 'email' => 'requester_email', - 'callback' => 'callback_uri', - 'url' => 'application_uri', - 'title' => 'application_title', - 'description' => 'application_descr', - 'notes' => 'application_notes', - 'type' => 'application_type', - 'commercial' => 'application_commercial', - ]; - - $consumer = []; - foreach ($mapping as $from => $to) { - $consumer[$to] = $this->$from; - } - - $query = "SELECT osr_id - FROM oauth_server_registry - WHERE osr_consumer_key = :key AND osr_consumer_secret = :secret"; - $statement = DBManager::get()->prepare($query); - $statement->bindValue(':key', $this->auth_key); - $statement->bindValue(':secret', $this->auth_secret); - $statement->execute(); - $consumer['id'] = $statement->fetchColumn(); - - $consumer_key = OAuthStore::instance('PDO')->updateConsumer($consumer, null, true); - - if ($this->isNew()) { - $consumer = OAuthStore::instance('PDO')->getConsumer($consumer_key, null, true); - $this->auth_key = $consumer['consumer_key']; - $this->auth_secret = $consumer['consumer_secret']; - } - } - - /** - * Grant oauth access for a user. - * - * @param mixed $user_id Specific user id or null to default to the - * injected user - * @throws Exception If no valid user is present - */ - public function grantAccess($user_id = null) - { - if ($user_id === null && $this->hasUser()) { - $user_id = $this->user->id; - } - if (!$user_id) { - throw new Exception('Can not grant access to unknown user'); - } - - UserPermissions::get($GLOBALS['user']->id)->set($this->id, true)->store(); - return self::getServer()->authorizeFinish(true, self::getOAuthId($user_id)); - } - - /** - * Revoke oauth access from a user. - * - * @param mixed $user_id Specific user id or null to default to the - * injected user - * @throws Exception If no valid user is present - */ - public function revokeAccess($user_id = null) - { - if ($user_id === null && $this->hasUser()) { - $user_id = $this->user->id; - } - if (!$user_id) { - throw new Exception('Can not revoke access from unknown user'); - } - - $query = "DELETE oauth_server_token - FROM oauth_server_token - JOIN oauth_server_registry - WHERE ost_usa_id_ref = :id AND osr_consumer_key = :key AND osr_consumer_secret = :secret"; - $statement = DBManager::get()->prepare($query); - $statement->bindValue(':id', self::getOAuthId($user_id)); - $statement->bindValue(':key', $this->auth_key); - $statement->bindValue(':secret', $this->auth_secret); - $statement->execute(); - - UserPermissions::get($GLOBALS['user']->id)->set($this->id, false)->store(); - return self::getServer()->authorizeFinish(false, self::getOAuthId($user_id)); - } - - /** - * Maps a user to an oauth id. This is neccessary due to the fact that - * the oauth lib works with different ids than Stud.IP. - * - * @param String $user_id Id of the user to get an oauth id for - * @return String The mapped oauth id - */ - public static function getOAuthId($user_id) - { - $query = "SELECT oauth_id FROM api_oauth_user_mapping WHERE user_id = :id"; - $statement = DBManager::get()->prepare($query); - $statement->bindValue(':id', $user_id); - $statement->execute(); - $oauth_id = $statement->fetchColumn(); - - if (!$oauth_id) { - $query = "INSERT INTO api_oauth_user_mapping (user_id, mkdate) - VALUES (:id, UNIX_TIMESTAMP())"; - $statement = DBManager::get()->prepare($query); - $statement->bindValue(':id', $user_id); - $statement->execute(); - $oauth_id = DBManager::get()->lastInsertId(); - } - - return $oauth_id; - } -} diff --git a/lib/classes/restapi/consumer/Studip.php b/lib/classes/restapi/consumer/Studip.php deleted file mode 100644 index 738dd75..0000000 --- a/lib/classes/restapi/consumer/Studip.php +++ /dev/null @@ -1,36 +0,0 @@ -<?php -namespace RESTAPI\Consumer; - -/** - * Stud.IP Session Consumer for the rest api - * - * @author Jan-Hendrik Willms <tleilax+studip@gmail.com> - * @license GPL 2 or later - * @since Stud.IP 3.0 - * @deprecated Since Stud.IP 5.0. Will be removed in Stud.IP 6.0. - */ -class Studip extends Base -{ - /** - * Detects a user via the Stud.IP session. If a session is present and - * valid, the auth and user object have already been set up by stud.ip - * functions, so we just need to check if these are present. - * - * @param mixed $request_type Type of request (optional; defaults to any) - * @return mixed Instance of self if authentication was detected, false - * otherwise - */ - public static function detect($request_type = null) - { - if ( - !isset($GLOBALS['auth']) - || !$GLOBALS['auth']->is_authenticated() - || $GLOBALS['user']->id === 'nobody' - || !\CSRFProtection::verifyRequest() - ) { - return false; - } - - return new self(null, $GLOBALS['user']->id); - } -} |
