diff --git a/src/Oauth2/MissingAccessTokenException.php b/src/Oauth2/MissingAccessTokenException.php new file mode 100644 index 00000000..0eb4ff0c --- /dev/null +++ b/src/Oauth2/MissingAccessTokenException.php @@ -0,0 +1,8 @@ +get = $get; + $this->post = $post; + $this->cookies = $cookies; + $this->files = $files; + $this->server = $server; + + if (empty($headers)) { + $this->headers = $this->readHeaders(); + } + } + + public function get($index = null, $default = null) + { + return $this->getPropertyValue('get', $index, $default); + } + + public function post($index = null, $default = null) + { + return $this->getPropertyValue('post', $index, $default); + } + + public function file($index = null, $default = null) + { + return $this->getPropertyValue('files', $index, $default); + } + + public function cookie($index = null, $default = null) + { + return $this->getPropertyValue('cookies', $index, $default); + } + + public function server($index = null, $default = null) + { + return $this->getPropertyValue('server', $index, $default); + } + + public function header($index = null, $default = null) + { + return $this->getPropertyValue('headers', $index, $default); + } + + protected function readHeaders() + { + $headers = array(); + foreach ($this->server() as $name => $value) { + if (substr($name, 0, 5) == 'HTTP_') { + $name = str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5))))); + $headers[$name] = $value; + } + } + + return $headers; + } + + protected function getPropertyValue($property, $index = null, $default = null) + { + if ( ! isset($this->{$property})) { + throw new InvalidArgumentException("Property '$property' does not exist."); + } + if (is_null($index)) { + return $this->{$property}; + } + + if ( ! array_key_exists($index, $this->{$property})) { + return $default; + } + + return $this->{$property}[$index]; + } +} diff --git a/src/Oauth2/RequestInterface.php b/src/Oauth2/RequestInterface.php new file mode 100644 index 00000000..458711ba --- /dev/null +++ b/src/Oauth2/RequestInterface.php @@ -0,0 +1,24 @@ +storages['session'] = $session; + $this->storages['session_scope'] = $session_scope; + + if (is_null($request)) { + $request = Request::buildFromGlobals(); + } + $this->request = $request; + } + + /** + * Checks if the Access Token is valid or not. + * + * @return bool + */ + public function isValid() + { + $access_token = $this->determineAccessToken(); + + $result = $this->storages['session']->validateAccessToken($access_token); + + if ( ! $result) { + return false; + } + + $this->accessToken = $access_token; + $this->sessionId = $result['id']; + $this->ownerType = $result['owner_type']; + $this->ownerId = $result['owner_id']; + + $this->sessionScopes = $this->storages['session_scope']->getScopes($this->sessionId); + + return true; + } + + /** + * Checks if the current session has the given scope(s). + * + * @param array + */ + public function hasScope($scopes) + { + if (is_string($scopes)) { + if (in_array($scopes, $this->sessionScopes)) { + return true; + } + return false; + } elseif (is_array($scopes)) { + foreach ($scopes as $scope) { + if ( ! in_array($scope, $this->sessionScopes)) { + return false; + } + } + return true; + } + + return false; + } + + protected function determineAccessToken() + { + if ($header = $this->request->header('Authorization')) { + $access_token = trim(str_replace('Bearer', '', $header)); + } else { + $method = $this->request->server('REQUEST_METHOD'); + $access_token = $this->request->{$method}($this->tokenKey); + } + + if (empty($access_token)) { + throw new MissingAccessTokenException('Access Token is Missing'); + } + + return $access_token; + } + +} diff --git a/src/Oauth2/Resource/Database.php b/src/Oauth2/Resource/Database.php deleted file mode 100644 index 8408df3a..00000000 --- a/src/Oauth2/Resource/Database.php +++ /dev/null @@ -1,59 +0,0 @@ - - * SELECT id, owner_type, owner_id FROM oauth_sessions WHERE access_token = - * $accessToken AND stage = 'granted' AND - * access_token_expires > UNIX_TIMESTAMP(now()) - * - * - * Response: - * - * - * Array - * ( - * [id] => (int) The session ID - * [owner_type] => (string) The session owner type - * [owner_id] => (string) The session owner's ID - * ) - * - * - * @param string $accessToken The access token - * @return array|bool Return an array on success or false on failure - */ - public function validateAccessToken($accessToken); - - /** - * Returns the scopes that the session is authorised with. - * - * Database query: - * - * - * SELECT scope FROM oauth_session_scopes WHERE session_id = - * $sessionId - * - * - * Response: - * - * - * Array - * ( - * [0] => (string) A scope - * [1] => (string) Another scope - * ... - * ) - * - * - * @param int $sessionId The session ID - * @return array A list of scopes - */ - public function sessionScopes($sessionId); -} \ No newline at end of file diff --git a/src/Oauth2/Resource/Server.php b/src/Oauth2/Resource/Server.php deleted file mode 100644 index 64a29d6e..00000000 --- a/src/Oauth2/Resource/Server.php +++ /dev/null @@ -1,253 +0,0 @@ - 'oauth_token' - ); - - /** - * Error codes. - * - * To provide i8ln errors just overwrite the keys - * - * @var array - */ - public $errors = array( - 'missing_access_token' => 'An access token was not presented with the request', - 'invalid_access_token' => 'The access token is not registered with the resource server', - 'missing_access_token_details' => 'The registered database abstractor did not return a valid access token details response', - 'invalid_access_token_scopes' => 'The registered database abstractor did not return a valid access token scopes response', - ); - - /** - * Constructor - * - * @access public - * @return void - */ - public function __construct($options = null) - { - if ($options !== null) { - $this->_config = array_merge($this->_config, $options); - } - } - - /** - * Magic method to test if access token represents a particular owner type - * @param string $method The method name - * @param mixed $arguements The method arguements - * @return bool If method is valid, and access token is owned by the requested party then true, - */ - public function __call($method, $arguements = null) - { - if (substr($method, 0, 2) === 'is') { - - if ($this->_type === strtolower(substr($method, 2))) { - return $this->_typeId; - } - - return false; - } - - trigger_error('Call to undefined function ' . $method . '()'); - } - - /** - * Register a database abstrator class - * - * @access public - * @param object $db A class that implements OAuth2ServerDatabase - * @return void - */ - public function registerDbAbstractor($db) - { - $this->_db = $db; - } - - /** - * Init function - * - * @access public - * @return void - */ - public function init() - { - $accessToken = null; - - $_SERVER['REQUEST_METHOD'] = isset($_SERVER['REQUEST_METHOD']) ? - $_SERVER['REQUEST_METHOD'] : - null; - - // Try and get the access token via an access_token or oauth_token parameter - switch ($_SERVER['REQUEST_METHOD']) - { - case 'POST': - $accessToken = isset($_POST[$this->_config['token_key']]) ? - $_POST[$this->_config['token_key']] : - null; - break; - - default: - $accessToken = isset($_GET[$this->_config['token_key']]) ? - $_GET[$this->_config['token_key']] : - null; - break; - } - - // Try and get an access token from the auth header - if (function_exists('getallheaders')) { - - $headers = getallheaders(); - - if (isset($headers['Authorization'])) { - - $rawToken = trim(str_replace('Bearer', '', $headers['Authorization'])); - - if ( ! empty($rawToken)) { - $accessToken = $rawToken; - } - } - } - - if ($accessToken) { - - $result = $this->_dbCall('validateAccessToken', $accessToken); - - if ($result === false) { - - throw new ClientException($this->errors['invalid_access_token']); - - } else { - - if ( ! array_key_exists('id', $result) || - ! array_key_exists('owner_id', $result) || - ! array_key_exists('owner_type', $result)) { - throw new ServerException($this->errors['missing_access_token_details']); - } - - $this->_accessToken = $accessToken; - $this->_type = $result['owner_type']; - $this->_typeId = $result['owner_id']; - - // Get the scopes - $scopes = $this->_dbCall('sessionScopes', $result['id']); - - if ( ! is_array($scopes)) - { - throw new ServerException($this->errors['invalid_access_token_scopes']); - } - - $this->_scopes = $scopes; - } - - } else { - - throw new ClientException($this->errors['missing_access_token']); - - } - } - - /** - * Test if the access token has a specific scope - * - * @param mixed $scopes Scope(s) to check - * - * @access public - * @return string|bool - */ - public function hasScope($scopes) - { - if (is_string($scopes)) { - - if (in_array($scopes, $this->_scopes)) { - return true; - } - - return false; - - } elseif (is_array($scopes)) { - - foreach ($scopes as $scope) { - - if ( ! in_array($scope, $this->_scopes)) { - return false; - } - - } - - return true; - } - - return false; - } - - /** - * Call database methods from the abstractor - * - * @return mixed The query result - */ - private function _dbCall() - { - if ($this->_db === null) { - throw new ServerException('No registered database abstractor'); - } - - if ( ! $this->_db instanceof Database) { - throw new ServerException('The registered database abstractor is not an instance of Oauth2\Resource\Database'); - } - - $args = func_get_args(); - $method = $args[0]; - unset($args[0]); - $params = array_values($args); - - return call_user_func_array(array($this->_db, $method), $params); - } -} \ No newline at end of file diff --git a/src/Oauth2/Storage/ClientEndpointInterface.php b/src/Oauth2/Storage/ClientEndpointInterface.php new file mode 100644 index 00000000..ae83eb93 --- /dev/null +++ b/src/Oauth2/Storage/ClientEndpointInterface.php @@ -0,0 +1,8 @@ +