From 31b36f23e7de9565d3c7ab81b76768b54b97ccdc Mon Sep 17 00:00:00 2001 From: Daniel Horrigan Date: Fri, 28 Dec 2012 15:12:16 -0500 Subject: [PATCH 001/113] Starting the reorganization --- src/Oauth2/MissingAccessTokenException.php | 8 + src/Oauth2/Request.php | 94 +++++++ src/Oauth2/RequestInterface.php | 24 ++ src/Oauth2/Resource.php | 110 ++++++++ src/Oauth2/Resource/Database.php | 59 ---- src/Oauth2/Resource/Server.php | 253 ------------------ .../Storage/ClientEndpointInterface.php | 8 + src/Oauth2/Storage/ClientInterface.php | 8 + src/Oauth2/Storage/ScopeInterface.php | 8 + src/Oauth2/Storage/SessionInterface.php | 8 + src/Oauth2/Storage/SessionScopeInterface.php | 8 + 11 files changed, 276 insertions(+), 312 deletions(-) create mode 100644 src/Oauth2/MissingAccessTokenException.php create mode 100644 src/Oauth2/Request.php create mode 100644 src/Oauth2/RequestInterface.php create mode 100644 src/Oauth2/Resource.php delete mode 100644 src/Oauth2/Resource/Database.php delete mode 100644 src/Oauth2/Resource/Server.php create mode 100644 src/Oauth2/Storage/ClientEndpointInterface.php create mode 100644 src/Oauth2/Storage/ClientInterface.php create mode 100644 src/Oauth2/Storage/ScopeInterface.php create mode 100644 src/Oauth2/Storage/SessionInterface.php create mode 100644 src/Oauth2/Storage/SessionScopeInterface.php 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 @@ + Date: Fri, 4 Jan 2013 14:44:02 -0500 Subject: [PATCH 002/113] Changing Case --- .../Authentication/Database.php | 0 .../Authentication/Server.php | 0 src/{Oauth2 => OAuth2}/Client/IDP.php | 0 src/{Oauth2 => OAuth2}/Client/Provider.php | 0 .../Client/Provider/Blooie.php | 0 .../Client/Provider/Facebook.php | 0 .../Client/Provider/Foursquare.php | 0 .../Client/Provider/Github.php | 0 .../Client/Provider/Google.php | 0 .../Client/Provider/Instagram.php | 0 .../Client/Provider/Mailchimp.php | 0 .../Client/Provider/Mailru.php | 0 .../Client/Provider/Paypal.php | 0 .../Client/Provider/Soundcloud.php | 0 .../Client/Provider/Vkontakte.php | 0 .../Client/Provider/Windowslive.php | 0 .../Client/Provider/Yandex.php | 0 src/{Oauth2 => OAuth2}/Client/Token.php | 0 .../Client/Token/Access.php | 0 .../Client/Token/Authorize.php | 0 src/OAuth2/GrantTypeInterface.php | 8 ++++ .../MissingAccessTokenException.php | 0 src/{Oauth2 => OAuth2}/Request.php | 0 src/{Oauth2 => OAuth2}/RequestInterface.php | 0 src/{Oauth2 => OAuth2}/Resource.php | 0 src/OAuth2/Server.php | 42 +++++++++++++++++++ .../Storage/ClientEndpointInterface.php | 0 .../Storage/ClientInterface.php | 0 .../Storage/ScopeInterface.php | 0 .../Storage/SessionInterface.php | 0 .../Storage/SessionScopeInterface.php | 0 31 files changed, 50 insertions(+) rename src/{Oauth2 => OAuth2}/Authentication/Database.php (100%) rename src/{Oauth2 => OAuth2}/Authentication/Server.php (100%) rename src/{Oauth2 => OAuth2}/Client/IDP.php (100%) rename src/{Oauth2 => OAuth2}/Client/Provider.php (100%) rename src/{Oauth2 => OAuth2}/Client/Provider/Blooie.php (100%) rename src/{Oauth2 => OAuth2}/Client/Provider/Facebook.php (100%) rename src/{Oauth2 => OAuth2}/Client/Provider/Foursquare.php (100%) rename src/{Oauth2 => OAuth2}/Client/Provider/Github.php (100%) rename src/{Oauth2 => OAuth2}/Client/Provider/Google.php (100%) rename src/{Oauth2 => OAuth2}/Client/Provider/Instagram.php (100%) rename src/{Oauth2 => OAuth2}/Client/Provider/Mailchimp.php (100%) rename src/{Oauth2 => OAuth2}/Client/Provider/Mailru.php (100%) rename src/{Oauth2 => OAuth2}/Client/Provider/Paypal.php (100%) rename src/{Oauth2 => OAuth2}/Client/Provider/Soundcloud.php (100%) rename src/{Oauth2 => OAuth2}/Client/Provider/Vkontakte.php (100%) rename src/{Oauth2 => OAuth2}/Client/Provider/Windowslive.php (100%) rename src/{Oauth2 => OAuth2}/Client/Provider/Yandex.php (100%) rename src/{Oauth2 => OAuth2}/Client/Token.php (100%) rename src/{Oauth2 => OAuth2}/Client/Token/Access.php (100%) rename src/{Oauth2 => OAuth2}/Client/Token/Authorize.php (100%) create mode 100644 src/OAuth2/GrantTypeInterface.php rename src/{Oauth2 => OAuth2}/MissingAccessTokenException.php (100%) rename src/{Oauth2 => OAuth2}/Request.php (100%) rename src/{Oauth2 => OAuth2}/RequestInterface.php (100%) rename src/{Oauth2 => OAuth2}/Resource.php (100%) create mode 100644 src/OAuth2/Server.php rename src/{Oauth2 => OAuth2}/Storage/ClientEndpointInterface.php (100%) rename src/{Oauth2 => OAuth2}/Storage/ClientInterface.php (100%) rename src/{Oauth2 => OAuth2}/Storage/ScopeInterface.php (100%) rename src/{Oauth2 => OAuth2}/Storage/SessionInterface.php (100%) rename src/{Oauth2 => OAuth2}/Storage/SessionScopeInterface.php (100%) diff --git a/src/Oauth2/Authentication/Database.php b/src/OAuth2/Authentication/Database.php similarity index 100% rename from src/Oauth2/Authentication/Database.php rename to src/OAuth2/Authentication/Database.php diff --git a/src/Oauth2/Authentication/Server.php b/src/OAuth2/Authentication/Server.php similarity index 100% rename from src/Oauth2/Authentication/Server.php rename to src/OAuth2/Authentication/Server.php diff --git a/src/Oauth2/Client/IDP.php b/src/OAuth2/Client/IDP.php similarity index 100% rename from src/Oauth2/Client/IDP.php rename to src/OAuth2/Client/IDP.php diff --git a/src/Oauth2/Client/Provider.php b/src/OAuth2/Client/Provider.php similarity index 100% rename from src/Oauth2/Client/Provider.php rename to src/OAuth2/Client/Provider.php diff --git a/src/Oauth2/Client/Provider/Blooie.php b/src/OAuth2/Client/Provider/Blooie.php similarity index 100% rename from src/Oauth2/Client/Provider/Blooie.php rename to src/OAuth2/Client/Provider/Blooie.php diff --git a/src/Oauth2/Client/Provider/Facebook.php b/src/OAuth2/Client/Provider/Facebook.php similarity index 100% rename from src/Oauth2/Client/Provider/Facebook.php rename to src/OAuth2/Client/Provider/Facebook.php diff --git a/src/Oauth2/Client/Provider/Foursquare.php b/src/OAuth2/Client/Provider/Foursquare.php similarity index 100% rename from src/Oauth2/Client/Provider/Foursquare.php rename to src/OAuth2/Client/Provider/Foursquare.php diff --git a/src/Oauth2/Client/Provider/Github.php b/src/OAuth2/Client/Provider/Github.php similarity index 100% rename from src/Oauth2/Client/Provider/Github.php rename to src/OAuth2/Client/Provider/Github.php diff --git a/src/Oauth2/Client/Provider/Google.php b/src/OAuth2/Client/Provider/Google.php similarity index 100% rename from src/Oauth2/Client/Provider/Google.php rename to src/OAuth2/Client/Provider/Google.php diff --git a/src/Oauth2/Client/Provider/Instagram.php b/src/OAuth2/Client/Provider/Instagram.php similarity index 100% rename from src/Oauth2/Client/Provider/Instagram.php rename to src/OAuth2/Client/Provider/Instagram.php diff --git a/src/Oauth2/Client/Provider/Mailchimp.php b/src/OAuth2/Client/Provider/Mailchimp.php similarity index 100% rename from src/Oauth2/Client/Provider/Mailchimp.php rename to src/OAuth2/Client/Provider/Mailchimp.php diff --git a/src/Oauth2/Client/Provider/Mailru.php b/src/OAuth2/Client/Provider/Mailru.php similarity index 100% rename from src/Oauth2/Client/Provider/Mailru.php rename to src/OAuth2/Client/Provider/Mailru.php diff --git a/src/Oauth2/Client/Provider/Paypal.php b/src/OAuth2/Client/Provider/Paypal.php similarity index 100% rename from src/Oauth2/Client/Provider/Paypal.php rename to src/OAuth2/Client/Provider/Paypal.php diff --git a/src/Oauth2/Client/Provider/Soundcloud.php b/src/OAuth2/Client/Provider/Soundcloud.php similarity index 100% rename from src/Oauth2/Client/Provider/Soundcloud.php rename to src/OAuth2/Client/Provider/Soundcloud.php diff --git a/src/Oauth2/Client/Provider/Vkontakte.php b/src/OAuth2/Client/Provider/Vkontakte.php similarity index 100% rename from src/Oauth2/Client/Provider/Vkontakte.php rename to src/OAuth2/Client/Provider/Vkontakte.php diff --git a/src/Oauth2/Client/Provider/Windowslive.php b/src/OAuth2/Client/Provider/Windowslive.php similarity index 100% rename from src/Oauth2/Client/Provider/Windowslive.php rename to src/OAuth2/Client/Provider/Windowslive.php diff --git a/src/Oauth2/Client/Provider/Yandex.php b/src/OAuth2/Client/Provider/Yandex.php similarity index 100% rename from src/Oauth2/Client/Provider/Yandex.php rename to src/OAuth2/Client/Provider/Yandex.php diff --git a/src/Oauth2/Client/Token.php b/src/OAuth2/Client/Token.php similarity index 100% rename from src/Oauth2/Client/Token.php rename to src/OAuth2/Client/Token.php diff --git a/src/Oauth2/Client/Token/Access.php b/src/OAuth2/Client/Token/Access.php similarity index 100% rename from src/Oauth2/Client/Token/Access.php rename to src/OAuth2/Client/Token/Access.php diff --git a/src/Oauth2/Client/Token/Authorize.php b/src/OAuth2/Client/Token/Authorize.php similarity index 100% rename from src/Oauth2/Client/Token/Authorize.php rename to src/OAuth2/Client/Token/Authorize.php diff --git a/src/OAuth2/GrantTypeInterface.php b/src/OAuth2/GrantTypeInterface.php new file mode 100644 index 00000000..c8eb83c8 --- /dev/null +++ b/src/OAuth2/GrantTypeInterface.php @@ -0,0 +1,8 @@ +getIdentifier(); + } + $this->grantTypes[$identifier] = $grant_type; + } + + public function setScopeDelimeter($scope_delimeter) + { + $this->scopeDelimeter = $scope_delimeter; + } + + public function setExpiresIn($expires_in) + { + $this->expiresIn = $expires_in; + } + +} diff --git a/src/Oauth2/Storage/ClientEndpointInterface.php b/src/OAuth2/Storage/ClientEndpointInterface.php similarity index 100% rename from src/Oauth2/Storage/ClientEndpointInterface.php rename to src/OAuth2/Storage/ClientEndpointInterface.php diff --git a/src/Oauth2/Storage/ClientInterface.php b/src/OAuth2/Storage/ClientInterface.php similarity index 100% rename from src/Oauth2/Storage/ClientInterface.php rename to src/OAuth2/Storage/ClientInterface.php diff --git a/src/Oauth2/Storage/ScopeInterface.php b/src/OAuth2/Storage/ScopeInterface.php similarity index 100% rename from src/Oauth2/Storage/ScopeInterface.php rename to src/OAuth2/Storage/ScopeInterface.php diff --git a/src/Oauth2/Storage/SessionInterface.php b/src/OAuth2/Storage/SessionInterface.php similarity index 100% rename from src/Oauth2/Storage/SessionInterface.php rename to src/OAuth2/Storage/SessionInterface.php diff --git a/src/Oauth2/Storage/SessionScopeInterface.php b/src/OAuth2/Storage/SessionScopeInterface.php similarity index 100% rename from src/Oauth2/Storage/SessionScopeInterface.php rename to src/OAuth2/Storage/SessionScopeInterface.php From 373ddf9f343f6672dd20ecdadb7924236fbd44a2 Mon Sep 17 00:00:00 2001 From: Daniel Horrigan Date: Fri, 4 Jan 2013 14:55:13 -0500 Subject: [PATCH 003/113] Changing Case in namespaces --- composer.json | 4 ++-- src/OAuth2/Authentication/Database.php | 2 +- src/OAuth2/Authentication/Server.php | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/composer.json b/composer.json index f2a89158..bebe9423 100644 --- a/composer.json +++ b/composer.json @@ -35,10 +35,10 @@ ], "autoload": { "psr-0": { - "Oauth2": "src/" + "OAuth2": "src/" } }, "suggest": { "lncd/oauth2-facebook": "Adds support for Facebook as an IDP" } -} \ No newline at end of file +} diff --git a/src/OAuth2/Authentication/Database.php b/src/OAuth2/Authentication/Database.php index d4ef203f..7a1398e4 100644 --- a/src/OAuth2/Authentication/Database.php +++ b/src/OAuth2/Authentication/Database.php @@ -1,6 +1,6 @@ Date: Fri, 4 Jan 2013 17:21:24 -0500 Subject: [PATCH 004/113] Fixing Resource bugs and moving the Request dep to a setter. --- src/OAuth2/MissingAccessTokenException.php | 4 +- src/OAuth2/Resource.php | 44 +++++++++++++++++----- 2 files changed, 36 insertions(+), 12 deletions(-) diff --git a/src/OAuth2/MissingAccessTokenException.php b/src/OAuth2/MissingAccessTokenException.php index 0eb4ff0c..d9d605ad 100644 --- a/src/OAuth2/MissingAccessTokenException.php +++ b/src/OAuth2/MissingAccessTokenException.php @@ -2,7 +2,7 @@ namespace OAuth2; -class MissingAccessTokenException +class MissingAccessTokenException extends \Exception { - + } diff --git a/src/OAuth2/Resource.php b/src/OAuth2/Resource.php index 285b4cb4..44b7436f 100644 --- a/src/OAuth2/Resource.php +++ b/src/OAuth2/Resource.php @@ -3,8 +3,8 @@ namespace OAuth2; use OutOfBoundsException; -use Storage\SessionInterface; -use Storage\SessionScopeInterface; +use OAuth2\Storage\SessionInterface; +use OAuth2\Storage\SessionScopeInterface; class Resource { @@ -29,19 +29,37 @@ class Resource * * @param SessionInterface The Session Storage Object * @param SessionScopeInterface The Session Scope Storage Object - * @param RequestInterface The Request Object */ - public function __construct(SessionInterface $session, SessionScopeInterface $session_scope, RequestInterface $request = null) + public function __construct(SessionInterface $session, SessionScopeInterface $session_scope) { $this->storages['session'] = $session; $this->storages['session_scope'] = $session_scope; + } - if (is_null($request)) { - $request = Request::buildFromGlobals(); - } + /** + * Sets the Request Object + * + * @param RequestInterface The Request Object + */ + public function setRequest(RequestInterface $request) + { $this->request = $request; } + /** + * Gets the Request object. It will create one from the globals if one is not set. + * + * @return RequestInterface + */ + public function getRequest() + { + if ($this->request === null) { + $this->request = Request::buildFromGlobals(); + } + + return $this->request; + } + /** * Checks if the Access Token is valid or not. * @@ -91,13 +109,19 @@ class Resource return false; } + /** + * Reads in the Access Token from the headers. + * + * @return string + * @throws MissingAccessTokenException + */ protected function determineAccessToken() { - if ($header = $this->request->header('Authorization')) { + if ($header = $this->getRequest()->header('Authorization')) { $access_token = trim(str_replace('Bearer', '', $header)); } else { - $method = $this->request->server('REQUEST_METHOD'); - $access_token = $this->request->{$method}($this->tokenKey); + $method = $this->getRequest()->server('REQUEST_METHOD'); + $access_token = $this->getRequest()->{$method}($this->tokenKey); } if (empty($access_token)) { From 89e89a73dc174d43f0118e2ab59ddab33f4f4275 Mon Sep 17 00:00:00 2001 From: Daniel Horrigan Date: Mon, 7 Jan 2013 10:31:28 -0500 Subject: [PATCH 005/113] Changing 'user_credentials' to password --- src/OAuth2/Authentication/Server.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/OAuth2/Authentication/Server.php b/src/OAuth2/Authentication/Server.php index 61306c5d..6f5f3f4e 100644 --- a/src/OAuth2/Authentication/Server.php +++ b/src/OAuth2/Authentication/Server.php @@ -48,7 +48,7 @@ class Server */ private $_grantTypes = array( 'authorization_code', - 'user_credentials', + 'password', 'refresh_token', ); @@ -379,7 +379,7 @@ class Server return $this->completeAuthCodeGrant($authParams, $params); break; - case 'user_credentials': + case 'password': return $this->completeUserCredentialsGrant($authParams, $params); break; @@ -542,7 +542,7 @@ class Server $params = array(); if ( ! isset($authParams['user_auth_callback'])) { - throw new \InvalidArgumentException('You must set a user_auth_callback when using the user_credentials grant type.'); + throw new \InvalidArgumentException('You must set a user_auth_callback when using the password grant type.'); } // Client ID @@ -582,7 +582,7 @@ class Server $params['grant_type'] = $_POST['grant_type']; } - if ($params['grant_type'] == 'user_credentials') + if ($params['grant_type'] == 'password') { // Check if user's u+p are correct $userId = call_user_func($authParams['user_auth_callback']); From c12472857b088bdbd8b12bfbe49b8c81dce03918 Mon Sep 17 00:00:00 2001 From: Daniel Horrigan Date: Tue, 8 Jan 2013 16:35:29 -0500 Subject: [PATCH 006/113] Changed Case of Oauth2 namespace to OAuth2 namespace --- README.md | 2 +- src/OAuth2/Authentication/Server.php | 6 +-- src/OAuth2/Client/IDP.php | 14 +++--- src/OAuth2/Client/Provider/Blooie.php | 8 ++-- src/OAuth2/Client/Provider/Facebook.php | 4 +- src/OAuth2/Client/Provider/Foursquare.php | 6 +-- src/OAuth2/Client/Provider/Github.php | 2 +- src/OAuth2/Client/Token.php | 4 +- src/OAuth2/Client/Token/Access.php | 4 +- src/OAuth2/Client/Token/Authorize.php | 2 +- tests/authentication/database_mock.php | 2 +- tests/authentication/server_test.php | 56 +++++++++++------------ tests/resource/database_mock.php | 2 +- tests/resource/server_test.php | 8 ++-- 14 files changed, 60 insertions(+), 60 deletions(-) diff --git a/README.md b/README.md index ff47bfce..06e193a5 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ The framework is provided as a Composer package which can be installed by adding ```javascript { "require": { - "lncd\Oauth2": "*" + "lncd\OAuth2": "*" } } ``` diff --git a/src/OAuth2/Authentication/Server.php b/src/OAuth2/Authentication/Server.php index 259d0ffb..755ca976 100644 --- a/src/OAuth2/Authentication/Server.php +++ b/src/OAuth2/Authentication/Server.php @@ -639,7 +639,7 @@ class Server $userId = call_user_func($this->_grantTypeCallbacks['password'], $params['username'], $params['password']); if ($userId === false) { - throw new \Oauth2\Authentication\ClientException($this->errors['invalid_credentials'], 0); + throw new \OAuth2\Authentication\ClientException($this->errors['invalid_credentials'], 0); } // Generate an access token @@ -730,7 +730,7 @@ class Server $sessionId = $this->_dbCall('validateRefreshToken', $params['refresh_token'], $params['client_id']); if ($sessionId === false) { - throw new \Oauth2\Authentication\ClientException($this->errors['invalid_refresh'], 0); + throw new \OAuth2\Authentication\ClientException($this->errors['invalid_refresh'], 0); } // Generate new tokens @@ -778,7 +778,7 @@ class Server } if ( ! $this->_db instanceof Database) { - throw new ServerException('Registered database abstractor is not an instance of Oauth2\Authentication\Database'); + throw new ServerException('Registered database abstractor is not an instance of OAuth2\Authentication\Database'); } $args = func_get_args(); diff --git a/src/OAuth2/Client/IDP.php b/src/OAuth2/Client/IDP.php index 2dbe182b..092da0e6 100644 --- a/src/OAuth2/Client/IDP.php +++ b/src/OAuth2/Client/IDP.php @@ -100,9 +100,9 @@ abstract class IDP { abstract public function urlAccessToken(); - abstract public function urlUserDetails(\Oauth2\Client\Token\Access $token); + abstract public function urlUserDetails(\OAuth2\Client\Token\Access $token); - abstract public function userDetails($response, \Oauth2\Client\Token\Access $token); + abstract public function userDetails($response, \OAuth2\Client\Token\Access $token); public function authorize($options = array()) { @@ -191,24 +191,24 @@ abstract class IDP { if (isset($result['error']) && ! empty($result['error'])) { - throw new \Oauth2\Client\IDPException($result); + throw new \OAuth2\Client\IDPException($result); } switch ($params['grant_type']) { case 'authorization_code': - return \Oauth2\Client\Token::factory('access', $result); + return \OAuth2\Client\Token::factory('access', $result); break; case 'refresh_token': - return \Oauth2\Client\Token::factory('refresh', $result); + return \OAuth2\Client\Token::factory('refresh', $result); break; } } - public function getUserDetails(\Oauth2\Client\Token\Access $token) + public function getUserDetails(\OAuth2\Client\Token\Access $token) { $url = $this->urlUserDetails($token); @@ -223,7 +223,7 @@ abstract class IDP { catch (\Guzzle\Http\Exception\BadResponseException $e) { $raw_response = explode("\n", $e->getResponse()); - throw new \Oauth2\Client\IDPException(end($raw_response)); + throw new \OAuth2\Client\IDPException(end($raw_response)); } } diff --git a/src/OAuth2/Client/Provider/Blooie.php b/src/OAuth2/Client/Provider/Blooie.php index 8078690e..9ae7dc45 100755 --- a/src/OAuth2/Client/Provider/Blooie.php +++ b/src/OAuth2/Client/Provider/Blooie.php @@ -1,14 +1,14 @@ $token->access_token, diff --git a/src/OAuth2/Client/Provider/Facebook.php b/src/OAuth2/Client/Provider/Facebook.php index 53aba543..cd41be17 100755 --- a/src/OAuth2/Client/Provider/Facebook.php +++ b/src/OAuth2/Client/Provider/Facebook.php @@ -9,7 +9,7 @@ * @license http://philsturgeon.co.uk/code/dbad-license */ -class Facebook extends Oauth2\Client\IDP +class Facebook extends OAuth2\Client\IDP { protected $scope = array('offline_access', 'email', 'read_stream'); @@ -23,7 +23,7 @@ class Facebook extends Oauth2\Client\IDP return 'https://graph.facebook.com/oauth/access_token'; } - public function getUserInfo(Oauth2\Token\Access $token) + public function getUserInfo(OAuth2\Token\Access $token) { $url = 'https://graph.facebook.com/me?'.http_build_query(array( 'access_token' => $token->access_token, diff --git a/src/OAuth2/Client/Provider/Foursquare.php b/src/OAuth2/Client/Provider/Foursquare.php index ebf81cb1..1c2740f8 100755 --- a/src/OAuth2/Client/Provider/Foursquare.php +++ b/src/OAuth2/Client/Provider/Foursquare.php @@ -9,8 +9,8 @@ * @license http://philsturgeon.co.uk/code/dbad-license */ -class Foursquare extends Oauth2\Client\IDP -{ +class Foursquare extends OAuth2\Client\IDP +{ public $method = 'POST'; public function urlAuthorize() @@ -23,7 +23,7 @@ class Foursquare extends Oauth2\Client\IDP return 'https://foursquare.com/oauth2/access_token'; } - public function getUserInfo(Oauth2\Token\Access $token) + public function getUserInfo(OAuth2\Token\Access $token) { $url = 'https://api.foursquare.com/v2/users/self?'.http_build_query(array( 'oauth_token' => $token->access_token, diff --git a/src/OAuth2/Client/Provider/Github.php b/src/OAuth2/Client/Provider/Github.php index acfd59ff..5ca9b512 100755 --- a/src/OAuth2/Client/Provider/Github.php +++ b/src/OAuth2/Client/Provider/Github.php @@ -9,7 +9,7 @@ * @license http://philsturgeon.co.uk/code/dbad-license */ -class OAuth2_Provider_Github extends Oauth2\Client\IDP +class OAuth2_Provider_Github extends OAuth2\Client\IDP { public function urlAuthorize() { diff --git a/src/OAuth2/Client/Token.php b/src/OAuth2/Client/Token.php index 2cb15b12..e4bae4bc 100755 --- a/src/OAuth2/Client/Token.php +++ b/src/OAuth2/Client/Token.php @@ -1,6 +1,6 @@ oauth = new Oauth2\Authentication\Server(); + $this->oauth = new OAuth2\Authentication\Server(); require_once 'database_mock.php'; $this->oauthdb = new OAuthdb(); - $this->assertInstanceOf('Oauth2\Authentication\Database', $this->oauthdb); + $this->assertInstanceOf('OAuth2\Authentication\Database', $this->oauthdb); $this->oauth->registerDbAbstractor($this->oauthdb); } public function test_setupWithOptions() { - $o = new Oauth2\Authentication\Server(array( + $o = new OAuth2\Authentication\Server(array( 'access_token_ttl' => 86400 )); @@ -116,7 +116,7 @@ class Authentication_Server_test extends PHPUnit_Framework_TestCase } /** - * @expectedException Oauth2\Authentication\ClientException + * @expectedException OAuth2\Authentication\ClientException * @expectedExceptionCode 0 */ public function test_checkClientAuthoriseParams_missingClientId() @@ -125,7 +125,7 @@ class Authentication_Server_test extends PHPUnit_Framework_TestCase } /** - * @expectedException Oauth2\Authentication\ClientException + * @expectedException OAuth2\Authentication\ClientException * @expectedExceptionCode 0 */ public function test_checkClientAuthoriseParams_missingRedirectUri() @@ -136,7 +136,7 @@ class Authentication_Server_test extends PHPUnit_Framework_TestCase } /** - * @expectedException Oauth2\Authentication\ClientException + * @expectedException OAuth2\Authentication\ClientException * @expectedExceptionCode 0 */ public function test_checkClientAuthoriseParams_missingResponseType() @@ -148,7 +148,7 @@ class Authentication_Server_test extends PHPUnit_Framework_TestCase } /** - * @expectedException Oauth2\Authentication\ClientException + * @expectedException OAuth2\Authentication\ClientException * @expectedExceptionCode 0 */ public function test_checkClientAuthoriseParams_missingScopes() @@ -162,7 +162,7 @@ class Authentication_Server_test extends PHPUnit_Framework_TestCase } /** - * @expectedException Oauth2\Authentication\ClientException + * @expectedException OAuth2\Authentication\ClientException * @expectedExceptionCode 4 */ public function test_checkClientAuthoriseParams_invalidScopes() @@ -176,7 +176,7 @@ class Authentication_Server_test extends PHPUnit_Framework_TestCase } /** - * @expectedException Oauth2\Authentication\ClientException + * @expectedException OAuth2\Authentication\ClientException * @expectedExceptionCode 8 */ public function test_checkClientAuthoriseParams_invalidClient() @@ -190,7 +190,7 @@ class Authentication_Server_test extends PHPUnit_Framework_TestCase } /** - * @expectedException Oauth2\Authentication\ClientException + * @expectedException OAuth2\Authentication\ClientException * @expectedExceptionCode 3 */ public function test_checkClientAuthoriseParams_invalidResponseType() @@ -247,7 +247,7 @@ class Authentication_Server_test extends PHPUnit_Framework_TestCase } /** - * @expectedException Oauth2\Authentication\ClientException + * @expectedException OAuth2\Authentication\ClientException * @expectedExceptionCode 7 */ public function test_issueAccessTokenNoRegisteredGrant() @@ -537,7 +537,7 @@ class Authentication_Server_test extends PHPUnit_Framework_TestCase } /** - * @expectedException Oauth2\Authentication\ClientException + * @expectedException OAuth2\Authentication\ClientException * @expectedExceptionCode 0 */ public function test_issueAccessToken_refresh_tokenMissingToken() @@ -584,7 +584,7 @@ class Authentication_Server_test extends PHPUnit_Framework_TestCase } /** - * @expectedException Oauth2\Authentication\ClientException + * @expectedException OAuth2\Authentication\ClientException * @expectedExceptionCode 0 */ public function test_issueAccessToken_invalid_refresh_token() @@ -632,7 +632,7 @@ class Authentication_Server_test extends PHPUnit_Framework_TestCase } /** - * @expectedException Oauth2\Authentication\ServerException + * @expectedException OAuth2\Authentication\ServerException * @expectedExceptionCode 0 */ public function test_issueAccessToken_password_grant_Missing_Callback() @@ -707,7 +707,7 @@ class Authentication_Server_test extends PHPUnit_Framework_TestCase } /** - * @expectedException Oauth2\Authentication\ClientException + * @expectedException OAuth2\Authentication\ClientException * @expectedExceptionCode 0 */ public function test_issueAccessToken_password_grant_wrongCreds() @@ -726,7 +726,7 @@ class Authentication_Server_test extends PHPUnit_Framework_TestCase } /** - * @expectedException Oauth2\Authentication\ClientException + * @expectedException OAuth2\Authentication\ClientException * @expectedExceptionCode 0 */ public function test_issueAccessToken_password_grant_missingUsername() @@ -743,7 +743,7 @@ class Authentication_Server_test extends PHPUnit_Framework_TestCase } /** - * @expectedException Oauth2\Authentication\ClientException + * @expectedException OAuth2\Authentication\ClientException * @expectedExceptionCode 0 */ public function test_issueAccessToken_password_grant_missingPassword() @@ -761,7 +761,7 @@ class Authentication_Server_test extends PHPUnit_Framework_TestCase } /** - * @expectedException Oauth2\Authentication\ClientException + * @expectedException OAuth2\Authentication\ClientException * @expectedExceptionCode 0 */ public function test_issueAccessToken_missingGrantType() @@ -770,7 +770,7 @@ class Authentication_Server_test extends PHPUnit_Framework_TestCase } /** - * @expectedException Oauth2\Authentication\ClientException + * @expectedException OAuth2\Authentication\ClientException * @expectedExceptionCode 7 */ public function test_issueAccessToken_unsupportedGrantType() @@ -781,7 +781,7 @@ class Authentication_Server_test extends PHPUnit_Framework_TestCase } /** - * @expectedException Oauth2\Authentication\ClientException + * @expectedException OAuth2\Authentication\ClientException * @expectedExceptionCode 0 */ public function test_completeAuthCodeGrant_missingClientId() @@ -794,7 +794,7 @@ class Authentication_Server_test extends PHPUnit_Framework_TestCase } /** - * @expectedException Oauth2\Authentication\ClientException + * @expectedException OAuth2\Authentication\ClientException * @expectedExceptionCode 0 */ public function test_completeAuthCodeGrant_missingClientSecret() @@ -809,7 +809,7 @@ class Authentication_Server_test extends PHPUnit_Framework_TestCase } /** - * @expectedException Oauth2\Authentication\ClientException + * @expectedException OAuth2\Authentication\ClientException * @expectedExceptionCode 0 */ public function test_completeAuthCodeGrant_missingRedirectUri() @@ -825,7 +825,7 @@ class Authentication_Server_test extends PHPUnit_Framework_TestCase } /** - * @expectedException Oauth2\Authentication\ClientException + * @expectedException OAuth2\Authentication\ClientException * @expectedExceptionCode 8 */ public function test_completeAuthCodeGrant_invalidClient() @@ -842,7 +842,7 @@ class Authentication_Server_test extends PHPUnit_Framework_TestCase } /** - * @expectedException Oauth2\Authentication\ClientException + * @expectedException OAuth2\Authentication\ClientException * @expectedExceptionCode 0 */ public function test_completeAuthCodeGrant_missingCode() @@ -859,7 +859,7 @@ class Authentication_Server_test extends PHPUnit_Framework_TestCase } /** - * @expectedException Oauth2\Authentication\ClientException + * @expectedException OAuth2\Authentication\ClientException * @expectedExceptionCode 9 */ public function test_completeAuthCodeGrant_invalidCode() @@ -877,7 +877,7 @@ class Authentication_Server_test extends PHPUnit_Framework_TestCase } /** - * @expectedException Oauth2\Authentication\ServerException + * @expectedException OAuth2\Authentication\ServerException * @expectedExceptionMessage No registered database abstractor */ public function test_noRegisteredDatabaseAbstractor() @@ -894,8 +894,8 @@ class Authentication_Server_test extends PHPUnit_Framework_TestCase } /** - * @expectedException Oauth2\Authentication\ServerException - * @expectedExceptionMessage Registered database abstractor is not an instance of Oauth2\Authentication\Database + * @expectedException OAuth2\Authentication\ServerException + * @expectedExceptionMessage Registered database abstractor is not an instance of OAuth2\Authentication\Database */ public function test_invalidRegisteredDatabaseAbstractor() { diff --git a/tests/resource/database_mock.php b/tests/resource/database_mock.php index 52c698d8..39469bac 100644 --- a/tests/resource/database_mock.php +++ b/tests/resource/database_mock.php @@ -1,6 +1,6 @@ server = new Oauth2\Resource\Server(); + $this->server = new OAuth2\Resource\Server(); $this->db = new ResourceDB(); - $this->assertInstanceOf('Oauth2\Resource\Database', $this->db); + $this->assertInstanceOf('OAuth2\Resource\Database', $this->db); $this->server->registerDbAbstractor($this->db); } @@ -72,7 +72,7 @@ class Resource_Server_test extends PHPUnit_Framework_TestCase { } /** - * @expectedException \Oauth2\Resource\ClientException + * @expectedException \OAuth2\Resource\ClientException * @expectedExceptionMessage An access token was not presented with the request */ function test_init_missingToken() @@ -81,7 +81,7 @@ class Resource_Server_test extends PHPUnit_Framework_TestCase { } /** - * @expectedException \Oauth2\Resource\ClientException + * @expectedException \OAuth2\Resource\ClientException * @expectedExceptionMessage The access token is not registered with the resource server */ function test_init_wrongToken() From 2727ba00789cde7c4f4a605f70c2c4f5f7d1f6ea Mon Sep 17 00:00:00 2001 From: Daniel Horrigan Date: Thu, 17 Jan 2013 15:19:01 -0500 Subject: [PATCH 007/113] Adding a few Getters to the Resource, moving Exceptions and adding some new ones. --- .../Exception/InvalidGrantTypeException.php | 8 +++++++ .../Exception/MissingAccessTokenException.php | 8 +++++++ src/OAuth2/Exception/OAuth2Exception.php | 8 +++++++ src/OAuth2/MissingAccessTokenException.php | 8 ------- src/OAuth2/Resource.php | 24 +++++++++++++++++-- 5 files changed, 46 insertions(+), 10 deletions(-) create mode 100644 src/OAuth2/Exception/InvalidGrantTypeException.php create mode 100644 src/OAuth2/Exception/MissingAccessTokenException.php create mode 100644 src/OAuth2/Exception/OAuth2Exception.php delete mode 100644 src/OAuth2/MissingAccessTokenException.php diff --git a/src/OAuth2/Exception/InvalidGrantTypeException.php b/src/OAuth2/Exception/InvalidGrantTypeException.php new file mode 100644 index 00000000..08b31e6a --- /dev/null +++ b/src/OAuth2/Exception/InvalidGrantTypeException.php @@ -0,0 +1,8 @@ +request; } + /** + * Gets the Owner ID. + * + * @return int + */ + public function getOwnerId() + { + return $this->ownerId; + } + + /** + * Gets the Owner Type. + * + * @return string + */ + public function getOwnerType() + { + return $this->ownerId; + } + /** * Checks if the Access Token is valid or not. * @@ -113,7 +133,7 @@ class Resource * Reads in the Access Token from the headers. * * @return string - * @throws MissingAccessTokenException + * @throws Exception\MissingAccessTokenException */ protected function determineAccessToken() { @@ -125,7 +145,7 @@ class Resource } if (empty($access_token)) { - throw new MissingAccessTokenException('Access Token is Missing'); + throw new Exception\MissingAccessTokenException('Access Token is Missing'); } return $access_token; From 892ae3a0d35bbf8fa2a089842eadaab45a84a55d Mon Sep 17 00:00:00 2001 From: Daniel Horrigan Date: Tue, 22 Jan 2013 11:25:51 -0500 Subject: [PATCH 008/113] Started adding some Server methods, adding some Util classes and adding a way to get the token from the Resource --- src/OAuth2/Resource.php | 10 ++++ src/OAuth2/Server.php | 83 +++++++++++++++++++++++++++++++++ src/OAuth2/Util/RedirectUri.php | 12 +++++ src/OAuth2/Util/SecureKey.php | 21 +++++++++ 4 files changed, 126 insertions(+) create mode 100644 src/OAuth2/Util/RedirectUri.php create mode 100644 src/OAuth2/Util/SecureKey.php diff --git a/src/OAuth2/Resource.php b/src/OAuth2/Resource.php index 4e2d540b..80590049 100644 --- a/src/OAuth2/Resource.php +++ b/src/OAuth2/Resource.php @@ -80,6 +80,16 @@ class Resource return $this->ownerId; } + /** + * Gets the Access Token. + * + * @return string + */ + public function getAccessToken() + { + return $this->accessToken; + } + /** * Checks if the Access Token is valid or not. * diff --git a/src/OAuth2/Server.php b/src/OAuth2/Server.php index 386a6cb5..09ef8a37 100644 --- a/src/OAuth2/Server.php +++ b/src/OAuth2/Server.php @@ -16,6 +16,8 @@ class Server protected $grantTypes = array(); + protected $request = null; + public function __construct($storage) { @@ -29,14 +31,95 @@ class Server $this->grantTypes[$identifier] = $grant_type; } + public function getScopeDelimeter() + { + return $this->scopeDelimeter; + } + public function setScopeDelimeter($scope_delimeter) { $this->scopeDelimeter = $scope_delimeter; } + public function getExpiresIn() + { + return $this->expiresIn; + } + public function setExpiresIn($expires_in) { $this->expiresIn = $expires_in; } + /** + * Sets the Request Object + * + * @param RequestInterface The Request Object + */ + public function setRequest(RequestInterface $request) + { + $this->request = $request; + } + + /** + * Gets the Request object. It will create one from the globals if one is not set. + * + * @return RequestInterface + */ + public function getRequest() + { + if ($this->request === null) { + $this->request = Request::buildFromGlobals(); + } + + return $this->request; + } + + /** + * Check client authorise parameters + * + * @access public + * @param array $authParams Optional array of parsed $_GET keys + * @return array Authorise request parameters + */ + public function checkClientAuthoriseParams($authParams = null) + { + + } + + /** + * Parse a new authorise request + * + * @param string $type The session owner's type + * @param string $typeId The session owner's ID + * @param array $authoriseParams The authorise request $_GET parameters + * @return string An authorisation code + */ + public function newAuthoriseRequest($type, $typeId, $authoriseParams) + { + + } + + /** + * Issue an access token + * + * @access public + * @param array $authParams Optional array of parsed $_POST keys + * @return array Authorise request parameters + */ + public function issueAccessToken($authParams = null) + { + + } + + + protected function getCurrentGrantType() + { + $grantType = $this->getRequest()->post('grant_type'); + + if (is_null($grantType)) { + throw new Exception + } + } + } diff --git a/src/OAuth2/Util/RedirectUri.php b/src/OAuth2/Util/RedirectUri.php new file mode 100644 index 00000000..7e75ab44 --- /dev/null +++ b/src/OAuth2/Util/RedirectUri.php @@ -0,0 +1,12 @@ + Date: Tue, 22 Jan 2013 11:33:09 -0500 Subject: [PATCH 009/113] Renaming Server and Resource to AuthServer and ResourceServer to be less confusing. --- src/OAuth2/{Server.php => AuthServer.php} | 2 +- src/OAuth2/{Resource.php => ResourceServer.php} | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename src/OAuth2/{Server.php => AuthServer.php} (99%) rename src/OAuth2/{Resource.php => ResourceServer.php} (99%) diff --git a/src/OAuth2/Server.php b/src/OAuth2/AuthServer.php similarity index 99% rename from src/OAuth2/Server.php rename to src/OAuth2/AuthServer.php index 09ef8a37..9008d829 100644 --- a/src/OAuth2/Server.php +++ b/src/OAuth2/AuthServer.php @@ -2,7 +2,7 @@ namespace OAuth2; -class Server +class AuthServer { protected $scopeDelimeter = ','; diff --git a/src/OAuth2/Resource.php b/src/OAuth2/ResourceServer.php similarity index 99% rename from src/OAuth2/Resource.php rename to src/OAuth2/ResourceServer.php index 80590049..ba0d6801 100644 --- a/src/OAuth2/Resource.php +++ b/src/OAuth2/ResourceServer.php @@ -6,7 +6,7 @@ use OutOfBoundsException; use OAuth2\Storage\SessionInterface; use OAuth2\Storage\SessionScopeInterface; -class Resource +class ResourceServer { protected $accessToken = null; From 9a41ab8bfc0b3addc979d5e2d97b995d53f13e55 Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Tue, 29 Jan 2013 14:14:50 +0000 Subject: [PATCH 010/113] Removed unnecessary column from the table --- sql/database.sql | 2 -- 1 file changed, 2 deletions(-) diff --git a/sql/database.sql b/sql/database.sql index b260d9f0..a21aeb94 100644 --- a/sql/database.sql +++ b/sql/database.sql @@ -49,11 +49,9 @@ CREATE TABLE `scopes` ( CREATE TABLE `oauth_session_scopes` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `session_id` int(11) unsigned NOT NULL, - `access_token` varchar(40) NOT NULL DEFAULT '', `scope` varchar(255) NOT NULL DEFAULT '', PRIMARY KEY (`id`), KEY `session_id` (`session_id`), - KEY `access_token` (`access_token`), KEY `scope` (`scope`), CONSTRAINT `oauth_session_scopes_ibfk_3` FOREIGN KEY (`scope`) REFERENCES `scopes` (`scope`) ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT `oauth_session_scopes_ibfk_4` FOREIGN KEY (`session_id`) REFERENCES `oauth_sessions` (`id`) ON DELETE CASCADE From f74a35074ab5cb2c2b8a0e023899f4979565e3e5 Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Tue, 29 Jan 2013 14:15:05 +0000 Subject: [PATCH 011/113] Added getResponseType parameter --- src/OAuth2/GrantTypeInterface.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/OAuth2/GrantTypeInterface.php b/src/OAuth2/GrantTypeInterface.php index c8eb83c8..ce79a6eb 100644 --- a/src/OAuth2/GrantTypeInterface.php +++ b/src/OAuth2/GrantTypeInterface.php @@ -5,4 +5,6 @@ namespace OAuth2; interface GrantTypeInterface { public function getIdentifier(); + + public function getResponseType(); } From d63c0ea2622d960de0f99afebf6575776023ff7d Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Tue, 29 Jan 2013 14:16:47 +0000 Subject: [PATCH 012/113] Added model variable storage --- src/OAuth2/AuthServer.php | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/OAuth2/AuthServer.php b/src/OAuth2/AuthServer.php index 9008d829..62c42b9e 100644 --- a/src/OAuth2/AuthServer.php +++ b/src/OAuth2/AuthServer.php @@ -2,6 +2,10 @@ namespace OAuth2; +use OAuth2\Storage\SessionInterface; +use OAuth2\Storage\ClientInterface; +use OAuth2\Storage\ScopeInterface; + class AuthServer { protected $scopeDelimeter = ','; @@ -18,9 +22,14 @@ class AuthServer protected $request = null; - public function __construct($storage) - { + public function __construct(ClientInterface $client, SessionInterface $session, ScopeInterface $scope) + { + $this->storages = array( + 'client' => $client, + 'session' => $session, + 'scope' => $scope + ); } public function addGrantType(GrantTypeInterface $grant_type, $identifier = null) @@ -75,6 +84,11 @@ class AuthServer return $this->request; } + public function getStorage($obj) + { + return $this->storages[$obj]; + } + /** * Check client authorise parameters * From a189156f263d19ad45a0f8e3f87afb347426b85f Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Tue, 29 Jan 2013 14:17:56 +0000 Subject: [PATCH 013/113] Response types are now generated from grants that are injected in --- src/OAuth2/AuthServer.php | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/OAuth2/AuthServer.php b/src/OAuth2/AuthServer.php index 62c42b9e..a4ce3cbf 100644 --- a/src/OAuth2/AuthServer.php +++ b/src/OAuth2/AuthServer.php @@ -12,9 +12,7 @@ class AuthServer protected $expiresIn = 3600; - protected $responseTypes = array( - 'code' - ); + protected $responseTypes = array(); protected $storages = array(); @@ -32,12 +30,16 @@ class AuthServer ); } - public function addGrantType(GrantTypeInterface $grant_type, $identifier = null) + public function addGrantType(GrantTypeInterface $grantType, $identifier = null) { if (is_null($identifier)) { - $identifier = $grant_type->getIdentifier(); + $identifier = $grantType->getIdentifier(); + } + $this->grantTypes[$identifier] = $grantType; + + if (! is_null($grantType->getResponseType())) { + $this->responseTypes[] = $grantType->getResponseType(); } - $this->grantTypes[$identifier] = $grant_type; } public function getScopeDelimeter() From 846a008c76cf8d080d9cba7a2d823ee7d7457cd5 Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Tue, 29 Jan 2013 14:18:13 +0000 Subject: [PATCH 014/113] Explanation of the scope delimiter parameter --- src/OAuth2/AuthServer.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/OAuth2/AuthServer.php b/src/OAuth2/AuthServer.php index a4ce3cbf..683255ec 100644 --- a/src/OAuth2/AuthServer.php +++ b/src/OAuth2/AuthServer.php @@ -8,6 +8,14 @@ use OAuth2\Storage\ScopeInterface; class AuthServer { + /** + * The delimeter between scopes specified in the scope query string parameter + * + * The OAuth 2 specification states it should be a space but that is stupid + * and everyone excepted Google use a comma instead. + * + * @var string + */ protected $scopeDelimeter = ','; protected $expiresIn = 3600; From 57f825b0a8a6fb7f53ffc265d2d14b4e5e7f7f53 Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Tue, 29 Jan 2013 14:19:23 +0000 Subject: [PATCH 015/113] Added exception codes and messages --- src/OAuth2/AuthServer.php | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/src/OAuth2/AuthServer.php b/src/OAuth2/AuthServer.php index 683255ec..8153c8ab 100644 --- a/src/OAuth2/AuthServer.php +++ b/src/OAuth2/AuthServer.php @@ -28,6 +28,41 @@ class AuthServer protected $request = null; + /** + * Exception error codes + * @var array + */ + protected $exceptionCodes = array( + 0 => 'invalid_request', + 1 => 'unauthorized_client', + 2 => 'access_denied', + 3 => 'unsupported_response_type', + 4 => 'invalid_scope', + 5 => 'server_error', + 6 => 'temporarily_unavailable', + 7 => 'unsupported_grant_type', + 8 => 'invalid_client', + 9 => 'invalid_grant' + ); + + /** + * Exception error messages + * @var array + */ + protected $exceptionMessages = array( + 'invalid_request' => 'The request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed. Check the "%s" parameter.', + 'unauthorized_client' => 'The client is not authorized to request an access token using this method.', + 'access_denied' => 'The resource owner or authorization server denied the request.', + 'unsupported_response_type' => 'The authorization server does not support obtaining an access token using this method.', + 'invalid_scope' => 'The requested scope is invalid, unknown, or malformed. Check the "%s" scope.', + 'server_error' => 'The authorization server encountered an unexpected condition which prevented it from fulfilling the request.', + 'temporarily_unavailable' => 'The authorization server is currently unable to handle the request due to a temporary overloading or maintenance of the server.', + 'unsupported_grant_type' => 'The authorization grant type "%s" is not supported by the authorization server', + 'invalid_client' => 'Client authentication failed', + 'invalid_grant' => 'The provided authorization grant is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client. Check the "%s" parameter.', + 'invalid_credentials' => 'The user credentials were incorrect.', + 'invalid_refresh' => 'The refresh token is invalid.', + ); public function __construct(ClientInterface $client, SessionInterface $session, ScopeInterface $scope) { From 1ed4c274207c3795673c90dd3c7624396709813c Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Tue, 29 Jan 2013 14:23:28 +0000 Subject: [PATCH 016/113] Update ClientInterface with get() method --- src/OAuth2/Storage/ClientInterface.php | 43 ++++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/src/OAuth2/Storage/ClientInterface.php b/src/OAuth2/Storage/ClientInterface.php index d0d7fb7d..bb339ffc 100644 --- a/src/OAuth2/Storage/ClientInterface.php +++ b/src/OAuth2/Storage/ClientInterface.php @@ -4,5 +4,44 @@ namespace OAuth2\Storage; interface ClientInterface { - -} + /** + * Validate a client + * + * Example SQL query: + * + * + * # Client ID + redirect URI + * SELECT clients.id FROM clients LEFT JOIN client_endpoints ON + * client_endpoints.client_id = clients.id WHERE clients.id = $clientId AND + * client_endpoints.redirect_uri = $redirectUri + * + * # Client ID + client secret + * SELECT clients.id FROM clients WHERE clients.id = $clientId AND + * clients.secret = $clientSecret + * + * # Client ID + client secret + redirect URI + * SELECT clients.id FROM clients LEFT JOIN client_endpoints ON + * client_endpoints.client_id = clients.id WHERE clients.id = $clientId AND + * clients.secret = $clientSecret AND client_endpoints.redirect_uri = + * $redirectUri + * + * + * Response: + * + * + * Array + * ( + * [client_id] => (string) The client ID + * [client secret] => (string) The client secret + * [redirect_uri] => (string) The redirect URI used in this request + * [name] => (string) The name of the client + * ) + * + * + * @param string $clientId The client's ID + * @param string $clientSecret The client's secret (default = "null") + * @param string $redirectUri The client's redirect URI (default = "null") + * @return bool|array Returns false if the validation fails, array on success + */ + public function get($clientId = null, $clientSecret = null, $redirectUri = null); +} \ No newline at end of file From 5e91b95cb35ed930568c43563135cdc4990dbc46 Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Tue, 29 Jan 2013 14:25:49 +0000 Subject: [PATCH 017/113] Updated ScopeInterface with get method --- src/OAuth2/Storage/ScopeInterface.php | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/src/OAuth2/Storage/ScopeInterface.php b/src/OAuth2/Storage/ScopeInterface.php index 392ce3a1..895cc4e6 100644 --- a/src/OAuth2/Storage/ScopeInterface.php +++ b/src/OAuth2/Storage/ScopeInterface.php @@ -4,5 +4,29 @@ namespace OAuth2\Storage; interface ScopeInterface { - + /** + * Return information about a scope + * + * Example SQL query: + * + * + * SELECT * FROM scopes WHERE scope = $scope + * + * + * Response: + * + * + * Array + * ( + * [id] => (int) The scope's ID + * [scope] => (string) The scope itself + * [name] => (string) The scope's name + * [description] => (string) The scope's description + * ) + * + * + * @param string $scope The scope + * @return bool|array If the scope doesn't exist return false + */ + public function get($scope); } From a8b6389092b474cdcaca851e7d84301eadce40ce Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Tue, 29 Jan 2013 14:55:50 +0000 Subject: [PATCH 018/113] Updated SessionInterface --- src/OAuth2/Storage/SessionInterface.php | 263 +++++++++++++++++++++++- 1 file changed, 262 insertions(+), 1 deletion(-) diff --git a/src/OAuth2/Storage/SessionInterface.php b/src/OAuth2/Storage/SessionInterface.php index c035cffa..eb660451 100644 --- a/src/OAuth2/Storage/SessionInterface.php +++ b/src/OAuth2/Storage/SessionInterface.php @@ -4,5 +4,266 @@ namespace OAuth2\Storage; interface SessionInterface { - public function validateAccessToken($access_token); + /** + * Create a new OAuth session + * + * Database query: + * + * + * INSERT INTO oauth_sessions (client_id, redirect_uri, owner_type, + * owner_id, auth_code, access_token, refresh_token, stage, first_requested, + * last_updated) VALUES ($clientId, $redirectUri, $type, $typeId, $authCode, + * $accessToken, $stage, UNIX_TIMESTAMP(NOW()), UNIX_TIMESTAMP(NOW())) + * + * + * @param string $clientId The client ID + * @param string $redirectUri The redirect URI + * @param string $type The session owner's type (default = "user") + * @param string $typeId The session owner's ID (default = "null") + * @param string $authCode The authorisation code (default = "null") + * @param string $accessToken The access token (default = "null") + * @param string $refreshToken The refresh token (default = "null") + * @param string $stage The stage of the session (default ="request") + * @return int The session ID + */ + public function new( + $clientId, + $redirectUri, + $type = 'user', + $typeId = null, + $authCode = null, + $accessToken = null, + $refreshToken = null, + $accessTokenExpire = null, + $stage = 'requested' + ); + + /** + * Update an OAuth session + * + * Database query: + * + * + * UPDATE oauth_sessions SET auth_code = $authCode, access_token = + * $accessToken, stage = $stage, last_updated = UNIX_TIMESTAMP(NOW()) WHERE + * id = $sessionId + * + * + * @param string $sessionId The session ID + * @param string $authCode The authorisation code (default = "null") + * @param string $accessToken The access token (default = "null") + * @param string $refreshToken The refresh token (default = "null") + * @param string $stage The stage of the session (default ="request") + * @return void + */ + public function update( + $sessionId, + $authCode = null, + $accessToken = null, + $refreshToken = null, + $accessTokenExpire = null, + $stage = 'requested' + ); + + /** + * Delete an OAuth session + * + * + * DELETE FROM oauth_sessions WHERE client_id = $clientId AND owner_type = + * $type AND owner_id = $typeId + * + * + * @param string $clientId The client ID + * @param string $type The session owner's type + * @param string $typeId The session owner's ID + * @return void + */ + public function delete( + $clientId, + $type, + $typeId + ); + + /** + * Return the session ID for a given session owner and client combination + * + * Database query: + * + * + * SELECT id FROM oauth_sessions WHERE client_id = $clientId + * AND owner_type = $type AND owner_id = $typeId + * + * + * @param string $type The session owner's type + * @param string $typeId The session owner's ID + * @param string $clientId The client ID + * @return string|null Return the session ID as an integer if + * found otherwise returns false + */ + public function exists( + $type, + $typeId, + $clientId + ); + + /** + * Validate that an authorisation code is valid + * + * Database query: + * + * + * SELECT id FROM oauth_sessions WHERE client_id = $clientID AND + * redirect_uri = $redirectUri AND auth_code = $authCode + * + * + * Response: + * + * + * Array + * ( + * [id] => (int) The session ID + * [client_id] => (string) The client ID + * [redirect_uri] => (string) The redirect URI + * [owner_type] => (string) The session owner type + * [owner_id] => (string) The session owner's ID + * [auth_code] => (string) The authorisation code + * [stage] => (string) The session's stage + * [first_requested] => (int) Unix timestamp of the time the session was + * first generated + * [last_updated] => (int) Unix timestamp of the time the session was + * last updated + * ) + * + * + * @param string $clientId The client ID + * @param string $redirectUri The redirect URI + * @param string $authCode The authorisation code + * @return int|bool Returns the session ID if the auth code + * is valid otherwise returns false + */ + public function validateAuthCode( + $clientId, + $redirectUri, + $authCode + ); + + /** + * Removes an authorisation code associated with a session + * + * Database query: + * + * + * UPDATE oauth_sessions SET auth_code = NULL WHERE id = $sessionId + * + * + * @param int $sessionId The OAuth session ID + * @return void + */ + public function removeAuthCode($sessionId); + + /** + * Sets a sessions access token + * + * Database query: + * + * + * UPDATE oauth_sessions SET access_token = $accessToken WHERE id = + * $sessionId + * + * + * @param int $sessionId The OAuth session ID + * @param string $accessToken The access token + * @return void + */ + public function setAccessToken( + $sessionId, + $accessToken + ); + + public function validateAccessToken($accessToken); + + /** + * Return the access token for a given session + * + * Database query: + * + * + * SELECT access_token FROM oauth_sessions WHERE id = $sessionId + * + * + * @param int $sessionId The OAuth session ID + * @return string|null Returns the access token as a string if + * found otherwise returns null + */ + public function getAccessToken($sessionId); + + public function validateRefreshToken($refreshToken, $clientId); + + /** + * Update the refresh token + * + * Database query: + * + * + * UPDATE oauth_sessions SET access_token = $newAccessToken, refresh_token = + * $newRefreshToken, access_toke_expires = $accessTokenExpires, last_updated = UNIX_TIMESTAMP(NOW()) WHERE + * id = $sessionId + * + * + * @param string $sessionId The session ID + * @param string $newAccessToken The new access token for this session + * @param string $newRefreshToken The new refresh token for the session + * @param int $accessTokenExpires The UNIX timestamp of when the new token expires + * @return void + */ + public function updateRefreshToken($sessionId, $newAccessToken, $newRefreshToken, $accessTokenExpires); + + /** + * Associates a session with a scope + * + * Database query: + * + * + * INSERT INTO oauth_session_scopes (session_id, scope) VALUE ($sessionId, + * $scope) + * + * + * @param int $sessionId The session ID + * @param string $scope The scope + * @return void + */ + public function associateScope( + $sessionId, + $scope + ); + + /** + * Return the scopes associated with an access token + * + * Database query: + * + * + * SELECT scopes.scope, scopes.name, scopes.description FROM + * oauth_session_scopes JOIN scopes ON oauth_session_scopes.scope = + * scopes.scope WHERE access_token = $accessToken + * + * + * Response: + * + * + * Array + * ( + * [0] => Array + * ( + * [scope] => (string) The scope + * [name] => (string) The scope's name + * [description] => (string) The scope's description + * ) + * ) + * + * + * @param string $accessToken The access token + * @return array + */ + public function getScopes($accessToken); } From 31c3b495bf5c40660b509204ade588fdb07666f2 Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Tue, 29 Jan 2013 14:56:17 +0000 Subject: [PATCH 019/113] Re-added checkClientAuthoriseParams() function --- src/OAuth2/AuthServer.php | 73 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 72 insertions(+), 1 deletion(-) diff --git a/src/OAuth2/AuthServer.php b/src/OAuth2/AuthServer.php index 8153c8ab..df4eec51 100644 --- a/src/OAuth2/AuthServer.php +++ b/src/OAuth2/AuthServer.php @@ -143,7 +143,78 @@ class AuthServer */ public function checkClientAuthoriseParams($authParams = null) { + $params = array(); + // Client ID + $params['client_id'] = (isset($authParams['client_id'])) ? + $authParams['client_id'] : + $this->getRequest()->get('client_id'); + + if (is_null($params['client_id'])) { + throw new Exception\ClientException(sprintf($this->exceptionMessages['invalid_request'], 'client_id'), 0); + } + + // Redirect URI + $params['redirect_uri'] = (isset($authParams['redirect_uri'])) ? + $authParams['redirect_uri'] : + $this->getRequest()->get('redirect_uri'); + + if (is_null($params['redirect_uri'])) { + throw new Exception\ClientException(sprintf($this->exceptionMessages['invalid_request'], 'redirect_uri'), 0); + } + + // Validate client ID and redirect URI + $clientDetails = $this->getStorage('client')->get($params['client_id'], null, $params['redirect_uri']); + + if ($clientDetails === false) { + throw new Exception\ClientException($this->exceptionMessages['invalid_client'], 8); + } + + $params['client_details'] = $clientDetails; + + // Response type + $params['response_type'] = (isset($authParams['response_type'])) ? + $authParams['response_type'] : + $this->getRequest()->get('response_type'); + + if (is_null($params['response_type'])) { + throw new Exception\ClientException(sprintf($this->exceptionMessages['invalid_request'], 'response_type'), 0); + } + + // Ensure response type is one that is recognised + if ( ! in_array($params['response_type'], $this->responseTypes)) { + throw new Exception\ClientException($this->exceptionMessages['unsupported_response_type'], 3); + } + + // Get and validate scopes + $scopes = (isset($authParams['scope'])) ? + $authParams['scope'] : + $this->getRequest()->get('scope', ''); + + $scopes = explode($this->_config['scope_delimeter'], $scopes); + + for ($i = 0; $i < count($scopes); $i++) { + $scopes[$i] = trim($scopes[$i]); + if ($scopes[$i] === '') unset($scopes[$i]); // Remove any junk scopes + } + + if (count($scopes) === 0) { + throw new Exception\ClientException(sprintf($this->exceptionMessages['invalid_request'], 'scope'), 0); + } + + $params['scopes'] = array(); + + foreach ($scopes as $scope) { + $scopeDetails = $this->getStorage('scope')->get($scope); + + if ($scopeDetails === false) { + throw new Exception\ClientException(sprintf($this->exceptionMessages['invalid_scope'], $scope), 4); + } + + $params['scopes'][] = $scopeDetails; + } + + return $params; } /** @@ -177,7 +248,7 @@ class AuthServer $grantType = $this->getRequest()->post('grant_type'); if (is_null($grantType)) { - throw new Exception + throw new Exception; } } From dcd1026a9842a0f65d1f4812a2599d585632d5c5 Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Tue, 29 Jan 2013 16:15:45 +0000 Subject: [PATCH 020/113] Use scope_id instead of the scope name --- sql/database.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/database.sql b/sql/database.sql index a21aeb94..6cc30716 100644 --- a/sql/database.sql +++ b/sql/database.sql @@ -49,7 +49,7 @@ CREATE TABLE `scopes` ( CREATE TABLE `oauth_session_scopes` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `session_id` int(11) unsigned NOT NULL, - `scope` varchar(255) NOT NULL DEFAULT '', + `scope_id` int(11) unsigned NOT NULL, PRIMARY KEY (`id`), KEY `session_id` (`session_id`), KEY `scope` (`scope`), From cab721923aceca582efbfd69a81b6a678d47eed9 Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Tue, 29 Jan 2013 16:17:30 +0000 Subject: [PATCH 021/113] Set relationship to scope_id --- sql/database.sql | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sql/database.sql b/sql/database.sql index 6cc30716..e733253b 100644 --- a/sql/database.sql +++ b/sql/database.sql @@ -52,7 +52,7 @@ CREATE TABLE `oauth_session_scopes` ( `scope_id` int(11) unsigned NOT NULL, PRIMARY KEY (`id`), KEY `session_id` (`session_id`), - KEY `scope` (`scope`), - CONSTRAINT `oauth_session_scopes_ibfk_3` FOREIGN KEY (`scope`) REFERENCES `scopes` (`scope`) ON DELETE CASCADE ON UPDATE CASCADE, + KEY `scope_id` (`scope_id`), + CONSTRAINT `oauth_session_scopes_ibfk_5` FOREIGN KEY (`scope_id`) REFERENCES `scopes` (`id`) ON DELETE CASCADE, CONSTRAINT `oauth_session_scopes_ibfk_4` FOREIGN KEY (`session_id`) REFERENCES `oauth_sessions` (`id`) ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8; From 74f48d28a4a6982737d01adaa92ef6c4fe515a5e Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Tue, 29 Jan 2013 16:18:23 +0000 Subject: [PATCH 022/113] Added ClientException --- src/OAuth2/Exception/ClientException.php | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 src/OAuth2/Exception/ClientException.php diff --git a/src/OAuth2/Exception/ClientException.php b/src/OAuth2/Exception/ClientException.php new file mode 100644 index 00000000..0a732431 --- /dev/null +++ b/src/OAuth2/Exception/ClientException.php @@ -0,0 +1,8 @@ + Date: Tue, 29 Jan 2013 16:18:45 +0000 Subject: [PATCH 023/113] Moved GrantTypeInterface --- src/OAuth2/{ => Grant}/GrantTypeInterface.php | 2 ++ 1 file changed, 2 insertions(+) rename src/OAuth2/{ => Grant}/GrantTypeInterface.php (78%) diff --git a/src/OAuth2/GrantTypeInterface.php b/src/OAuth2/Grant/GrantTypeInterface.php similarity index 78% rename from src/OAuth2/GrantTypeInterface.php rename to src/OAuth2/Grant/GrantTypeInterface.php index ce79a6eb..67a389c2 100644 --- a/src/OAuth2/GrantTypeInterface.php +++ b/src/OAuth2/Grant/GrantTypeInterface.php @@ -7,4 +7,6 @@ interface GrantTypeInterface public function getIdentifier(); public function getResponseType(); + + public function completeFlow(); } From ffcad85d95fae42f017b54d8931009d478156563 Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Tue, 29 Jan 2013 16:21:21 +0000 Subject: [PATCH 024/113] Renamed functions, changed some doc terms --- src/OAuth2/Storage/SessionInterface.php | 33 +++++++++++-------------- 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/src/OAuth2/Storage/SessionInterface.php b/src/OAuth2/Storage/SessionInterface.php index eb660451..a84e50d2 100644 --- a/src/OAuth2/Storage/SessionInterface.php +++ b/src/OAuth2/Storage/SessionInterface.php @@ -7,7 +7,7 @@ interface SessionInterface /** * Create a new OAuth session * - * Database query: + * Example SQL query: * * * INSERT INTO oauth_sessions (client_id, redirect_uri, owner_type, @@ -26,7 +26,7 @@ interface SessionInterface * @param string $stage The stage of the session (default ="request") * @return int The session ID */ - public function new( + public function create( $clientId, $redirectUri, $type = 'user', @@ -41,7 +41,7 @@ interface SessionInterface /** * Update an OAuth session * - * Database query: + * Example SQL query: * * * UPDATE oauth_sessions SET auth_code = $authCode, access_token = @@ -87,7 +87,7 @@ interface SessionInterface /** * Return the session ID for a given session owner and client combination * - * Database query: + * Example SQL query: * * * SELECT id FROM oauth_sessions WHERE client_id = $clientId @@ -109,7 +109,7 @@ interface SessionInterface /** * Validate that an authorisation code is valid * - * Database query: + * Example SQL query: * * * SELECT id FROM oauth_sessions WHERE client_id = $clientID AND @@ -150,7 +150,7 @@ interface SessionInterface /** * Removes an authorisation code associated with a session * - * Database query: + * Example SQL query: * * * UPDATE oauth_sessions SET auth_code = NULL WHERE id = $sessionId @@ -164,7 +164,7 @@ interface SessionInterface /** * Sets a sessions access token * - * Database query: + * Example SQL query: * * * UPDATE oauth_sessions SET access_token = $accessToken WHERE id = @@ -185,7 +185,7 @@ interface SessionInterface /** * Return the access token for a given session * - * Database query: + * Example SQL query: * * * SELECT access_token FROM oauth_sessions WHERE id = $sessionId @@ -202,7 +202,7 @@ interface SessionInterface /** * Update the refresh token * - * Database query: + * Example SQL query: * * * UPDATE oauth_sessions SET access_token = $newAccessToken, refresh_token = @@ -221,26 +221,23 @@ interface SessionInterface /** * Associates a session with a scope * - * Database query: + * Example SQL query: * * - * INSERT INTO oauth_session_scopes (session_id, scope) VALUE ($sessionId, - * $scope) + * INSERT INTO oauth_session_scopes (session_id, scope_id) VALUE ($sessionId, + * $scopeId) * * * @param int $sessionId The session ID - * @param string $scope The scope + * @param string $scope The scope ID * @return void */ - public function associateScope( - $sessionId, - $scope - ); + public function associateScope($sessionId, $scopeId); /** * Return the scopes associated with an access token * - * Database query: + * Example SQL query: * * * SELECT scopes.scope, scopes.name, scopes.description FROM From 8ae0dbcf4636c62cb31e6296f1458f0228d5ddaf Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Tue, 29 Jan 2013 16:21:39 +0000 Subject: [PATCH 025/113] Default to 40 characters (as that is what the DB table columns are set to) --- src/OAuth2/Util/SecureKey.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/OAuth2/Util/SecureKey.php b/src/OAuth2/Util/SecureKey.php index d6e0d232..0739a193 100644 --- a/src/OAuth2/Util/SecureKey.php +++ b/src/OAuth2/Util/SecureKey.php @@ -4,7 +4,7 @@ namespace OAuth2\Util; class SecureKey { - public static function make($len = 42) + public static function make($len = 40) { // We generate twice as many bytes here because we want to ensure we have // enough after we base64 encode it to get the length we need because we From 3cb53448c5bde0d3772c000ef3c25cc82dcc58a3 Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Tue, 29 Jan 2013 16:21:53 +0000 Subject: [PATCH 026/113] Anal style fix --- src/OAuth2/AuthServer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/OAuth2/AuthServer.php b/src/OAuth2/AuthServer.php index df4eec51..2ff9df46 100644 --- a/src/OAuth2/AuthServer.php +++ b/src/OAuth2/AuthServer.php @@ -80,7 +80,7 @@ class AuthServer } $this->grantTypes[$identifier] = $grantType; - if (! is_null($grantType->getResponseType())) { + if ( ! is_null($grantType->getResponseType())) { $this->responseTypes[] = $grantType->getResponseType(); } } From 514aabb8389a55df524044a44d5238ad7f0134cc Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Tue, 29 Jan 2013 16:23:41 +0000 Subject: [PATCH 027/113] Updated newAuthoriseRequest method --- src/OAuth2/AuthServer.php | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/OAuth2/AuthServer.php b/src/OAuth2/AuthServer.php index 2ff9df46..c83ad822 100644 --- a/src/OAuth2/AuthServer.php +++ b/src/OAuth2/AuthServer.php @@ -2,6 +2,7 @@ namespace OAuth2; +use OAuth2\Util; use OAuth2\Storage\SessionInterface; use OAuth2\Storage\ClientInterface; use OAuth2\Storage\ScopeInterface; @@ -227,7 +228,22 @@ class AuthServer */ public function newAuthoriseRequest($type, $typeId, $authoriseParams) { + // Generate an auth code + $authCode = SecureKey::make(); + // Remove any old sessions the user might have + $this->getStorage('session')->delete($authoriseParams['client_id'], $type, $typeId); + + // Create a new session + $sessionId = $this->getStorage('session')->create($authoriseParams['client_id'], $authoriseParams['redirect_uri'], $type, $typeId, $authCode); + + // Associate scopes with the new session + foreach ($authoriseParams['scopes'] as $scope) + { + $this->getStorage('session')->associateScope($sessionId, $scope['id']); + } + + return $authCode; } /** From 4fa37bb356ea29d2943a92937985ca70878bd287 Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Tue, 29 Jan 2013 16:24:28 +0000 Subject: [PATCH 028/113] Updated issueAccessToken method --- src/OAuth2/AuthServer.php | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/OAuth2/AuthServer.php b/src/OAuth2/AuthServer.php index c83ad822..d6701f81 100644 --- a/src/OAuth2/AuthServer.php +++ b/src/OAuth2/AuthServer.php @@ -255,9 +255,18 @@ class AuthServer */ public function issueAccessToken($authParams = null) { + $params['grant_type'] = (isset($authParams['grant_type'])) ? + $authParams['grant_type'] : + $this->getRequest()->post('grant_type'); - } + if (is_null($params['grant_type'])) { + throw new Exception\ClientException(sprintf($this->errors['invalid_request'], 'grant_type'), 0); + } + // Ensure grant type is one that is recognised and is enabled + if ( ! in_array($params['grant_type'], array_keys($this->grantTypes))) { + throw new Exception\ClientException(sprintf($this->errors['unsupported_grant_type'], $params['grant_type']), 7); + } protected function getCurrentGrantType() { From 87a142cc3088edfc8ed706bd6d37ede632ade115 Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Tue, 29 Jan 2013 16:24:48 +0000 Subject: [PATCH 029/113] Updated getCurrentGrantType method --- src/OAuth2/AuthServer.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/OAuth2/AuthServer.php b/src/OAuth2/AuthServer.php index d6701f81..5a7cb227 100644 --- a/src/OAuth2/AuthServer.php +++ b/src/OAuth2/AuthServer.php @@ -268,13 +268,13 @@ class AuthServer throw new Exception\ClientException(sprintf($this->errors['unsupported_grant_type'], $params['grant_type']), 7); } - protected function getCurrentGrantType() - { - $grantType = $this->getRequest()->post('grant_type'); + // Complete the flow + return $this->getCurrentGrantType($params['grant_type'])->completeFlow($authParams, $params); + } - if (is_null($grantType)) { - throw new Exception; - } + protected function getCurrentGrantType($grantType) + { + return $this->grantTypes[$grantType]; } } From 781bf985c3b5f3a730418a430a1cc420f4a71162 Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Tue, 29 Jan 2013 16:25:14 +0000 Subject: [PATCH 030/113] Renamed checkClientAuthoriseParams method to checkAuthoriseParams --- src/OAuth2/AuthServer.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/OAuth2/AuthServer.php b/src/OAuth2/AuthServer.php index 5a7cb227..f4930f8d 100644 --- a/src/OAuth2/AuthServer.php +++ b/src/OAuth2/AuthServer.php @@ -136,13 +136,13 @@ class AuthServer } /** - * Check client authorise parameters + * Check authorise parameters * * @access public * @param array $authParams Optional array of parsed $_GET keys * @return array Authorise request parameters */ - public function checkClientAuthoriseParams($authParams = null) + public function checkAuthoriseParams($authParams = null) { $params = array(); From 9b6a92c506abafcea117cad460f2726c60d29796 Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Tue, 29 Jan 2013 16:53:39 +0000 Subject: [PATCH 031/113] Updated namespace use for Util\SecureKey --- src/OAuth2/AuthServer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/OAuth2/AuthServer.php b/src/OAuth2/AuthServer.php index f4930f8d..bd14fcff 100644 --- a/src/OAuth2/AuthServer.php +++ b/src/OAuth2/AuthServer.php @@ -2,7 +2,7 @@ namespace OAuth2; -use OAuth2\Util; +use OAuth2\Util\SecureKey; use OAuth2\Storage\SessionInterface; use OAuth2\Storage\ClientInterface; use OAuth2\Storage\ScopeInterface; From 7a851084c67030e8804cec048ea87c2e26c82e21 Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Fri, 1 Feb 2013 10:50:32 +0000 Subject: [PATCH 032/113] Initial commit of AuthCode grant type --- src/OAuth2/Grant/AuthCode.php | 130 ++++++++++++++++++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 src/OAuth2/Grant/AuthCode.php diff --git a/src/OAuth2/Grant/AuthCode.php b/src/OAuth2/Grant/AuthCode.php new file mode 100644 index 00000000..05701013 --- /dev/null +++ b/src/OAuth2/Grant/AuthCode.php @@ -0,0 +1,130 @@ +identifier; + } + + public function getResponseType() + { + return $this->responseType; + } + + public function completeFlow() + { + /* + // Client ID + if ( ! isset($authParams['client_id']) && ! isset($_POST['client_id'])) { + throw new ClientException(sprintf($this->errors['invalid_request'], 'client_id'), 0); + } + + $params['client_id'] = (isset($authParams['client_id'])) ? + $authParams['client_id'] : + $_POST['client_id']; + + // Client secret + if ( ! isset($authParams['client_secret']) && ! isset($_POST['client_secret'])) { + throw new ClientException(sprintf($this->errors['invalid_request'], 'client_secret'), 0); + } + + $params['client_secret'] = (isset($authParams['client_secret'])) ? + $authParams['client_secret'] : + $_POST['client_secret']; + + // Redirect URI + if ( ! isset($authParams['redirect_uri']) && ! isset($_POST['redirect_uri'])) { + throw new ClientException(sprintf($this->errors['invalid_request'], 'redirect_uri'), 0); + } + + $params['redirect_uri'] = (isset($authParams['redirect_uri'])) ? + $authParams['redirect_uri'] : + $_POST['redirect_uri']; + + // Validate client ID and redirect URI + $clientDetails = $this->_dbCall( + 'validateClient', + $params['client_id'], + $params['client_secret'], + $params['redirect_uri'] + ); + + if ($clientDetails === false) { + throw new ClientException($this->errors['invalid_client'], 8); + } + + // The authorization code + if ( ! isset($authParams['code']) && ! isset($_POST['code'])) { + throw new ClientException(sprintf($this->errors['invalid_request'], 'code'), 0); + } + + $params['code'] = (isset($authParams['code'])) ? + $authParams['code'] : + $_POST['code']; + + // Verify the authorization code matches the client_id and the request_uri + $session = $this->_dbCall( + 'validateAuthCode', + $params['client_id'], + $params['redirect_uri'], + $params['code'] + ); + + if ( ! $session) { + throw new ClientException(sprintf($this->errors['invalid_grant'], 'code'), 9); + } + + // A session ID was returned so update it with an access token, + // remove the authorisation code, change the stage to 'granted' + + $accessToken = $this->_generateCode(); + $refreshToken = ($this->_grantTypes['refresh_token']) ? + $this->_generateCode() : + null; + + $accessTokenExpires = time() + $this->_config['access_token_ttl']; + $accessTokenExpiresIn = $this->_config['access_token_ttl']; + + $this->_dbCall( + 'updateSession', + $session['id'], + null, + $accessToken, + $refreshToken, + $accessTokenExpires, + 'granted' + ); + + // Update the session's scopes to reference the access token + $this->_dbCall( + 'updateSessionScopeAccessToken', + $session['id'], + $accessToken, + $refreshToken + ); + + $response = array( + 'access_token' => $accessToken, + 'token_type' => 'bearer', + 'expires' => $accessTokenExpires, + 'expires_in' => $accessTokenExpiresIn + ); + + if ($this->_grantTypes['refresh_token']) { + $response['refresh_token'] = $refreshToken; + } + + return $response; + + */ + } + +} \ No newline at end of file From 6eb5db02391ba0cc1aa319b51e8a8c557625c273 Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Fri, 1 Feb 2013 14:41:10 +0000 Subject: [PATCH 033/113] Lots of bug fixes. Some methods and variables made static so they can be accessed by grant classes. --- src/OAuth2/AuthServer.php | 113 +++++++++++++++++++++----------------- 1 file changed, 62 insertions(+), 51 deletions(-) diff --git a/src/OAuth2/AuthServer.php b/src/OAuth2/AuthServer.php index bd14fcff..cc07c02d 100644 --- a/src/OAuth2/AuthServer.php +++ b/src/OAuth2/AuthServer.php @@ -6,6 +6,7 @@ use OAuth2\Util\SecureKey; use OAuth2\Storage\SessionInterface; use OAuth2\Storage\ClientInterface; use OAuth2\Storage\ScopeInterface; +use OAuth2\Grant\GrantTypeInterface; class AuthServer { @@ -23,7 +24,7 @@ class AuthServer protected $responseTypes = array(); - protected $storages = array(); + static protected $storages = array(); protected $grantTypes = array(); @@ -50,7 +51,7 @@ class AuthServer * Exception error messages * @var array */ - protected $exceptionMessages = array( + static protected $exceptionMessages = array( 'invalid_request' => 'The request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed. Check the "%s" parameter.', 'unauthorized_client' => 'The client is not authorized to request an access token using this method.', 'access_denied' => 'The resource owner or authorization server denied the request.', @@ -65,9 +66,14 @@ class AuthServer 'invalid_refresh' => 'The refresh token is invalid.', ); + public static function getExceptionMessage($error = '') + { + return self::$exceptionMessages[$error]; + } + public function __construct(ClientInterface $client, SessionInterface $session, ScopeInterface $scope) { - $this->storages = array( + self::$storages = array( 'client' => $client, 'session' => $session, 'scope' => $scope @@ -86,6 +92,11 @@ class AuthServer } } + public static function hasGrantType($identifier) + { + return (array_key_exists($identifier, $this->grantTypes)); + } + public function getScopeDelimeter() { return $this->scopeDelimeter; @@ -96,14 +107,14 @@ class AuthServer $this->scopeDelimeter = $scope_delimeter; } - public function getExpiresIn() + public static function getExpiresIn() { return $this->expiresIn; } - public function setExpiresIn($expires_in) + public function setExpiresIn($expiresIn) { - $this->expiresIn = $expires_in; + $this->expiresIn = $expiresIn; } /** @@ -130,69 +141,69 @@ class AuthServer return $this->request; } - public function getStorage($obj) + public static function getStorage($obj) { - return $this->storages[$obj]; + return self::$storages[$obj]; } /** * Check authorise parameters * * @access public - * @param array $authParams Optional array of parsed $_GET keys + * @param array $inputParams Optional array of parsed $_GET keys * @return array Authorise request parameters */ - public function checkAuthoriseParams($authParams = null) + public function checkAuthoriseParams($inputParams = array()) { - $params = array(); + $authParams = array(); // Client ID - $params['client_id'] = (isset($authParams['client_id'])) ? - $authParams['client_id'] : + $authParams['client_id'] = (isset($inputParams['client_id'])) ? + $inputParams['client_id'] : $this->getRequest()->get('client_id'); - if (is_null($params['client_id'])) { - throw new Exception\ClientException(sprintf($this->exceptionMessages['invalid_request'], 'client_id'), 0); + if (is_null($authParams['client_id'])) { + throw new Exception\ClientException(sprintf(self::$exceptionMessages['invalid_request'], 'client_id'), 0); } // Redirect URI - $params['redirect_uri'] = (isset($authParams['redirect_uri'])) ? - $authParams['redirect_uri'] : + $authParams['redirect_uri'] = (isset($inputParams['redirect_uri'])) ? + $inputParams['redirect_uri'] : $this->getRequest()->get('redirect_uri'); - if (is_null($params['redirect_uri'])) { - throw new Exception\ClientException(sprintf($this->exceptionMessages['invalid_request'], 'redirect_uri'), 0); + if (is_null($authParams['redirect_uri'])) { + throw new Exception\ClientException(sprintf(self::$exceptionMessages['invalid_request'], 'redirect_uri'), 0); } // Validate client ID and redirect URI - $clientDetails = $this->getStorage('client')->get($params['client_id'], null, $params['redirect_uri']); + $clientDetails = self::getStorage('client')->get($authParams['client_id'], null, $authParams['redirect_uri']); if ($clientDetails === false) { - throw new Exception\ClientException($this->exceptionMessages['invalid_client'], 8); + throw new Exception\ClientException(self::$exceptionMessages['invalid_client'], 8); } - $params['client_details'] = $clientDetails; + $authParams['client_details'] = $clientDetails; // Response type - $params['response_type'] = (isset($authParams['response_type'])) ? - $authParams['response_type'] : + $authParams['response_type'] = (isset($inputParams['response_type'])) ? + $inputParams['response_type'] : $this->getRequest()->get('response_type'); - if (is_null($params['response_type'])) { - throw new Exception\ClientException(sprintf($this->exceptionMessages['invalid_request'], 'response_type'), 0); + if (is_null($authParams['response_type'])) { + throw new Exception\ClientException(sprintf(self::$exceptionMessages['invalid_request'], 'response_type'), 0); } // Ensure response type is one that is recognised - if ( ! in_array($params['response_type'], $this->responseTypes)) { - throw new Exception\ClientException($this->exceptionMessages['unsupported_response_type'], 3); + if ( ! in_array($authParams['response_type'], $this->responseTypes)) { + throw new Exception\ClientException(self::$exceptionMessages['unsupported_response_type'], 3); } // Get and validate scopes - $scopes = (isset($authParams['scope'])) ? - $authParams['scope'] : + $scopes = (isset($inputParams['scope'])) ? + $inputParams['scope'] : $this->getRequest()->get('scope', ''); - $scopes = explode($this->_config['scope_delimeter'], $scopes); + $scopes = explode($this->scopeDelimeter, $scopes); for ($i = 0; $i < count($scopes); $i++) { $scopes[$i] = trim($scopes[$i]); @@ -200,22 +211,22 @@ class AuthServer } if (count($scopes) === 0) { - throw new Exception\ClientException(sprintf($this->exceptionMessages['invalid_request'], 'scope'), 0); + throw new Exception\ClientException(sprintf(self::$exceptionMessages['invalid_request'], 'scope'), 0); } - $params['scopes'] = array(); + $authParams['scopes'] = array(); foreach ($scopes as $scope) { - $scopeDetails = $this->getStorage('scope')->get($scope); + $scopeDetails = self::getStorage('scope')->get($scope); if ($scopeDetails === false) { - throw new Exception\ClientException(sprintf($this->exceptionMessages['invalid_scope'], $scope), 4); + throw new Exception\ClientException(sprintf(self::$exceptionMessages['invalid_scope'], $scope), 4); } - $params['scopes'][] = $scopeDetails; + $authParams['scopes'][] = $scopeDetails; } - return $params; + return $authParams; } /** @@ -226,21 +237,21 @@ class AuthServer * @param array $authoriseParams The authorise request $_GET parameters * @return string An authorisation code */ - public function newAuthoriseRequest($type, $typeId, $authoriseParams) + public function newAuthoriseRequest($type, $typeId, $authParams = array()) { // Generate an auth code $authCode = SecureKey::make(); // Remove any old sessions the user might have - $this->getStorage('session')->delete($authoriseParams['client_id'], $type, $typeId); + self::getStorage('session')->delete($authParams['client_id'], $type, $typeId); // Create a new session - $sessionId = $this->getStorage('session')->create($authoriseParams['client_id'], $authoriseParams['redirect_uri'], $type, $typeId, $authCode); + $sessionId = self::getStorage('session')->create($authParams['client_id'], $authParams['redirect_uri'], $type, $typeId, $authCode); // Associate scopes with the new session - foreach ($authoriseParams['scopes'] as $scope) + foreach ($authParams['scopes'] as $scope) { - $this->getStorage('session')->associateScope($sessionId, $scope['id']); + self::getStorage('session')->associateScope($sessionId, $scope['id']); } return $authCode; @@ -250,26 +261,26 @@ class AuthServer * Issue an access token * * @access public - * @param array $authParams Optional array of parsed $_POST keys + * @param array $inputParams Optional array of parsed $_POST keys * @return array Authorise request parameters */ - public function issueAccessToken($authParams = null) + public function issueAccessToken($inputParams = array()) { - $params['grant_type'] = (isset($authParams['grant_type'])) ? - $authParams['grant_type'] : + $authParams['grant_type'] = (isset($inputParams['grant_type'])) ? + $inputParams['grant_type'] : $this->getRequest()->post('grant_type'); - if (is_null($params['grant_type'])) { - throw new Exception\ClientException(sprintf($this->errors['invalid_request'], 'grant_type'), 0); + if (is_null($authParams['grant_type'])) { + throw new Exception\ClientException(sprintf(self::$exceptionMessages['invalid_request'], 'grant_type'), 0); } // Ensure grant type is one that is recognised and is enabled - if ( ! in_array($params['grant_type'], array_keys($this->grantTypes))) { - throw new Exception\ClientException(sprintf($this->errors['unsupported_grant_type'], $params['grant_type']), 7); + if ( ! in_array($authParams['grant_type'], array_keys($this->grantTypes))) { + throw new Exception\ClientException(sprintf(self::$exceptionMessages['unsupported_grant_type'], $authParams['grant_type']), 7); } // Complete the flow - return $this->getCurrentGrantType($params['grant_type'])->completeFlow($authParams, $params); + return $this->getCurrentGrantType($authParams['grant_type'])->completeFlow($inputParams, $authParams, $this->request); } protected function getCurrentGrantType($grantType) From d732778f65a4226718c0cff0758802d85dd8fff3 Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Fri, 1 Feb 2013 14:41:52 +0000 Subject: [PATCH 034/113] Finished AuthCode grant --- src/OAuth2/Grant/AuthCode.php | 106 +++++++++++++++------------------- 1 file changed, 46 insertions(+), 60 deletions(-) diff --git a/src/OAuth2/Grant/AuthCode.php b/src/OAuth2/Grant/AuthCode.php index 05701013..f26e77f7 100644 --- a/src/OAuth2/Grant/AuthCode.php +++ b/src/OAuth2/Grant/AuthCode.php @@ -1,12 +1,18 @@ responseType; } - public function completeFlow() + public function completeFlow($inputParams = null, $authParams = array(), Request $request) { - /* // Client ID - if ( ! isset($authParams['client_id']) && ! isset($_POST['client_id'])) { - throw new ClientException(sprintf($this->errors['invalid_request'], 'client_id'), 0); - } + $authParams['client_id'] = (isset($inputParams['client_id'])) ? + $inputParams['client_id'] : + $request->post('client_id'); - $params['client_id'] = (isset($authParams['client_id'])) ? - $authParams['client_id'] : - $_POST['client_id']; + if (is_null($authParams['client_id'])) { + throw new Exception\ClientException(sprintf(AuthServer::getExceptionMessage('invalid_request'), 'client_id'), 0); + } // Client secret - if ( ! isset($authParams['client_secret']) && ! isset($_POST['client_secret'])) { - throw new ClientException(sprintf($this->errors['invalid_request'], 'client_secret'), 0); - } + $authParams['client_secret'] = (isset($inputParams['client_secret'])) ? + $inputParams['client_secret'] : + $request->post('client_secret'); - $params['client_secret'] = (isset($authParams['client_secret'])) ? - $authParams['client_secret'] : - $_POST['client_secret']; + if (is_null($authParams['client_secret'])) { + throw new Exception\ClientException(sprintf(AuthServer::getExceptionMessage('invalid_request'), 'client_secret'), 0); + } // Redirect URI - if ( ! isset($authParams['redirect_uri']) && ! isset($_POST['redirect_uri'])) { - throw new ClientException(sprintf($this->errors['invalid_request'], 'redirect_uri'), 0); - } + $authParams['redirect_uri'] = (isset($inputParams['redirect_uri'])) ? + $inputParams['redirect_uri'] : + $request->post('redirect_uri'); - $params['redirect_uri'] = (isset($authParams['redirect_uri'])) ? - $authParams['redirect_uri'] : - $_POST['redirect_uri']; + if (is_null($authParams['redirect_uri'])) { + throw new Exception\ClientException(sprintf(AuthServer::getExceptionMessage('invalid_request'), 'redirect_uri'), 0); + } // Validate client ID and redirect URI - $clientDetails = $this->_dbCall( - 'validateClient', - $params['client_id'], - $params['client_secret'], - $params['redirect_uri'] - ); + $clientDetails = AuthServer::getStorage('client')->get($authParams['client_id'], null, $authParams['redirect_uri']); if ($clientDetails === false) { - throw new ClientException($this->errors['invalid_client'], 8); + throw new Exception\ClientException(AuthServer::getExceptionMessage('invalid_client'), 8); } + $authParams['client_details'] = $clientDetails; + // The authorization code - if ( ! isset($authParams['code']) && ! isset($_POST['code'])) { - throw new ClientException(sprintf($this->errors['invalid_request'], 'code'), 0); + $authParams['code'] = (isset($inputParams['code'])) ? + $inputParams['code'] : + $request->post('code'); + + if (is_null($authParams['code'])) { + throw new Exception\ClientException(sprintf(AuthServer::getExceptionMessage('invalid_request'), 'code'), 0); } - $params['code'] = (isset($authParams['code'])) ? - $authParams['code'] : - $_POST['code']; - // Verify the authorization code matches the client_id and the request_uri - $session = $this->_dbCall( - 'validateAuthCode', - $params['client_id'], - $params['redirect_uri'], - $params['code'] - ); + $session = AuthServer::getStorage('session')->validateAuthCode($authParams['client_id'], $authParams['redirect_uri'], $authParams['code']); if ( ! $session) { - throw new ClientException(sprintf($this->errors['invalid_grant'], 'code'), 9); + throw new Exception\ClientException(sprintf(AuthServer::getExceptionMessage('invalid_grant'), 'code'), 9); } // A session ID was returned so update it with an access token, // remove the authorisation code, change the stage to 'granted' - $accessToken = $this->_generateCode(); - $refreshToken = ($this->_grantTypes['refresh_token']) ? - $this->_generateCode() : + $accessToken = SecureKey::make(); + $refreshToken = (AuthServer::hasGrantType('refresh_token')) ? + SecureKey::make() : null; - $accessTokenExpires = time() + $this->_config['access_token_ttl']; - $accessTokenExpiresIn = $this->_config['access_token_ttl']; + $accessTokenExpires = time() + AuthServer::getExpiresIn(); + $accessTokenExpiresIn = AuthServer::getExpiresIn(); - $this->_dbCall( - 'updateSession', + AuthServer::getStorage('session')->update( $session['id'], null, $accessToken, @@ -103,14 +99,6 @@ class AuthCode implements GrantTypeInterface { 'granted' ); - // Update the session's scopes to reference the access token - $this->_dbCall( - 'updateSessionScopeAccessToken', - $session['id'], - $accessToken, - $refreshToken - ); - $response = array( 'access_token' => $accessToken, 'token_type' => 'bearer', @@ -118,13 +106,11 @@ class AuthCode implements GrantTypeInterface { 'expires_in' => $accessTokenExpiresIn ); - if ($this->_grantTypes['refresh_token']) { + if (AuthServer::hasGrantType('refresh_token')) { $response['refresh_token'] = $refreshToken; } return $response; - - */ } } \ No newline at end of file From 2c1dedfe8a9f9b8d8850db1b4c1d5557d326fd32 Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Fri, 1 Feb 2013 14:56:36 +0000 Subject: [PATCH 035/113] Updated grantTypeInterface --- src/OAuth2/Grant/GrantTypeInterface.php | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/OAuth2/Grant/GrantTypeInterface.php b/src/OAuth2/Grant/GrantTypeInterface.php index 67a389c2..206f00fc 100644 --- a/src/OAuth2/Grant/GrantTypeInterface.php +++ b/src/OAuth2/Grant/GrantTypeInterface.php @@ -1,6 +1,14 @@ Date: Fri, 1 Feb 2013 15:02:36 +0000 Subject: [PATCH 036/113] < PHP5.4 array syntax --- src/OAuth2/Util/SecureKey.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/OAuth2/Util/SecureKey.php b/src/OAuth2/Util/SecureKey.php index 0739a193..eaa741c7 100644 --- a/src/OAuth2/Util/SecureKey.php +++ b/src/OAuth2/Util/SecureKey.php @@ -16,6 +16,6 @@ class SecureKey throw new Exception('Error Generating Key'); } - return substr(str_replace(['/', '+', '='], '', base64_encode($bytes)), 0, $len); + return substr(str_replace(array('/', '+', '='), '', base64_encode($bytes)), 0, $len); } } \ No newline at end of file From aec9aa908cc40338679c2af6fb0da6628a076e6f Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Fri, 1 Feb 2013 15:07:47 +0000 Subject: [PATCH 037/113] Made getRequest static --- src/OAuth2/AuthServer.php | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/OAuth2/AuthServer.php b/src/OAuth2/AuthServer.php index cc07c02d..87f8e2dd 100644 --- a/src/OAuth2/AuthServer.php +++ b/src/OAuth2/AuthServer.php @@ -28,7 +28,7 @@ class AuthServer protected $grantTypes = array(); - protected $request = null; + static protected $request = null; /** * Exception error codes @@ -132,13 +132,13 @@ class AuthServer * * @return RequestInterface */ - public function getRequest() + public static function getRequest() { - if ($this->request === null) { - $this->request = Request::buildFromGlobals(); + if (self::$request === null) { + self::$request = Request::buildFromGlobals(); } - return $this->request; + return self::$request; } public static function getStorage($obj) @@ -160,7 +160,7 @@ class AuthServer // Client ID $authParams['client_id'] = (isset($inputParams['client_id'])) ? $inputParams['client_id'] : - $this->getRequest()->get('client_id'); + self::getRequest()->get('client_id'); if (is_null($authParams['client_id'])) { throw new Exception\ClientException(sprintf(self::$exceptionMessages['invalid_request'], 'client_id'), 0); @@ -169,7 +169,7 @@ class AuthServer // Redirect URI $authParams['redirect_uri'] = (isset($inputParams['redirect_uri'])) ? $inputParams['redirect_uri'] : - $this->getRequest()->get('redirect_uri'); + self::getRequest()->get('redirect_uri'); if (is_null($authParams['redirect_uri'])) { throw new Exception\ClientException(sprintf(self::$exceptionMessages['invalid_request'], 'redirect_uri'), 0); @@ -187,7 +187,7 @@ class AuthServer // Response type $authParams['response_type'] = (isset($inputParams['response_type'])) ? $inputParams['response_type'] : - $this->getRequest()->get('response_type'); + self::getRequest()->get('response_type'); if (is_null($authParams['response_type'])) { throw new Exception\ClientException(sprintf(self::$exceptionMessages['invalid_request'], 'response_type'), 0); @@ -201,7 +201,7 @@ class AuthServer // Get and validate scopes $scopes = (isset($inputParams['scope'])) ? $inputParams['scope'] : - $this->getRequest()->get('scope', ''); + self::getRequest()->get('scope', ''); $scopes = explode($this->scopeDelimeter, $scopes); @@ -268,7 +268,7 @@ class AuthServer { $authParams['grant_type'] = (isset($inputParams['grant_type'])) ? $inputParams['grant_type'] : - $this->getRequest()->post('grant_type'); + self::getRequest()->post('grant_type'); if (is_null($authParams['grant_type'])) { throw new Exception\ClientException(sprintf(self::$exceptionMessages['invalid_request'], 'grant_type'), 0); @@ -280,7 +280,7 @@ class AuthServer } // Complete the flow - return $this->getCurrentGrantType($authParams['grant_type'])->completeFlow($inputParams, $authParams, $this->request); + return $this->getCurrentGrantType($authParams['grant_type'])->completeFlow($inputParams, $authParams); } protected function getCurrentGrantType($grantType) From 2a8688b54e99a3d7b560ec1aed5db559d1d3153b Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Fri, 1 Feb 2013 15:09:15 +0000 Subject: [PATCH 038/113] Update getRequest calls to static requests --- src/OAuth2/Grant/AuthCode.php | 10 +++++----- src/OAuth2/Grant/GrantTypeInterface.php | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/OAuth2/Grant/AuthCode.php b/src/OAuth2/Grant/AuthCode.php index f26e77f7..efd2659a 100644 --- a/src/OAuth2/Grant/AuthCode.php +++ b/src/OAuth2/Grant/AuthCode.php @@ -25,12 +25,12 @@ class AuthCode implements GrantTypeInterface { return $this->responseType; } - public function completeFlow($inputParams = null, $authParams = array(), Request $request) + public function completeFlow($inputParams = null, $authParams = array()) { // Client ID $authParams['client_id'] = (isset($inputParams['client_id'])) ? $inputParams['client_id'] : - $request->post('client_id'); + AuthServer::getRequest()->post('client_id'); if (is_null($authParams['client_id'])) { throw new Exception\ClientException(sprintf(AuthServer::getExceptionMessage('invalid_request'), 'client_id'), 0); @@ -39,7 +39,7 @@ class AuthCode implements GrantTypeInterface { // Client secret $authParams['client_secret'] = (isset($inputParams['client_secret'])) ? $inputParams['client_secret'] : - $request->post('client_secret'); + AuthServer::getRequest()->post('client_secret'); if (is_null($authParams['client_secret'])) { throw new Exception\ClientException(sprintf(AuthServer::getExceptionMessage('invalid_request'), 'client_secret'), 0); @@ -48,7 +48,7 @@ class AuthCode implements GrantTypeInterface { // Redirect URI $authParams['redirect_uri'] = (isset($inputParams['redirect_uri'])) ? $inputParams['redirect_uri'] : - $request->post('redirect_uri'); + AuthServer::getRequest()->post('redirect_uri'); if (is_null($authParams['redirect_uri'])) { throw new Exception\ClientException(sprintf(AuthServer::getExceptionMessage('invalid_request'), 'redirect_uri'), 0); @@ -66,7 +66,7 @@ class AuthCode implements GrantTypeInterface { // The authorization code $authParams['code'] = (isset($inputParams['code'])) ? $inputParams['code'] : - $request->post('code'); + AuthServer::getRequest()->post('code'); if (is_null($authParams['code'])) { throw new Exception\ClientException(sprintf(AuthServer::getExceptionMessage('invalid_request'), 'code'), 0); diff --git a/src/OAuth2/Grant/GrantTypeInterface.php b/src/OAuth2/Grant/GrantTypeInterface.php index 206f00fc..6f00c8b5 100644 --- a/src/OAuth2/Grant/GrantTypeInterface.php +++ b/src/OAuth2/Grant/GrantTypeInterface.php @@ -16,5 +16,5 @@ interface GrantTypeInterface public function getResponseType(); - public function completeFlow($inputParams = null, $authParams = array(), Request $request); + public function completeFlow($inputParams = null, $authParams = array()); } From 3aa8465640e76450e4961c2af94ae44f643c103b Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Fri, 1 Feb 2013 15:23:04 +0000 Subject: [PATCH 039/113] Made $grantTypes static to fix ref bug --- src/OAuth2/AuthServer.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/OAuth2/AuthServer.php b/src/OAuth2/AuthServer.php index 87f8e2dd..464eba35 100644 --- a/src/OAuth2/AuthServer.php +++ b/src/OAuth2/AuthServer.php @@ -26,7 +26,7 @@ class AuthServer static protected $storages = array(); - protected $grantTypes = array(); + static protected $grantTypes = array(); static protected $request = null; @@ -94,7 +94,7 @@ class AuthServer public static function hasGrantType($identifier) { - return (array_key_exists($identifier, $this->grantTypes)); + return (array_key_exists($identifier, self::$grantTypes)); } public function getScopeDelimeter() From fcf57abbb2ca92b86d1c5724e559e43994788d14 Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Fri, 1 Feb 2013 15:24:01 +0000 Subject: [PATCH 040/113] Removed guzzle dependancy --- composer.json | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/composer.json b/composer.json index b12af92c..e5951b33 100644 --- a/composer.json +++ b/composer.json @@ -5,8 +5,7 @@ "homepage": "https://github.com/lncd/OAuth2", "license": "MIT", "require": { - "php": ">=5.3.0", - "guzzle/guzzle": "*" + "php": ">=5.3.0" }, "require-dev": { "phpunit/phpunit": "*" @@ -38,7 +37,5 @@ "OAuth2": "src/" } }, - "suggest": { - "lncd/oauth2-facebook": "Adds support for Facebook as an IDP" - } + "suggest": {} } From 47731ce9019f540504188abf3ddffcc5c2bc200d Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Fri, 1 Feb 2013 15:28:25 +0000 Subject: [PATCH 041/113] $expiresIn now static --- src/OAuth2/AuthServer.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/OAuth2/AuthServer.php b/src/OAuth2/AuthServer.php index 464eba35..e499b738 100644 --- a/src/OAuth2/AuthServer.php +++ b/src/OAuth2/AuthServer.php @@ -20,7 +20,7 @@ class AuthServer */ protected $scopeDelimeter = ','; - protected $expiresIn = 3600; + static protected $expiresIn = 3600; protected $responseTypes = array(); @@ -109,7 +109,7 @@ class AuthServer public static function getExpiresIn() { - return $this->expiresIn; + return self::$expiresIn; } public function setExpiresIn($expiresIn) From a3a617171aaddd8ad569769d6ea4e602f7fa63f1 Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Fri, 1 Feb 2013 15:28:40 +0000 Subject: [PATCH 042/113] $grantTypes static access --- src/OAuth2/AuthServer.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/OAuth2/AuthServer.php b/src/OAuth2/AuthServer.php index e499b738..c09ac8d5 100644 --- a/src/OAuth2/AuthServer.php +++ b/src/OAuth2/AuthServer.php @@ -85,7 +85,7 @@ class AuthServer if (is_null($identifier)) { $identifier = $grantType->getIdentifier(); } - $this->grantTypes[$identifier] = $grantType; + self::$grantTypes[$identifier] = $grantType; if ( ! is_null($grantType->getResponseType())) { $this->responseTypes[] = $grantType->getResponseType(); @@ -275,7 +275,7 @@ class AuthServer } // Ensure grant type is one that is recognised and is enabled - if ( ! in_array($authParams['grant_type'], array_keys($this->grantTypes))) { + if ( ! in_array($authParams['grant_type'], array_keys(self::$grantTypes))) { throw new Exception\ClientException(sprintf(self::$exceptionMessages['unsupported_grant_type'], $authParams['grant_type']), 7); } @@ -285,7 +285,7 @@ class AuthServer protected function getCurrentGrantType($grantType) { - return $this->grantTypes[$grantType]; + return self::$grantTypes[$grantType]; } } From 9fd7ccc137f7292db5e4247bdde9ae82870b6534 Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Fri, 1 Feb 2013 15:51:51 +0000 Subject: [PATCH 043/113] Added ClientCredentials grant --- src/OAuth2/Grant/ClientCredentials.php | 94 ++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 src/OAuth2/Grant/ClientCredentials.php diff --git a/src/OAuth2/Grant/ClientCredentials.php b/src/OAuth2/Grant/ClientCredentials.php new file mode 100644 index 00000000..02fdf5ab --- /dev/null +++ b/src/OAuth2/Grant/ClientCredentials.php @@ -0,0 +1,94 @@ +identifier; + } + + public function getResponseType() + { + return $this->responseType; + } + + public function completeFlow($inputParams = null, $authParams = array()) + { + // Client ID + $authParams['client_id'] = (isset($inputParams['client_id'])) ? + $inputParams['client_id'] : + AuthServer::getRequest()->post('client_id'); + + if (is_null($authParams['client_id'])) { + throw new Exception\ClientException(sprintf(AuthServer::getExceptionMessage('invalid_request'), 'client_id'), 0); + } + + // Client secret + $authParams['client_secret'] = (isset($inputParams['client_secret'])) ? + $inputParams['client_secret'] : + AuthServer::getRequest()->post('client_secret'); + + if (is_null($authParams['client_secret'])) { + throw new Exception\ClientException(sprintf(AuthServer::getExceptionMessage('invalid_request'), 'client_secret'), 0); + } + + // Validate client ID and redirect URI + $clientDetails = AuthServer::getStorage('client')->get($authParams['client_id'], $authParams['client_secret']); + + if ($clientDetails === false) { + throw new Exception\ClientException(AuthServer::getExceptionMessage('invalid_client'), 8); + } + + $authParams['client_details'] = $clientDetails; + + // Generate an access token + $accessToken = SecureKey::make(); + $refreshToken = (AuthServer::hasGrantType('refresh_token')) ? SecureKey::make() : null; + + $accessTokenExpires = time() + AuthServer::getExpiresIn(); + $accessTokenExpiresIn = AuthServer::getExpiresIn(); + + // Delete any existing sessions just to be sure + AuthServer::getStorage('session')->deleteSession($params['client_id'], 'client', $params['client_id']); + + // Create a new session + AuthServer::getStorage('session')->newSession( + $params['client_id'], + null, + 'client', + $params['client_id'], + null, + $accessToken, + $refreshToken, + $accessTokenExpires, + 'granted' + ); + + $response = array( + 'access_token' => $accessToken, + 'token_type' => 'bearer', + 'expires' => $accessTokenExpires, + 'expires_in' => $accessTokenExpiresIn + ); + + if (AuthServer::hasGrantType('refresh_token')) { + $response['refresh_token'] = $refreshToken; + } + + return $response; + } + +} \ No newline at end of file From 5abb84eda0a0bf4edb848aadd43cfcbc14ac068e Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Fri, 1 Feb 2013 15:59:43 +0000 Subject: [PATCH 044/113] Validate all client credentials --- src/OAuth2/Grant/AuthCode.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/OAuth2/Grant/AuthCode.php b/src/OAuth2/Grant/AuthCode.php index efd2659a..9ac86911 100644 --- a/src/OAuth2/Grant/AuthCode.php +++ b/src/OAuth2/Grant/AuthCode.php @@ -55,7 +55,7 @@ class AuthCode implements GrantTypeInterface { } // Validate client ID and redirect URI - $clientDetails = AuthServer::getStorage('client')->get($authParams['client_id'], null, $authParams['redirect_uri']); + $clientDetails = AuthServer::getStorage('client')->get($authParams['client_id'], $authParams['client_secret'], $authParams['redirect_uri']); if ($clientDetails === false) { throw new Exception\ClientException(AuthServer::getExceptionMessage('invalid_client'), 8); From e8d43f208768fb75f2fc51d6b5e030f28cf043d3 Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Fri, 1 Feb 2013 15:59:50 +0000 Subject: [PATCH 045/113] Anal restyle --- src/OAuth2/Grant/AuthCode.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/OAuth2/Grant/AuthCode.php b/src/OAuth2/Grant/AuthCode.php index 9ac86911..758611e3 100644 --- a/src/OAuth2/Grant/AuthCode.php +++ b/src/OAuth2/Grant/AuthCode.php @@ -83,9 +83,7 @@ class AuthCode implements GrantTypeInterface { // remove the authorisation code, change the stage to 'granted' $accessToken = SecureKey::make(); - $refreshToken = (AuthServer::hasGrantType('refresh_token')) ? - SecureKey::make() : - null; + $refreshToken = (AuthServer::hasGrantType('refresh_token')) ? SecureKey::make() : null; $accessTokenExpires = time() + AuthServer::getExpiresIn(); $accessTokenExpiresIn = AuthServer::getExpiresIn(); From a81c486e0eef827189b074f63fe4df64c24451e3 Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Fri, 1 Feb 2013 16:00:00 +0000 Subject: [PATCH 046/113] Spelling fix --- src/OAuth2/Grant/ClientCredentials.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/OAuth2/Grant/ClientCredentials.php b/src/OAuth2/Grant/ClientCredentials.php index 02fdf5ab..0881777e 100644 --- a/src/OAuth2/Grant/ClientCredentials.php +++ b/src/OAuth2/Grant/ClientCredentials.php @@ -62,7 +62,7 @@ class ClientCredentials implements GrantTypeInterface { $accessTokenExpiresIn = AuthServer::getExpiresIn(); // Delete any existing sessions just to be sure - AuthServer::getStorage('session')->deleteSession($params['client_id'], 'client', $params['client_id']); + AuthServer::getStorage('session')->delete($params['client_id'], 'client', $params['client_id']); // Create a new session AuthServer::getStorage('session')->newSession( From 85c42db3552ec3527147456595a077b79b5c609d Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Fri, 1 Feb 2013 16:02:04 +0000 Subject: [PATCH 047/113] Variable name fix --- src/OAuth2/Grant/ClientCredentials.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/OAuth2/Grant/ClientCredentials.php b/src/OAuth2/Grant/ClientCredentials.php index 0881777e..0489d38d 100644 --- a/src/OAuth2/Grant/ClientCredentials.php +++ b/src/OAuth2/Grant/ClientCredentials.php @@ -62,14 +62,14 @@ class ClientCredentials implements GrantTypeInterface { $accessTokenExpiresIn = AuthServer::getExpiresIn(); // Delete any existing sessions just to be sure - AuthServer::getStorage('session')->delete($params['client_id'], 'client', $params['client_id']); + AuthServer::getStorage('session')->delete($authParams['client_id'], 'client', $authParams['client_id']); // Create a new session AuthServer::getStorage('session')->newSession( - $params['client_id'], + $authParams['client_id'], null, 'client', - $params['client_id'], + $authParams['client_id'], null, $accessToken, $refreshToken, From 5e365bb9746ca9422efceb537dc5a67574579493 Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Fri, 1 Feb 2013 16:02:38 +0000 Subject: [PATCH 048/113] Function name fix --- src/OAuth2/Grant/ClientCredentials.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/OAuth2/Grant/ClientCredentials.php b/src/OAuth2/Grant/ClientCredentials.php index 0489d38d..fe5ee23e 100644 --- a/src/OAuth2/Grant/ClientCredentials.php +++ b/src/OAuth2/Grant/ClientCredentials.php @@ -65,7 +65,7 @@ class ClientCredentials implements GrantTypeInterface { AuthServer::getStorage('session')->delete($authParams['client_id'], 'client', $authParams['client_id']); // Create a new session - AuthServer::getStorage('session')->newSession( + AuthServer::getStorage('session')->create( $authParams['client_id'], null, 'client', From f855b572e8ff36d94af552bda3671413f5b023f2 Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Fri, 1 Feb 2013 16:50:59 +0000 Subject: [PATCH 049/113] First commit of new refresh token grant --- src/OAuth2/Grant/RefreshToken.php | 94 +++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 src/OAuth2/Grant/RefreshToken.php diff --git a/src/OAuth2/Grant/RefreshToken.php b/src/OAuth2/Grant/RefreshToken.php new file mode 100644 index 00000000..e4e3fb51 --- /dev/null +++ b/src/OAuth2/Grant/RefreshToken.php @@ -0,0 +1,94 @@ +identifier; + } + + public function getResponseType() + { + return $this->responseType; + } + + public function completeFlow($inputParams = null, $authParams = array()) + { + // Client ID + $authParams['client_id'] = (isset($inputParams['client_id'])) ? + $inputParams['client_id'] : + AuthServer::getRequest()->post('client_id'); + + if (is_null($authParams['client_id'])) { + throw new Exception\ClientException(sprintf(AuthServer::getExceptionMessage('invalid_request'), 'client_id'), 0); + } + + // Client secret + $authParams['client_secret'] = (isset($inputParams['client_secret'])) ? + $inputParams['client_secret'] : + AuthServer::getRequest()->post('client_secret'); + + if (is_null($authParams['client_secret'])) { + throw new Exception\ClientException(sprintf(AuthServer::getExceptionMessage('invalid_request'), 'client_secret'), 0); + } + + // Validate client ID and redirect URI + $clientDetails = AuthServer::getStorage('client')->get($authParams['client_id'], $authParams['client_secret']); + + if ($clientDetails === false) { + throw new Exception\ClientException(AuthServer::getExceptionMessage('invalid_client'), 8); + } + + $authParams['client_details'] = $clientDetails; + + // Refresh token + $authParams['refresh_token'] = (isset($inputParams['refresh_token'])) ? + $inputParams['refresh_token'] : + AuthServer::getRequest()->post('refresh_token'); + + if (is_null($authParams['refresh_token'])) { + throw new Exception\ClientException(sprintf(AuthServer::getExceptionMessage('invalid_request'), 'refresh_token'), 0); + } + + // Validate refresh token + $sessionId = AuthServer::getStorage('client')->validateRefreshToken( + $params['refresh_token'], + $params['client_id'] + ); + + if ($sessionId === false) { + throw new Exception\ClientException(AuthServer::getExceptionMessage('invalid_refresh'), 0); + } + + // Generate new tokens + $accessToken = SecureKey::make(); + $refreshToken = (AuthServer::hasGrantType('refresh_token')) ? SecureKey::make() : null; + + $accessTokenExpires = time() + AuthServer::getExpiresIn(); + $accessTokenExpiresIn = AuthServer::getExpiresIn(); + + AuthServer::getStorage('session')->updateRefreshToken($sessionId, $accessToken, $refreshToken, $accessTokenExpires); + + return array( + 'access_token' => $accessToken, + 'refresh_token' => $refreshToken, + 'token_type' => 'bearer', + 'expires' => $accessTokenExpires, + 'expires_in' => $accessTokenExpiresIn + ); + } + +} \ No newline at end of file From 5f8ca897727c480d19ff79924f2b5c4e90c2345e Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Mon, 4 Feb 2013 13:59:34 +0000 Subject: [PATCH 050/113] Added docblocks to the grant interface --- src/OAuth2/Grant/GrantTypeInterface.php | 41 +++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/src/OAuth2/Grant/GrantTypeInterface.php b/src/OAuth2/Grant/GrantTypeInterface.php index 6f00c8b5..e1902400 100644 --- a/src/OAuth2/Grant/GrantTypeInterface.php +++ b/src/OAuth2/Grant/GrantTypeInterface.php @@ -12,9 +12,50 @@ use OAuth2\Storage\ScopeInterface; interface GrantTypeInterface { + /** + * The grant type identifier + * @var string + */ + protected $identifier = ''; + + /** + * The response type + * + * This is not used for most grant types + * + * @var null|string + */ + protected $responseType = null; + + /** + * Returns the grant identifier (used to validate grant_type in OAuth2\AuthServer\issueAccessToken()) + * @return string + */ public function getIdentifier(); + /** + * Returns the response type (used to validate response_type in OAuth2\AuthServer\checkAuthoriseParams()) + * @return null|string + */ public function getResponseType(); + /** + * Complete the grant flow + * + * Example response: + * + * array( + * 'access_token' => (string), // The access token + * 'refresh_token' => (string), // The refresh token (only set if the refresh token grant is enabled) + * 'token_type' => 'bearer', // Almost always "bearer" (exceptions: JWT, SAML) + * 'expires' => (int), // The timestamp of when the access token will expire + * 'expires_in' => (int) // The number of seconds before the access token will expire + * ) + * + * + * @param null|array $inputParams Null unless the input parameters have been manually set + * @param array $authParams The authorisation paramaters that have been set so far in the request + * @return array An array of parameters to be passed back to the client + */ public function completeFlow($inputParams = null, $authParams = array()); } From 3c7fe00130cf4525f937351af8634e102edfb88e Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Mon, 4 Feb 2013 14:41:40 +0000 Subject: [PATCH 051/113] Renamed some session methods to avoid conflicts with ORM methods --- src/OAuth2/AuthServer.php | 4 ++-- src/OAuth2/Grant/AuthCode.php | 2 +- src/OAuth2/Grant/ClientCredentials.php | 4 ++-- src/OAuth2/Storage/SessionInterface.php | 8 ++++---- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/OAuth2/AuthServer.php b/src/OAuth2/AuthServer.php index c09ac8d5..92c4ac82 100644 --- a/src/OAuth2/AuthServer.php +++ b/src/OAuth2/AuthServer.php @@ -243,10 +243,10 @@ class AuthServer $authCode = SecureKey::make(); // Remove any old sessions the user might have - self::getStorage('session')->delete($authParams['client_id'], $type, $typeId); + self::getStorage('session')->deleteSession($authParams['client_id'], $type, $typeId); // Create a new session - $sessionId = self::getStorage('session')->create($authParams['client_id'], $authParams['redirect_uri'], $type, $typeId, $authCode); + $sessionId = self::getStorage('session')->createSession($authParams['client_id'], $authParams['redirect_uri'], $type, $typeId, $authCode); // Associate scopes with the new session foreach ($authParams['scopes'] as $scope) diff --git a/src/OAuth2/Grant/AuthCode.php b/src/OAuth2/Grant/AuthCode.php index 758611e3..960996c2 100644 --- a/src/OAuth2/Grant/AuthCode.php +++ b/src/OAuth2/Grant/AuthCode.php @@ -88,7 +88,7 @@ class AuthCode implements GrantTypeInterface { $accessTokenExpires = time() + AuthServer::getExpiresIn(); $accessTokenExpiresIn = AuthServer::getExpiresIn(); - AuthServer::getStorage('session')->update( + AuthServer::getStorage('session')->updateSession( $session['id'], null, $accessToken, diff --git a/src/OAuth2/Grant/ClientCredentials.php b/src/OAuth2/Grant/ClientCredentials.php index fe5ee23e..75380819 100644 --- a/src/OAuth2/Grant/ClientCredentials.php +++ b/src/OAuth2/Grant/ClientCredentials.php @@ -62,10 +62,10 @@ class ClientCredentials implements GrantTypeInterface { $accessTokenExpiresIn = AuthServer::getExpiresIn(); // Delete any existing sessions just to be sure - AuthServer::getStorage('session')->delete($authParams['client_id'], 'client', $authParams['client_id']); + AuthServer::getStorage('session')->deleteSession($authParams['client_id'], 'client', $authParams['client_id']); // Create a new session - AuthServer::getStorage('session')->create( + AuthServer::getStorage('session')->createSession( $authParams['client_id'], null, 'client', diff --git a/src/OAuth2/Storage/SessionInterface.php b/src/OAuth2/Storage/SessionInterface.php index a84e50d2..f886339a 100644 --- a/src/OAuth2/Storage/SessionInterface.php +++ b/src/OAuth2/Storage/SessionInterface.php @@ -26,7 +26,7 @@ interface SessionInterface * @param string $stage The stage of the session (default ="request") * @return int The session ID */ - public function create( + public function createSession( $clientId, $redirectUri, $type = 'user', @@ -56,7 +56,7 @@ interface SessionInterface * @param string $stage The stage of the session (default ="request") * @return void */ - public function update( + public function updateSession( $sessionId, $authCode = null, $accessToken = null, @@ -78,7 +78,7 @@ interface SessionInterface * @param string $typeId The session owner's ID * @return void */ - public function delete( + public function deleteSession( $clientId, $type, $typeId @@ -100,7 +100,7 @@ interface SessionInterface * @return string|null Return the session ID as an integer if * found otherwise returns false */ - public function exists( + public function sessionExists( $type, $typeId, $clientId From 91bf8cc241aa59e4e89ed2e57f8731b5dfbf79cf Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Mon, 4 Feb 2013 14:42:14 +0000 Subject: [PATCH 052/113] Removed old Authentication folder --- src/OAuth2/Authentication/Database.php | 357 ----------- src/OAuth2/Authentication/Server.php | 791 ------------------------- 2 files changed, 1148 deletions(-) delete mode 100644 src/OAuth2/Authentication/Database.php delete mode 100644 src/OAuth2/Authentication/Server.php diff --git a/src/OAuth2/Authentication/Database.php b/src/OAuth2/Authentication/Database.php deleted file mode 100644 index aafaa4b7..00000000 --- a/src/OAuth2/Authentication/Database.php +++ /dev/null @@ -1,357 +0,0 @@ - - * # Client ID + redirect URI - * SELECT clients.id FROM clients LEFT JOIN client_endpoints ON - * client_endpoints.client_id = clients.id WHERE clients.id = $clientId AND - * client_endpoints.redirect_uri = $redirectUri - * - * # Client ID + client secret - * SELECT clients.id FROM clients WHERE clients.id = $clientId AND - * clients.secret = $clientSecret - * - * # Client ID + client secret + redirect URI - * SELECT clients.id FROM clients LEFT JOIN client_endpoints ON - * client_endpoints.client_id = clients.id WHERE clients.id = $clientId AND - * clients.secret = $clientSecret AND client_endpoints.redirect_uri = - * $redirectUri - * - * - * Response: - * - * - * Array - * ( - * [client_id] => (string) The client ID - * [client secret] => (string) The client secret - * [redirect_uri] => (string) The redirect URI used in this request - * [name] => (string) The name of the client - * ) - * - * - * @param string $clientId The client's ID - * @param string $clientSecret The client's secret (default = "null") - * @param string $redirectUri The client's redirect URI (default = "null") - * @return bool|array Returns false if the validation fails, array on success - */ - public function validateClient( - $clientId, - $clientSecret = null, - $redirectUri = null - ); - - /** - * Create a new OAuth session - * - * Database query: - * - * - * INSERT INTO oauth_sessions (client_id, redirect_uri, owner_type, - * owner_id, auth_code, access_token, refresh_token, stage, first_requested, - * last_updated) VALUES ($clientId, $redirectUri, $type, $typeId, $authCode, - * $accessToken, $stage, UNIX_TIMESTAMP(NOW()), UNIX_TIMESTAMP(NOW())) - * - * - * @param string $clientId The client ID - * @param string $redirectUri The redirect URI - * @param string $type The session owner's type (default = "user") - * @param string $typeId The session owner's ID (default = "null") - * @param string $authCode The authorisation code (default = "null") - * @param string $accessToken The access token (default = "null") - * @param string $refreshToken The refresh token (default = "null") - * @param string $stage The stage of the session (default ="request") - * @return int The session ID - */ - public function newSession( - $clientId, - $redirectUri, - $type = 'user', - $typeId = null, - $authCode = null, - $accessToken = null, - $refreshToken = null, - $accessTokenExpire = null, - $stage = 'requested' - ); - - /** - * Update an OAuth session - * - * Database query: - * - * - * UPDATE oauth_sessions SET auth_code = $authCode, access_token = - * $accessToken, stage = $stage, last_updated = UNIX_TIMESTAMP(NOW()) WHERE - * id = $sessionId - * - * - * @param string $sessionId The session ID - * @param string $authCode The authorisation code (default = "null") - * @param string $accessToken The access token (default = "null") - * @param string $refreshToken The refresh token (default = "null") - * @param string $stage The stage of the session (default ="request") - * @return void - */ - public function updateSession( - $sessionId, - $authCode = null, - $accessToken = null, - $refreshToken = null, - $accessTokenExpire = null, - $stage = 'requested' - ); - - /** - * Delete an OAuth session - * - * - * DELETE FROM oauth_sessions WHERE client_id = $clientId AND owner_type = - * $type AND owner_id = $typeId - * - * - * @param string $clientId The client ID - * @param string $type The session owner's type - * @param string $typeId The session owner's ID - * @return void - */ - public function deleteSession( - $clientId, - $type, - $typeId - ); - - public function validateRefreshToken($refreshToken, $clientId); - - /** - * Update the refresh token - * - * Database query: - * - * - * UPDATE oauth_sessions SET access_token = $newAccessToken, refresh_token = - * $newRefreshToken, access_toke_expires = $accessTokenExpires, last_updated = UNIX_TIMESTAMP(NOW()) WHERE - * id = $sessionId - * - * - * @param string $sessionId The session ID - * @param string $newAccessToken The new access token for this session - * @param string $newRefreshToken The new refresh token for the session - * @param int $accessTokenExpires The UNIX timestamp of when the new token expires - * @return void - */ - public function updateRefreshToken($sessionId, $newAccessToken, $newRefreshToken, $accessTokenExpires); - - /** - * Validate that an authorisation code is valid - * - * Database query: - * - * - * SELECT id FROM oauth_sessions WHERE client_id = $clientID AND - * redirect_uri = $redirectUri AND auth_code = $authCode - * - * - * Response: - * - * - * Array - * ( - * [id] => (int) The session ID - * [client_id] => (string) The client ID - * [redirect_uri] => (string) The redirect URI - * [owner_type] => (string) The session owner type - * [owner_id] => (string) The session owner's ID - * [auth_code] => (string) The authorisation code - * [stage] => (string) The session's stage - * [first_requested] => (int) Unix timestamp of the time the session was - * first generated - * [last_updated] => (int) Unix timestamp of the time the session was - * last updated - * ) - * - * - * @param string $clientId The client ID - * @param string $redirectUri The redirect URI - * @param string $authCode The authorisation code - * @return int|bool Returns the session ID if the auth code - * is valid otherwise returns false - */ - public function validateAuthCode( - $clientId, - $redirectUri, - $authCode - ); - - /** - * Return the session ID for a given session owner and client combination - * - * Database query: - * - * - * SELECT id FROM oauth_sessions WHERE client_id = $clientId - * AND owner_type = $type AND owner_id = $typeId - * - * - * @param string $type The session owner's type - * @param string $typeId The session owner's ID - * @param string $clientId The client ID - * @return string|null Return the session ID as an integer if - * found otherwise returns false - */ - public function hasSession( - $type, - $typeId, - $clientId - ); - - /** - * Return the access token for a given session - * - * Database query: - * - * - * SELECT access_token FROM oauth_sessions WHERE id = $sessionId - * - * - * @param int $sessionId The OAuth session ID - * @return string|null Returns the access token as a string if - * found otherwise returns null - */ - public function getAccessToken($sessionId); - - /** - * Removes an authorisation code associated with a session - * - * Database query: - * - * - * UPDATE oauth_sessions SET auth_code = NULL WHERE id = $sessionId - * - * - * @param int $sessionId The OAuth session ID - * @return void - */ - public function removeAuthCode($sessionId); - - /** - * Sets a sessions access token - * - * Database query: - * - * - * UPDATE oauth_sessions SET access_token = $accessToken WHERE id = - * $sessionId - * - * - * @param int $sessionId The OAuth session ID - * @param string $accessToken The access token - * @return void - */ - public function setAccessToken( - $sessionId, - $accessToken - ); - - /** - * Associates a session with a scope - * - * Database query: - * - * - * INSERT INTO oauth_session_scopes (session_id, scope) VALUE ($sessionId, - * $scope) - * - * - * @param int $sessionId The session ID - * @param string $scope The scope - * @return void - */ - public function addSessionScope( - $sessionId, - $scope - ); - - /** - * Return information about a scope - * - * Database query: - * - * - * SELECT * FROM scopes WHERE scope = $scope - * - * - * Response: - * - * - * Array - * ( - * [id] => (int) The scope's ID - * [scope] => (string) The scope itself - * [name] => (string) The scope's name - * [description] => (string) The scope's description - * ) - * - * - * @param string $scope The scope - * @return array - */ - public function getScope($scope); - - /** - * Associate a session's scopes with an access token - * - * Database query: - * - * - * UPDATE oauth_session_scopes SET access_token = $accessToken WHERE - * session_id = $sessionId - * - * - * @param int $sessionId The session ID - * @param string $accessToken The access token - * @return void - */ - public function updateSessionScopeAccessToken( - $sessionId, - $accessToken - ); - - /** - * Return the scopes associated with an access token - * - * Database query: - * - * - * SELECT scopes.scope, scopes.name, scopes.description FROM - * oauth_session_scopes JOIN scopes ON oauth_session_scopes.scope = - * scopes.scope WHERE access_token = $accessToken - * - * - * Response: - * - * - * Array - * ( - * [0] => Array - * ( - * [scope] => (string) The scope - * [name] => (string) The scope's name - * [description] => (string) The scope's description - * ) - * ) - * - * - * @param string $accessToken The access token - * @return array - */ - public function accessTokenScopes($accessToken); -} diff --git a/src/OAuth2/Authentication/Server.php b/src/OAuth2/Authentication/Server.php deleted file mode 100644 index 755ca976..00000000 --- a/src/OAuth2/Authentication/Server.php +++ /dev/null @@ -1,791 +0,0 @@ - ',', - 'access_token_ttl' => 3600 - ); - - /** - * Supported response types - * @var array - */ - private $_responseTypes = array( - 'code' - ); - - /** - * Supported grant types - * @var array - */ - private $_grantTypes = array( - 'authorization_code' => false, - 'client_credentials' => false, - 'password' => false, - 'refresh_token' => false, - ); - - private $_grantTypeCallbacks = array( - 'password' => null - ); - - /** - * Exception error codes - * @var array - */ - public $exceptionCodes = array( - 0 => 'invalid_request', - 1 => 'unauthorized_client', - 2 => 'access_denied', - 3 => 'unsupported_response_type', - 4 => 'invalid_scope', - 5 => 'server_error', - 6 => 'temporarily_unavailable', - 7 => 'unsupported_grant_type', - 8 => 'invalid_client', - 9 => 'invalid_grant' - ); - - /** - * Error codes. - * - * To provide i8ln errors just overwrite the keys - * - * @var array - */ - public $errors = array( - 'invalid_request' => 'The request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed. Check the "%s" parameter.', - 'unauthorized_client' => 'The client is not authorized to request an access token using this method.', - 'access_denied' => 'The resource owner or authorization server denied the request.', - 'unsupported_response_type' => 'The authorization server does not support obtaining an access token using this method.', - 'invalid_scope' => 'The requested scope is invalid, unknown, or malformed. Check the "%s" scope.', - 'server_error' => 'The authorization server encountered an unexpected condition which prevented it from fulfilling the request.', - 'temporarily_unavailable' => 'The authorization server is currently unable to handle the request due to a temporary overloading or maintenance of the server.', - 'unsupported_grant_type' => 'The authorization grant type "%s" is not supported by the authorization server', - 'invalid_client' => 'Client authentication failed', - 'invalid_grant' => 'The provided authorization grant is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client. Check the "%s" parameter.', - 'invalid_credentials' => 'The user credentials were incorrect.', - 'invalid_refresh' => 'The refresh token is invalid.', - ); - - /** - * Constructor - * - * @access public - * @param array $options Optional list of options to overwrite the defaults - * @return void - */ - public function __construct($options = null) - { - if ($options !== null) { - $this->_config = array_merge($this->_config, $options); - } - } - - /** - * Register a database abstrator class - * - * @access public - * @param object $db A class that implements OAuth2ServerDatabase - * @return void - */ - public function registerDbAbstractor($db) - { - $this->_db = $db; - } - - /** - * Enable a grant type - * - * @access public - * @return void - */ - public function enableGrantType($type, $callback = null) - { - if (isset($this->_grantTypes[$type])) { - $this->_grantTypes[$type] = true; - } - - if (in_array($type, array_keys($this->_grantTypeCallbacks))) { - if (is_null($callback) || ! is_callable($callback)) { - throw new ServerException('No registered callback function for grant type `'.$type.'`'); - } - - $this->_grantTypeCallbacks[$type] = $callback; - } - } - - /** - * Check client authorise parameters - * - * @access public - * @param array $authParams Optional array of parsed $_GET keys - * @return array Authorise request parameters - */ - public function checkClientAuthoriseParams($authParams = null) - { - $params = array(); - - // Client ID - if ( ! isset($authParams['client_id']) && ! isset($_GET['client_id'])) { - throw new ClientException(sprintf($this->errors['invalid_request'], 'client_id'), 0); - } - - $params['client_id'] = (isset($authParams['client_id'])) ? - $authParams['client_id'] : - $_GET['client_id']; - - // Redirect URI - if ( ! isset($authParams['redirect_uri']) && ! isset($_GET['redirect_uri'])) { - throw new ClientException(sprintf($this->errors['invalid_request'], 'redirect_uri'), 0); - } - - $params['redirect_uri'] = (isset($authParams['redirect_uri'])) ? - $authParams['redirect_uri'] : - $_GET['redirect_uri']; - - // Validate client ID and redirect URI - $clientDetails = $this->_dbCall( - 'validateClient', - $params['client_id'], - null, - $params['redirect_uri'] - ); - - if ($clientDetails === false) { - throw new ClientException($this->errors['invalid_client'], 8); - } - - $params['client_details'] = $clientDetails; - - // Response type - if ( ! isset($authParams['response_type']) && ! isset($_GET['response_type'])) { - throw new ClientException(sprintf($this->errors['invalid_request'], 'response_type'), 0); - } - - $params['response_type'] = (isset($authParams['response_type'])) ? - $authParams['response_type'] : - $_GET['response_type']; - - // Ensure response type is one that is recognised - if ( ! in_array($params['response_type'], $this->_responseTypes)) { - throw new ClientException($this->errors['unsupported_response_type'], 3); - } - - // Get and validate scopes - if (isset($authParams['scope']) || isset($_GET['scope'])) { - - $scopes = (isset($_GET['scope'])) ? - $_GET['scope'] : - $authParams['scope']; - - $scopes = explode($this->_config['scope_delimeter'], $scopes); - - // Remove any junk scopes - for ($i = 0; $i < count($scopes); $i++) { - - $scopes[$i] = trim($scopes[$i]); - - if ($scopes[$i] === '') { - unset($scopes[$i]); - } - } - - if (count($scopes) === 0) { - throw new ClientException(sprintf($this->errors['invalid_request'], 'scope'), 0); - } - - $params['scopes'] = array(); - - foreach ($scopes as $scope) { - - $scopeDetails = $this->_dbCall( - 'getScope', - $scope - ); - - if ($scopeDetails === false) { - throw new ClientException(sprintf($this->errors['invalid_scope'], $scope), 4); - } - - $params['scopes'][] = $scopeDetails; - - } - } - - return $params; - } - - /** - * Parse a new authorise request - * - * @param string $type The session owner's type - * @param string $typeId The session owner's ID - * @param array $authoriseParams The authorise request $_GET parameters - * @return string An authorisation code - */ - public function newAuthoriseRequest($type, $typeId, $authoriseParams) - { - // Remove any old sessions the user might have - $this->_dbCall( - 'deleteSession', - $authoriseParams['client_id'], - $type, - $typeId - ); - - // Create the new auth code - $authCode = $this->_newAuthCode( - $authoriseParams['client_id'], - 'user', - $typeId, - $authoriseParams['redirect_uri'], - $authoriseParams['scopes'] - ); - - return $authCode; - } - - /** - * Generate a unique code - * - * Generate a unique code for an authorisation code, or token - * - * @return string A unique code - */ - private function _generateCode() - { - return sha1(uniqid(microtime())); - } - - /** - * Create a new authorisation code - * - * @param string $clientId The client ID - * @param string $type The type of the owner of the session - * @param string $typeId The session owner's ID - * @param string $redirectUri The redirect URI - * @param array $scopes The requested scopes - * @param string $accessToken The access token (default = null) - * @return string An authorisation code - */ - private function _newAuthCode($clientId, $type, $typeId, $redirectUri, $scopes = array()) - { - $authCode = $this->_generateCode(); - - // Delete any existing sessions just to be sure - $this->_dbCall('deleteSession', $clientId, $type, $typeId); - - // Create a new session - $sessionId = $this->_dbCall( - 'newSession', - $clientId, - $redirectUri, - $type, - $typeId, - $authCode, - null, - null, - 'requested' - ); - - // Add the scopes - foreach ($scopes as $key => $scope) { - - $this->_dbCall( - 'addSessionScope', - $sessionId, - $scope['scope'] - ); - - } - - return $authCode; - } - - /** - * Issue an access token - * - * @access public - * - * @param array $authParams Optional array of parsed $_POST keys - * - * @return array Authorise request parameters - */ - public function issueAccessToken($authParams = null) - { - if ( ! isset($authParams['grant_type']) && ! isset($_POST['grant_type'])) { - throw new ClientException(sprintf($this->errors['invalid_request'], 'grant_type'), 0); - } - - $params['grant_type'] = (isset($authParams['grant_type'])) ? - $authParams['grant_type'] : - $_POST['grant_type']; - - // Ensure grant type is one that is recognised and is enabled - if ( ! in_array($params['grant_type'], array_keys($this->_grantTypes)) || $this->_grantTypes[$params['grant_type']] !== true) { - throw new ClientException(sprintf($this->errors['unsupported_grant_type'], $params['grant_type']), 7); - } - - switch ($params['grant_type']) - { - case 'authorization_code': // Authorization code grant - return $this->_completeAuthCodeGrant($authParams, $params); - break; - - case 'client_credentials': // Client credentials grant - return $this->_completeClientCredentialsGrant($authParams, $params); - break; - - case 'password': // Resource owner password credentials grant - return $this->_completeUserCredentialsGrant($authParams, $params); - break; - - case 'refresh_token': // Refresh token grant - return $this->_completeRefreshTokenGrant($authParams, $params); - break; - - // @codeCoverageIgnoreStart - default: // Unsupported - throw new ServerException($this->errors['server_error'] . 'Tried to process an unsuppported grant type.', 5); - break; - } - // @codeCoverageIgnoreEnd - } - - /** - * Complete the authorisation code grant - * - * @access private - * - * @param array $authParams Array of parsed $_POST keys - * @param array $params Generated parameters from issueAccessToken() - * - * @return array Authorise request parameters - */ - private function _completeAuthCodeGrant($authParams = array(), $params = array()) - { - // Client ID - if ( ! isset($authParams['client_id']) && ! isset($_POST['client_id'])) { - throw new ClientException(sprintf($this->errors['invalid_request'], 'client_id'), 0); - } - - $params['client_id'] = (isset($authParams['client_id'])) ? - $authParams['client_id'] : - $_POST['client_id']; - - // Client secret - if ( ! isset($authParams['client_secret']) && ! isset($_POST['client_secret'])) { - throw new ClientException(sprintf($this->errors['invalid_request'], 'client_secret'), 0); - } - - $params['client_secret'] = (isset($authParams['client_secret'])) ? - $authParams['client_secret'] : - $_POST['client_secret']; - - // Redirect URI - if ( ! isset($authParams['redirect_uri']) && ! isset($_POST['redirect_uri'])) { - throw new ClientException(sprintf($this->errors['invalid_request'], 'redirect_uri'), 0); - } - - $params['redirect_uri'] = (isset($authParams['redirect_uri'])) ? - $authParams['redirect_uri'] : - $_POST['redirect_uri']; - - // Validate client ID and redirect URI - $clientDetails = $this->_dbCall( - 'validateClient', - $params['client_id'], - $params['client_secret'], - $params['redirect_uri'] - ); - - if ($clientDetails === false) { - throw new ClientException($this->errors['invalid_client'], 8); - } - - // The authorization code - if ( ! isset($authParams['code']) && ! isset($_POST['code'])) { - throw new ClientException(sprintf($this->errors['invalid_request'], 'code'), 0); - } - - $params['code'] = (isset($authParams['code'])) ? - $authParams['code'] : - $_POST['code']; - - // Verify the authorization code matches the client_id and the request_uri - $session = $this->_dbCall( - 'validateAuthCode', - $params['client_id'], - $params['redirect_uri'], - $params['code'] - ); - - if ( ! $session) { - throw new ClientException(sprintf($this->errors['invalid_grant'], 'code'), 9); - } - - // A session ID was returned so update it with an access token, - // remove the authorisation code, change the stage to 'granted' - - $accessToken = $this->_generateCode(); - $refreshToken = ($this->_grantTypes['refresh_token']) ? - $this->_generateCode() : - null; - - $accessTokenExpires = time() + $this->_config['access_token_ttl']; - $accessTokenExpiresIn = $this->_config['access_token_ttl']; - - $this->_dbCall( - 'updateSession', - $session['id'], - null, - $accessToken, - $refreshToken, - $accessTokenExpires, - 'granted' - ); - - // Update the session's scopes to reference the access token - $this->_dbCall( - 'updateSessionScopeAccessToken', - $session['id'], - $accessToken, - $refreshToken - ); - - $response = array( - 'access_token' => $accessToken, - 'token_type' => 'bearer', - 'expires' => $accessTokenExpires, - 'expires_in' => $accessTokenExpiresIn - ); - - if ($this->_grantTypes['refresh_token']) { - $response['refresh_token'] = $refreshToken; - } - - return $response; - } - - /** - * Complete the resource owner password credentials grant - * - * @access private - * @param array $authParams Array of parsed $_POST keys - * @param array $params Generated parameters from issueAccessToken() - * @return array Authorise request parameters - */ - private function _completeClientCredentialsGrant($authParams = array(), $params = array()) - { - // Client ID - if ( ! isset($authParams['client_id']) && ! isset($_POST['client_id'])) { - // @codeCoverageIgnoreStart - throw new ClientException(sprintf($this->errors['invalid_request'], 'client_id'), 0); - // @codeCoverageIgnoreEnd - } - - $params['client_id'] = (isset($authParams['client_id'])) ? - $authParams['client_id'] : - $_POST['client_id']; - - // Client secret - if ( ! isset($authParams['client_secret']) && ! isset($_POST['client_secret'])) { - // @codeCoverageIgnoreStart - throw new ClientException(sprintf($this->errors['invalid_request'], 'client_secret'), 0); - // @codeCoverageIgnoreEnd - } - - $params['client_secret'] = (isset($authParams['client_secret'])) ? - $authParams['client_secret'] : - $_POST['client_secret']; - - // Validate client ID and client secret - $clientDetails = $this->_dbCall( - 'validateClient', - $params['client_id'], - $params['client_secret'], - null - ); - - if ($clientDetails === false) { - // @codeCoverageIgnoreStart - throw new ClientException($this->errors['invalid_client'], 8); - // @codeCoverageIgnoreEnd - } - - // Generate an access token - $accessToken = $this->_generateCode(); - $refreshToken = ($this->_grantTypes['refresh_token']) ? - $this->_generateCode() : - null; - - $accessTokenExpires = time() + $this->_config['access_token_ttl']; - $accessTokenExpiresIn = $this->_config['access_token_ttl']; - - // Delete any existing sessions just to be sure - $this->_dbCall('deleteSession', $params['client_id'], 'client', $params['client_id']); - - // Create a new session - $this->_dbCall('newSession', $params['client_id'], null, 'client', $params['client_id'], null, $accessToken, $refreshToken, $accessTokenExpires, 'granted'); - - $response = array( - 'access_token' => $accessToken, - 'token_type' => 'bearer', - 'expires' => $accessTokenExpires, - 'expires_in' => $accessTokenExpiresIn - ); - - if ($this->_grantTypes['refresh_token']) { - $response['refresh_token'] = $refreshToken; - } - - return $response; - } - - /** - * Complete the resource owner password credentials grant - * - * @access private - * @param array $authParams Array of parsed $_POST keys - * @param array $params Generated parameters from issueAccessToken() - * @return array Authorise request parameters - */ - private function _completeUserCredentialsGrant($authParams = array(), $params = array()) - { - // Client ID - if ( ! isset($authParams['client_id']) && ! isset($_POST['client_id'])) { - // @codeCoverageIgnoreStart - throw new ClientException(sprintf($this->errors['invalid_request'], 'client_id'), 0); - // @codeCoverageIgnoreEnd - } - - $params['client_id'] = (isset($authParams['client_id'])) ? - $authParams['client_id'] : - $_POST['client_id']; - - // Client secret - if ( ! isset($authParams['client_secret']) && ! isset($_POST['client_secret'])) { - // @codeCoverageIgnoreStart - throw new ClientException(sprintf($this->errors['invalid_request'], 'client_secret'), 0); - // @codeCoverageIgnoreEnd - } - - $params['client_secret'] = (isset($authParams['client_secret'])) ? - $authParams['client_secret'] : - $_POST['client_secret']; - - // Validate client ID and client secret - $clientDetails = $this->_dbCall( - 'validateClient', - $params['client_id'], - $params['client_secret'], - null - ); - - if ($clientDetails === false) { - // @codeCoverageIgnoreStart - throw new ClientException($this->errors['invalid_client'], 8); - // @codeCoverageIgnoreEnd - } - - // User's username - if ( ! isset($authParams['username']) && ! isset($_POST['username'])) { - throw new ClientException(sprintf($this->errors['invalid_request'], 'username'), 0); - } - - $params['username'] = (isset($authParams['username'])) ? - $authParams['username'] : - $_POST['username']; - - // User's password - if ( ! isset($authParams['password']) && ! isset($_POST['password'])) { - throw new ClientException(sprintf($this->errors['invalid_request'], 'password'), 0); - } - - $params['password'] = (isset($authParams['password'])) ? - $authParams['password'] : - $_POST['password']; - - // Check if user's username and password are correct - $userId = call_user_func($this->_grantTypeCallbacks['password'], $params['username'], $params['password']); - - if ($userId === false) { - throw new \OAuth2\Authentication\ClientException($this->errors['invalid_credentials'], 0); - } - - // Generate an access token - $accessToken = $this->_generateCode(); - $refreshToken = ($this->_grantTypes['refresh_token']) ? - $this->_generateCode() : - null; - - $accessTokenExpires = time() + $this->_config['access_token_ttl']; - $accessTokenExpiresIn = $this->_config['access_token_ttl']; - - // Delete any existing sessions just to be sure - $this->_dbCall('deleteSession', $params['client_id'], 'user', $userId); - - // Create a new session - $this->_dbCall('newSession', $params['client_id'], null, 'user', $userId, null, $accessToken, $refreshToken, $accessTokenExpires, 'granted'); - - $response = array( - 'access_token' => $accessToken, - 'token_type' => 'bearer', - 'expires' => $accessTokenExpires, - 'expires_in' => $accessTokenExpiresIn - ); - - if ($this->_grantTypes['refresh_token']) { - $response['refresh_token'] = $refreshToken; - } - - return $response; - } - - /** - * Complete the refresh token grant - * - * @access private - * @param array $authParams Array of parsed $_POST keys - * @param array $params Generated parameters from issueAccessToken() - * @return array Authorise request parameters - */ - private function _completeRefreshTokenGrant($authParams = array(), $params = array()) - { - // Client ID - if ( ! isset($authParams['client_id']) && ! isset($_POST['client_id'])) { - // @codeCoverageIgnoreStart - throw new ClientException(sprintf($this->errors['invalid_request'], 'client_id'), 0); - // @codeCoverageIgnoreEnd - } - - $params['client_id'] = (isset($authParams['client_id'])) ? - $authParams['client_id'] : - $_POST['client_id']; - - // Client secret - if ( ! isset($authParams['client_secret']) && ! isset($_POST['client_secret'])) { - // @codeCoverageIgnoreStart - throw new ClientException(sprintf($this->errors['invalid_request'], 'client_secret'), 0); - // @codeCoverageIgnoreEnd - } - - $params['client_secret'] = (isset($authParams['client_secret'])) ? - $authParams['client_secret'] : - $_POST['client_secret']; - - // Validate client ID and client secret - $clientDetails = $this->_dbCall( - 'validateClient', - $params['client_id'], - $params['client_secret'], - null - ); - - if ($clientDetails === false) { - // @codeCoverageIgnoreStart - throw new ClientException($this->errors['invalid_client'], 8); - // @codeCoverageIgnoreEnd - } - - // Refresh token - if ( ! isset($authParams['refresh_token']) && ! isset($_POST['refresh_token'])) { - throw new ClientException(sprintf($this->errors['invalid_request'], 'refresh_token'), 0); - } - - $params['refresh_token'] = (isset($authParams['refresh_token'])) ? - $authParams['refresh_token'] : - $_POST['refresh_token']; - - // Validate refresh token - $sessionId = $this->_dbCall('validateRefreshToken', $params['refresh_token'], $params['client_id']); - - if ($sessionId === false) { - throw new \OAuth2\Authentication\ClientException($this->errors['invalid_refresh'], 0); - } - - // Generate new tokens - $accessToken = $this->_generateCode(); - $refreshToken = $this->_generateCode(); - - $accessTokenExpires = time() + $this->_config['access_token_ttl']; - $accessTokenExpiresIn = $this->_config['access_token_ttl']; - - // Update the tokens - $this->_dbCall('updateRefreshToken', $sessionId, $accessToken, $refreshToken, $accessTokenExpires); - - return array( - 'access_token' => $accessToken, - 'refresh_token' => $refreshToken, - 'token_type' => 'bearer', - 'expires' => $accessTokenExpires, - 'expires_in' => $accessTokenExpiresIn - ); - } - - /** - * Generates the redirect uri with appended params - * - * @param string $redirectUri The redirect URI - * @param array $params The parameters to be appended to the URL - * @param string $query_delimeter The query string delimiter (default: ?) - * - * @return string The updated redirect URI - */ - public function redirectUri($redirectUri, $params = array(), $queryDelimeter = '?') - { - return (strstr($redirectUri, $queryDelimeter)) ? $redirectUri . '&' . http_build_query($params) : $redirectUri . $queryDelimeter . http_build_query($params); - } - - /** - * 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('Registered database abstractor is not an instance of OAuth2\Authentication\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); - } -} From 1a1bfd9348bd9024f01059241d9b7091cc57f2b0 Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Mon, 4 Feb 2013 15:32:21 +0000 Subject: [PATCH 053/113] Fix $expiresIn call as static --- src/OAuth2/AuthServer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/OAuth2/AuthServer.php b/src/OAuth2/AuthServer.php index 92c4ac82..03b1ba87 100644 --- a/src/OAuth2/AuthServer.php +++ b/src/OAuth2/AuthServer.php @@ -114,7 +114,7 @@ class AuthServer public function setExpiresIn($expiresIn) { - $this->expiresIn = $expiresIn; + self::$expiresIn = $expiresIn; } /** From 4b8bc76622089df69647bf5e6a0443b4c3ba5d45 Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Mon, 4 Feb 2013 15:32:33 +0000 Subject: [PATCH 054/113] Removed properties from Interface --- src/OAuth2/Grant/GrantTypeInterface.php | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/src/OAuth2/Grant/GrantTypeInterface.php b/src/OAuth2/Grant/GrantTypeInterface.php index e1902400..f64b3e9f 100644 --- a/src/OAuth2/Grant/GrantTypeInterface.php +++ b/src/OAuth2/Grant/GrantTypeInterface.php @@ -12,21 +12,6 @@ use OAuth2\Storage\ScopeInterface; interface GrantTypeInterface { - /** - * The grant type identifier - * @var string - */ - protected $identifier = ''; - - /** - * The response type - * - * This is not used for most grant types - * - * @var null|string - */ - protected $responseType = null; - /** * Returns the grant identifier (used to validate grant_type in OAuth2\AuthServer\issueAccessToken()) * @return string From 0d173d4c351f87c3b46b7daa55a09ab740784aef Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Mon, 4 Feb 2013 17:10:30 +0000 Subject: [PATCH 055/113] Renamed methods to prevent ORM conflict --- src/OAuth2/Storage/ClientInterface.php | 2 +- src/OAuth2/Storage/ScopeInterface.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/OAuth2/Storage/ClientInterface.php b/src/OAuth2/Storage/ClientInterface.php index bb339ffc..2abee251 100644 --- a/src/OAuth2/Storage/ClientInterface.php +++ b/src/OAuth2/Storage/ClientInterface.php @@ -43,5 +43,5 @@ interface ClientInterface * @param string $redirectUri The client's redirect URI (default = "null") * @return bool|array Returns false if the validation fails, array on success */ - public function get($clientId = null, $clientSecret = null, $redirectUri = null); + public function getClient($clientId = null, $clientSecret = null, $redirectUri = null); } \ No newline at end of file diff --git a/src/OAuth2/Storage/ScopeInterface.php b/src/OAuth2/Storage/ScopeInterface.php index 895cc4e6..8777aee6 100644 --- a/src/OAuth2/Storage/ScopeInterface.php +++ b/src/OAuth2/Storage/ScopeInterface.php @@ -28,5 +28,5 @@ interface ScopeInterface * @param string $scope The scope * @return bool|array If the scope doesn't exist return false */ - public function get($scope); + public function getScope($scope); } From 768dfb369c4dc03279e65e32b85fb47f5c31e6ce Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Mon, 4 Feb 2013 18:30:56 +0000 Subject: [PATCH 056/113] Renamed getCurrentGrantType to getGrantType --- src/OAuth2/AuthServer.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/OAuth2/AuthServer.php b/src/OAuth2/AuthServer.php index 03b1ba87..1e0b8f24 100644 --- a/src/OAuth2/AuthServer.php +++ b/src/OAuth2/AuthServer.php @@ -280,10 +280,10 @@ class AuthServer } // Complete the flow - return $this->getCurrentGrantType($authParams['grant_type'])->completeFlow($inputParams, $authParams); + return $this->getGrantType($authParams['grant_type'])->completeFlow($inputParams, $authParams); } - protected function getCurrentGrantType($grantType) + protected function getGrantType($grantType) { return self::$grantTypes[$grantType]; } From 6ae4db460ed58137001efb0b78ef7b8567218101 Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Mon, 4 Feb 2013 18:31:13 +0000 Subject: [PATCH 057/113] $request parameter is static --- src/OAuth2/AuthServer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/OAuth2/AuthServer.php b/src/OAuth2/AuthServer.php index 1e0b8f24..3819b58b 100644 --- a/src/OAuth2/AuthServer.php +++ b/src/OAuth2/AuthServer.php @@ -124,7 +124,7 @@ class AuthServer */ public function setRequest(RequestInterface $request) { - $this->request = $request; + self::$request = $request; } /** From 04b8394009f66a938b714ca9916936e8a68eed27 Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Mon, 4 Feb 2013 18:44:19 +0000 Subject: [PATCH 058/113] Updated method calls to reflect naming changes --- src/OAuth2/AuthServer.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/OAuth2/AuthServer.php b/src/OAuth2/AuthServer.php index 3819b58b..391c2a7f 100644 --- a/src/OAuth2/AuthServer.php +++ b/src/OAuth2/AuthServer.php @@ -176,7 +176,7 @@ class AuthServer } // Validate client ID and redirect URI - $clientDetails = self::getStorage('client')->get($authParams['client_id'], null, $authParams['redirect_uri']); + $clientDetails = self::getStorage('client')->getClient($authParams['client_id'], null, $authParams['redirect_uri']); if ($clientDetails === false) { throw new Exception\ClientException(self::$exceptionMessages['invalid_client'], 8); @@ -217,7 +217,7 @@ class AuthServer $authParams['scopes'] = array(); foreach ($scopes as $scope) { - $scopeDetails = self::getStorage('scope')->get($scope); + $scopeDetails = self::getStorage('scope')->getScope($scope); if ($scopeDetails === false) { throw new Exception\ClientException(sprintf(self::$exceptionMessages['invalid_scope'], $scope), 4); From 9a265f7956d00e118888224fe6dfcf798d514c16 Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Mon, 4 Feb 2013 18:58:17 +0000 Subject: [PATCH 059/113] Fixed bad ternary statement. Added missing semicolon --- src/OAuth2/Util/RedirectUri.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/OAuth2/Util/RedirectUri.php b/src/OAuth2/Util/RedirectUri.php index 7e75ab44..580758e5 100644 --- a/src/OAuth2/Util/RedirectUri.php +++ b/src/OAuth2/Util/RedirectUri.php @@ -6,7 +6,7 @@ class RedirectUri { public static function make($uri, $params = array(), $queryDelimeter = '?') { - $uri .= (strstr($uri, $queryDelimeter) === false) ? $queryDelimeter ? '&'; - return $uri.http_build_query($params) + $uri .= (strstr($uri, $queryDelimeter) === false) ? $queryDelimeter : '&'; + return $uri.http_build_query($params); } } \ No newline at end of file From d5ae471d940db03a5d52480ca1248665a8e37b11 Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Mon, 4 Feb 2013 18:58:26 +0000 Subject: [PATCH 060/113] Throw root exception --- src/OAuth2/Util/SecureKey.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/OAuth2/Util/SecureKey.php b/src/OAuth2/Util/SecureKey.php index eaa741c7..53014278 100644 --- a/src/OAuth2/Util/SecureKey.php +++ b/src/OAuth2/Util/SecureKey.php @@ -13,7 +13,7 @@ class SecureKey // We want to stop execution if the key fails because, well, that is bad. if ($bytes === false || $strong === false) { - throw new Exception('Error Generating Key'); + throw new \Exception('Error Generating Key'); } return substr(str_replace(array('/', '+', '='), '', base64_encode($bytes)), 0, $len); From d80b2935fc953dd0f1cc6c333a37c9bed1451b09 Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Mon, 4 Feb 2013 19:45:03 +0000 Subject: [PATCH 061/113] Require mockery for unit tests --- composer.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/composer.json b/composer.json index e5951b33..83328f1c 100644 --- a/composer.json +++ b/composer.json @@ -8,7 +8,8 @@ "php": ">=5.3.0" }, "require-dev": { - "phpunit/phpunit": "*" + "phpunit/phpunit": "*", + "mockery/mockery": ">=0.7.2" }, "repositories": [ { From 8a6823b78dc286e0c256b06ff1b8ca9dc2c2457b Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Mon, 4 Feb 2013 19:45:19 +0000 Subject: [PATCH 062/113] Removed resource tests, added util tests --- build/phpunit.xml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/build/phpunit.xml b/build/phpunit.xml index 792b1799..48e085c6 100644 --- a/build/phpunit.xml +++ b/build/phpunit.xml @@ -2,10 +2,10 @@ - ../tests/authentication + ../tests/authentication - - ../tests/resource + + ../tests/util @@ -13,7 +13,9 @@ PEAR_INSTALL_DIR PHP_LIBDIR ../vendor/composer + ../vendor/mockery ../tests + ../testing From 6edd486b4c7160ad487b53716c9ebb1d04d87819 Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Mon, 4 Feb 2013 19:45:34 +0000 Subject: [PATCH 063/113] Added code coverage ignore blocks to getRequest method --- src/OAuth2/AuthServer.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/OAuth2/AuthServer.php b/src/OAuth2/AuthServer.php index 391c2a7f..19710b57 100644 --- a/src/OAuth2/AuthServer.php +++ b/src/OAuth2/AuthServer.php @@ -135,8 +135,11 @@ class AuthServer public static function getRequest() { if (self::$request === null) { + // @codeCoverageIgnoreStart self::$request = Request::buildFromGlobals(); + } + // @codeCoverageIgnoreEnd return self::$request; } From 22f793a16faaa50c28fdbf79a3a514fe26c2d19d Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Mon, 4 Feb 2013 19:45:47 +0000 Subject: [PATCH 064/113] Fixed getClient call --- src/OAuth2/Grant/AuthCode.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/OAuth2/Grant/AuthCode.php b/src/OAuth2/Grant/AuthCode.php index 960996c2..b055d896 100644 --- a/src/OAuth2/Grant/AuthCode.php +++ b/src/OAuth2/Grant/AuthCode.php @@ -55,7 +55,7 @@ class AuthCode implements GrantTypeInterface { } // Validate client ID and redirect URI - $clientDetails = AuthServer::getStorage('client')->get($authParams['client_id'], $authParams['client_secret'], $authParams['redirect_uri']); + $clientDetails = AuthServer::getStorage('client')->getClient($authParams['client_id'], $authParams['client_secret'], $authParams['redirect_uri']); if ($clientDetails === false) { throw new Exception\ClientException(AuthServer::getExceptionMessage('invalid_client'), 8); From c89a2346a84a7a1aabe9db7443cde04fc53e8a28 Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Mon, 4 Feb 2013 19:45:58 +0000 Subject: [PATCH 065/113] Removed unnecessary code --- src/OAuth2/Request.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/OAuth2/Request.php b/src/OAuth2/Request.php index 3b934a69..6c5c1742 100644 --- a/src/OAuth2/Request.php +++ b/src/OAuth2/Request.php @@ -67,8 +67,8 @@ class Request implements RequestInterface { $headers = array(); foreach ($this->server() as $name => $value) { - if (substr($name, 0, 5) == 'HTTP_') { - $name = str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5))))); + if (substr($name, 0, 5) === 'HTTP_') { + $name = str_replace(' ', '-', strtolower(str_replace('_', ' ', substr($name, 5)))); $headers[$name] = $value; } } From 4a50af333d4e1cb561ae9d0690e44480e7f4f493 Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Mon, 4 Feb 2013 19:46:06 +0000 Subject: [PATCH 066/113] Added code coverage blocks --- src/OAuth2/Util/SecureKey.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/OAuth2/Util/SecureKey.php b/src/OAuth2/Util/SecureKey.php index 53014278..35a55298 100644 --- a/src/OAuth2/Util/SecureKey.php +++ b/src/OAuth2/Util/SecureKey.php @@ -13,7 +13,9 @@ class SecureKey // We want to stop execution if the key fails because, well, that is bad. if ($bytes === false || $strong === false) { + // @codeCoverageIgnoreStart throw new \Exception('Error Generating Key'); + // @codeCoverageIgnoreEnd } return substr(str_replace(array('/', '+', '='), '', base64_encode($bytes)), 0, $len); From 2f010584ef0dc3d694590c2a4938af62f3e25a87 Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Mon, 4 Feb 2013 19:46:21 +0000 Subject: [PATCH 067/113] Removed old auth server unit tests --- tests/authentication/database_mock.php | 168 ----- tests/authentication/server_test.php | 912 ------------------------- 2 files changed, 1080 deletions(-) delete mode 100644 tests/authentication/database_mock.php delete mode 100644 tests/authentication/server_test.php diff --git a/tests/authentication/database_mock.php b/tests/authentication/database_mock.php deleted file mode 100644 index 315ca10e..00000000 --- a/tests/authentication/database_mock.php +++ /dev/null @@ -1,168 +0,0 @@ - array( - 'client_id' => 'test', - 'client_secret' => 'test', - 'redirect_uri' => 'http://example.com/test', - 'name' => 'Test Client' - )); - - private $scopes = array('test' => array( - 'id' => 1, - 'scope' => 'test', - 'name' => 'test', - 'description' => 'test' - )); - - public function validateClient($clientId, $clientSecret = null, $redirectUri = null) - { - if ($clientId !== $this->clients[0]['client_id']) { - return false; - } - - if ($clientSecret !== null && $clientSecret !== $this->clients[0]['client_secret']) { - return false; - } - - if ($redirectUri !== null && $redirectUri !== $this->clients[0]['redirect_uri']) { - return false; - } - - return $this->clients[0]; - } - - public function newSession($clientId, $redirectUri, $type = 'user', $typeId = null, $authCode = null, $accessToken = null, $refreshToken = null, $accessTokenExpire = null, $stage = 'requested') - { - $id = count($this->sessions); - - $this->sessions[$id] = array( - 'id' => $id, - 'client_id' => $clientId, - 'redirect_uri' => $redirectUri, - 'owner_type' => $type, - 'owner_id' => $typeId, - 'auth_code' => $authCode, - 'access_token' => $accessToken, - 'refresh_token' => $refreshToken, - 'access_token_expire' => $accessTokenExpire, - 'stage' => $stage - ); - - $this->sessions_client_type_id[$clientId . ':' . $type . ':' . $typeId] = $id; - $this->sessions_code[$clientId . ':' . $redirectUri . ':' . $authCode] = $id; - - return $id; - } - - public function updateSession($sessionId, $authCode = null, $accessToken = null, $refreshToken = null, $accessTokenExpire = null, $stage = 'requested') - { - $this->sessions[$sessionId]['auth_code'] = $authCode; - $this->sessions[$sessionId]['access_token'] = $accessToken; - $this->sessions[$sessionId]['refresh_token'] = $refreshToken; - $this->sessions[$sessionId]['access_token_expire'] = $accessTokenExpire; - $this->sessions[$sessionId]['stage'] = $stage; - - return true; - } - - public function deleteSession($clientId, $type, $typeId) - { - $key = $clientId . ':' . $type . ':' . $typeId; - if (isset($this->sessions_client_type_id[$key])) { - unset($this->sessions[$this->sessions_client_type_id[$key]]); - } - return true; - } - - public function refreshToken($currentRefreshToken, $newAccessToken, $newRefreshToken, $accessTokenExpires) - { - die('not implemented refreshToken'); - } - - public function validateAuthCode($clientId, $redirectUri, $authCode) - { - $key = $clientId . ':' . $redirectUri . ':' . $authCode; - - if (isset($this->sessions_code[$key])) { - return $this->sessions[$this->sessions_code[$key]]; - } - - return false; - } - - public function hasSession($type, $typeId, $clientId) - { - die('not implemented hasSession'); - } - - public function getAccessToken($sessionId) - { - die('not implemented getAccessToken'); - } - - public function removeAuthCode($sessionId) - { - die('not implemented removeAuthCode'); - } - - public function setAccessToken($sessionId, $accessToken) - { - die('not implemented setAccessToken'); - } - - public function addSessionScope($sessionId, $scope) - { - if ( ! isset($this->session_scopes[$sessionId])) { - $this->session_scopes[$sessionId] = array(); - } - - $this->session_scopes[$sessionId][] = $scope; - - return true; - } - - public function getScope($scope) - { - if ( ! isset($this->scopes[$scope])) { - return false; - } - - return $this->scopes[$scope]; - } - - public function updateSessionScopeAccessToken($sessionId, $accessToken) - { - return true; - } - - public function accessTokenScopes($accessToken) - { - die('not implemented accessTokenScopes'); - } - - public function validateRefreshToken($refreshToken, $clientId) - { - if ($refreshToken !== $this->sessions[0]['refresh_token']) - { - return false; - } - - return true; - } - - public function updateRefreshToken($sessionId, $newAccessToken, $newRefreshToken, $accessTokenExpires) - { - $this->sessions[$sessionId]['access_token'] = $newAccessToken; - $this->sessions[$sessionId]['refresh_token'] = $newRefreshToken; - $this->sessions[$sessionId]['access_token_expire'] = $accessTokenExpires; - } -} \ No newline at end of file diff --git a/tests/authentication/server_test.php b/tests/authentication/server_test.php deleted file mode 100644 index 77029403..00000000 --- a/tests/authentication/server_test.php +++ /dev/null @@ -1,912 +0,0 @@ -oauth = new OAuth2\Authentication\Server(); - - require_once 'database_mock.php'; - $this->oauthdb = new OAuthdb(); - $this->assertInstanceOf('OAuth2\Authentication\Database', $this->oauthdb); - $this->oauth->registerDbAbstractor($this->oauthdb); - } - - public function test_setupWithOptions() - { - $o = new OAuth2\Authentication\Server(array( - 'access_token_ttl' => 86400 - )); - - $reflector = new ReflectionClass($o); - $param = $reflector->getProperty('_config'); - $param->setAccessible(true); - $array = $param->getValue($o); - - $this->assertEquals(86400, $array['access_token_ttl']); - } - - public function test_generateCode() - { - $reflector = new ReflectionClass($this->oauth); - $method = $reflector->getMethod('_generateCode'); - $method->setAccessible(true); - - $result = $method->invoke($this->oauth); - $result2 = $method->invoke($this->oauth); - - $this->assertEquals(40, strlen($result)); - $this->assertNotEquals($result, $result2); - } - - public function test_redirectUri() - { - $result1 = $this->oauth->redirectUri('http://example.com/foo'); - $result2 = $this->oauth->redirectUri('http://example.com/foo', array('foo' => 'bar')); - $result3 = $this->oauth->redirectUri('http://example.com/foo', array('foo' => 'bar'), '#'); - - $this->assertEquals('http://example.com/foo?', $result1); - $this->assertEquals('http://example.com/foo?foo=bar', $result2); - $this->assertEquals('http://example.com/foo#foo=bar', $result3); - } - - public function test_checkClientAuthoriseParams_GET() - { - $_GET['client_id'] = 'test'; - $_GET['redirect_uri'] = 'http://example.com/test'; - $_GET['response_type'] = 'code'; - $_GET['scope'] = 'test'; - - $expect = array( - 'client_id' => 'test', - 'redirect_uri' => 'http://example.com/test', - 'client_details' => array( - 'client_id' => 'test', - 'client_secret' => 'test', - 'redirect_uri' => 'http://example.com/test', - 'name' => 'Test Client' - ), - 'response_type' => 'code', - 'scopes' => array( - 0 => array( - 'id' => 1, - 'scope' => 'test', - 'name' => 'test', - 'description' => 'test' - ) - ) - ); - - $result = $this->oauth->checkClientAuthoriseParams(); - - $this->assertEquals($expect, $result); - } - - public function test_checkClientAuthoriseParams_PassedParams() - { - unset($_GET['client_id']); - unset($_GET['redirect_uri']); - unset($_GET['response_type']); - unset($_GET['scope']); - - $params = array( - 'client_id' => 'test', - 'redirect_uri' => 'http://example.com/test', - 'response_type' => 'code', - 'scope' => 'test' - ); - - $this->assertEquals(array( - 'client_id' => 'test', - 'redirect_uri' => 'http://example.com/test', - 'client_details' => array( - 'client_id' => 'test', - 'client_secret' => 'test', - 'redirect_uri' => 'http://example.com/test', - 'name' => 'Test Client' - ), - 'response_type' => 'code', - 'scopes' => array(0 => array( - 'id' => 1, - 'scope' => 'test', - 'name' => 'test', - 'description' => 'test' - )) - ), $this->oauth->checkClientAuthoriseParams($params)); - } - - /** - * @expectedException OAuth2\Authentication\ClientException - * @expectedExceptionCode 0 - */ - public function test_checkClientAuthoriseParams_missingClientId() - { - $this->oauth->checkClientAuthoriseParams(); - } - - /** - * @expectedException OAuth2\Authentication\ClientException - * @expectedExceptionCode 0 - */ - public function test_checkClientAuthoriseParams_missingRedirectUri() - { - $_GET['client_id'] = 'test'; - - $this->oauth->checkClientAuthoriseParams(); - } - - /** - * @expectedException OAuth2\Authentication\ClientException - * @expectedExceptionCode 0 - */ - public function test_checkClientAuthoriseParams_missingResponseType() - { - $_GET['client_id'] = 'test'; - $_GET['redirect_uri'] = 'http://example.com/test'; - - $this->oauth->checkClientAuthoriseParams(); - } - - /** - * @expectedException OAuth2\Authentication\ClientException - * @expectedExceptionCode 0 - */ - public function test_checkClientAuthoriseParams_missingScopes() - { - $_GET['client_id'] = 'test'; - $_GET['redirect_uri'] = 'http://example.com/test'; - $_GET['response_type'] = 'code'; - $_GET['scope'] = ' '; - - $this->oauth->checkClientAuthoriseParams(); - } - - /** - * @expectedException OAuth2\Authentication\ClientException - * @expectedExceptionCode 4 - */ - public function test_checkClientAuthoriseParams_invalidScopes() - { - $_GET['client_id'] = 'test'; - $_GET['redirect_uri'] = 'http://example.com/test'; - $_GET['response_type'] = 'code'; - $_GET['scope'] = 'blah'; - - $this->oauth->checkClientAuthoriseParams(); - } - - /** - * @expectedException OAuth2\Authentication\ClientException - * @expectedExceptionCode 8 - */ - public function test_checkClientAuthoriseParams_invalidClient() - { - $_GET['client_id'] = 'test'; - $_GET['redirect_uri'] = 'http://example.com/test2'; - $_GET['response_type'] = 'code'; - $_GET['scope'] = 'blah'; - - $this->oauth->checkClientAuthoriseParams(); - } - - /** - * @expectedException OAuth2\Authentication\ClientException - * @expectedExceptionCode 3 - */ - public function test_checkClientAuthoriseParams_invalidResponseType() - { - $_GET['client_id'] = 'test'; - $_GET['redirect_uri'] = 'http://example.com/test'; - $_GET['response_type'] = 'blah'; - $_GET['scope'] = 'blah'; - - $this->oauth->checkClientAuthoriseParams(); - } - - public function test_newAuthoriseRequest() - { - $result = $this->oauth->newAuthoriseRequest('user', '123', array( - 'client_id' => 'test', - 'redirect_uri' => 'http://example.com/test', - 'scopes' => array(array( - 'id' => 1, - 'scope' => 'test', - 'name' => 'test', - 'description' => 'test' - )) - )); - - $this->assertEquals(40, strlen($result)); - } - - public function test_newAuthoriseRequest_isUnique() - { - $result1 = $this->oauth->newAuthoriseRequest('user', '123', array( - 'client_id' => 'test', - 'redirect_uri' => 'http://example.com/test', - 'scopes' => array(array( - 'id' => 1, - 'scope' => 'test', - 'name' => 'test', - 'description' => 'test' - )) - )); - - $result2 = $this->oauth->newAuthoriseRequest('user', '123', array( - 'client_id' => 'test', - 'redirect_uri' => 'http://example.com/test', - 'scopes' => array(array( - 'id' => 1, - 'scope' => 'test', - 'name' => 'test', - 'description' => 'test' - )) - )); - - $this->assertNotEquals($result1, $result2); - } - - /** - * @expectedException OAuth2\Authentication\ClientException - * @expectedExceptionCode 7 - */ - public function test_issueAccessTokenNoRegisteredGrant() - { - $auth_code = $this->oauth->newAuthoriseRequest('user', '123', array( - 'client_id' => 'test', - 'redirect_uri' => 'http://example.com/test', - 'scopes' => array(array( - 'id' => 1, - 'scope' => 'test', - 'name' => 'test', - 'description' => 'test' - )) - )); - - $_POST['client_id'] = 'test'; - $_POST['client_secret'] = 'test'; - $_POST['redirect_uri'] = 'http://example.com/test'; - $_POST['grant_type'] = 'authorization_code'; - $_POST['code'] = $auth_code; - - $result = $this->oauth->issueAccessToken(); - } - - public function test_issueAccessToken_POST_authorization_code() - { - $auth_code = $this->oauth->newAuthoriseRequest('user', '123', array( - 'client_id' => 'test', - 'redirect_uri' => 'http://example.com/test', - 'scopes' => array(array( - 'id' => 1, - 'scope' => 'test', - 'name' => 'test', - 'description' => 'test' - )) - )); - - $_POST['client_id'] = 'test'; - $_POST['client_secret'] = 'test'; - $_POST['redirect_uri'] = 'http://example.com/test'; - $_POST['grant_type'] = 'authorization_code'; - $_POST['code'] = $auth_code; - - $this->oauth->enableGrantType('authorization_code'); - $result = $this->oauth->issueAccessToken(); - - $this->assertCount(4, $result); - $this->assertArrayHasKey('access_token', $result); - $this->assertArrayHasKey('token_type', $result); - $this->assertArrayHasKey('expires_in', $result); - $this->assertArrayHasKey('expires', $result); - } - - public function test_issueAccessToken_PassedParams_authorization_code() - { - $auth_code = $this->oauth->newAuthoriseRequest('user', '123', array( - 'client_id' => 'test', - 'redirect_uri' => 'http://example.com/test', - 'scopes' => array(array( - 'id' => 1, - 'scope' => 'test', - 'name' => 'test', - 'description' => 'test' - )) - )); - - $params['client_id'] = 'test'; - $params['client_secret'] = 'test'; - $params['redirect_uri'] = 'http://example.com/test'; - $params['grant_type'] = 'authorization_code'; - $params['code'] = $auth_code; - - $this->oauth->enableGrantType('authorization_code'); - $result = $this->oauth->issueAccessToken($params); - - $this->assertCount(4, $result); - $this->assertArrayHasKey('access_token', $result); - $this->assertArrayHasKey('token_type', $result); - $this->assertArrayHasKey('expires_in', $result); - $this->assertArrayHasKey('expires', $result); - } - - public function test_issueAccessToken_refresh_token() - { - $this->oauth->enableGrantType('authorization_code'); - $this->oauth->enableGrantType('refresh_token'); - - $auth_code = $this->oauth->newAuthoriseRequest('user', '123', array( - 'client_id' => 'test', - 'redirect_uri' => 'http://example.com/test', - 'scopes' => array(array( - 'id' => 1, - 'scope' => 'test', - 'name' => 'test', - 'description' => 'test' - )) - )); - - $params['client_id'] = 'test'; - $params['client_secret'] = 'test'; - $params['redirect_uri'] = 'http://example.com/test'; - $params['grant_type'] = 'authorization_code'; - $params['code'] = $auth_code; - - $result = $this->oauth->issueAccessToken($params); - - $this->assertCount(5, $result); - $this->assertArrayHasKey('access_token', $result); - $this->assertArrayHasKey('token_type', $result); - $this->assertArrayHasKey('expires_in', $result); - $this->assertArrayHasKey('expires', $result); - $this->assertArrayHasKey('refresh_token', $result); - - // Wait for a few seconds for the access token to age - sleep(1); - - // Refresh the token - $params2['client_id'] = 'test'; - $params2['client_secret'] = 'test'; - $params2['redirect_uri'] = 'http://example.com/test'; - $params2['grant_type'] = 'refresh_token'; - $params2['refresh_token'] = $result['refresh_token']; - - $result2 = $this->oauth->issueAccessToken($params2); - - $this->assertCount(5, $result2); - $this->assertArrayHasKey('access_token', $result2); - $this->assertArrayHasKey('token_type', $result2); - $this->assertArrayHasKey('expires_in', $result2); - $this->assertArrayHasKey('expires', $result2); - $this->assertArrayHasKey('refresh_token', $result2); - - $this->assertNotEquals($result['access_token'], $result2['access_token']); - $this->assertNotEquals($result['refresh_token'], $result2['refresh_token']); - $this->assertNotEquals($result['expires'], $result2['expires']); - $this->assertEquals($result['expires_in'], $result2['expires_in']); - $this->assertEquals($result['token_type'], $result2['token_type']); - } - - public function test_issueAccessToken_client_credentials() - { - $this->oauth->enableGrantType('client_credentials'); - - $auth_code = $this->oauth->newAuthoriseRequest('user', '123', array( - 'client_id' => 'test', - 'redirect_uri' => 'http://example.com/test', - 'scopes' => array(array( - 'id' => 1, - 'scope' => 'test', - 'name' => 'test', - 'description' => 'test' - )) - )); - - $params['client_id'] = 'test'; - $params['client_secret'] = 'test'; - $params['redirect_uri'] = 'http://example.com/test'; - $params['grant_type'] = 'client_credentials'; - $params['code'] = $auth_code; - - $result = $this->oauth->issueAccessToken($params); - - $this->assertCount(4, $result); - $this->assertArrayHasKey('access_token', $result); - $this->assertArrayHasKey('token_type', $result); - $this->assertArrayHasKey('expires_in', $result); - $this->assertArrayHasKey('expires', $result); - } - - public function test_issueAccessToken_client_credentialsPOST() - { - $this->oauth->enableGrantType('client_credentials'); - - $auth_code = $this->oauth->newAuthoriseRequest('user', '123', array( - 'client_id' => 'test', - 'redirect_uri' => 'http://example.com/test', - 'scopes' => array(array( - 'id' => 1, - 'scope' => 'test', - 'name' => 'test', - 'description' => 'test' - )) - )); - - $_POST['client_id'] = 'test'; - $_POST['client_secret'] = 'test'; - $_POST['redirect_uri'] = 'http://example.com/test'; - $_POST['grant_type'] = 'client_credentials'; - $_POST['code'] = $auth_code; - - $result = $this->oauth->issueAccessToken(); - - $this->assertCount(4, $result); - $this->assertArrayHasKey('access_token', $result); - $this->assertArrayHasKey('token_type', $result); - $this->assertArrayHasKey('expires_in', $result); - $this->assertArrayHasKey('expires', $result); - } - - public function test_issueAccessToken_client_credentials_withRefreshToken() - { - $this->oauth->enableGrantType('client_credentials'); - $this->oauth->enableGrantType('refresh_token'); - - $auth_code = $this->oauth->newAuthoriseRequest('user', '123', array( - 'client_id' => 'test', - 'redirect_uri' => 'http://example.com/test', - 'scopes' => array(array( - 'id' => 1, - 'scope' => 'test', - 'name' => 'test', - 'description' => 'test' - )) - )); - - $params['client_id'] = 'test'; - $params['client_secret'] = 'test'; - $params['redirect_uri'] = 'http://example.com/test'; - $params['grant_type'] = 'client_credentials'; - $params['code'] = $auth_code; - - $result = $this->oauth->issueAccessToken($params); - - $this->assertCount(5, $result); - $this->assertArrayHasKey('access_token', $result); - $this->assertArrayHasKey('token_type', $result); - $this->assertArrayHasKey('expires_in', $result); - $this->assertArrayHasKey('expires', $result); - $this->assertArrayHasKey('refresh_token', $result); - } - - public function test_issueAccessToken_refresh_tokenPOST() - { - $this->oauth->enableGrantType('authorization_code'); - $this->oauth->enableGrantType('refresh_token'); - - $auth_code = $this->oauth->newAuthoriseRequest('user', '123', array( - 'client_id' => 'test', - 'redirect_uri' => 'http://example.com/test', - 'scopes' => array(array( - 'id' => 1, - 'scope' => 'test', - 'name' => 'test', - 'description' => 'test' - )) - )); - - $_POST['client_id'] = 'test'; - $_POST['client_secret'] = 'test'; - $_POST['redirect_uri'] = 'http://example.com/test'; - $_POST['grant_type'] = 'authorization_code'; - $_POST['code'] = $auth_code; - - $result = $this->oauth->issueAccessToken(); - - $this->assertCount(5, $result); - $this->assertArrayHasKey('access_token', $result); - $this->assertArrayHasKey('token_type', $result); - $this->assertArrayHasKey('expires_in', $result); - $this->assertArrayHasKey('expires', $result); - $this->assertArrayHasKey('refresh_token', $result); - - // Wait for a few seconds for the access token to age - sleep(1); - - // Refresh the token - $_POST['client_id'] = 'test'; - $_POST['client_secret'] = 'test'; - $_POST['redirect_uri'] = 'http://example.com/test'; - $_POST['grant_type'] = 'refresh_token'; - $_POST['refresh_token'] = $result['refresh_token']; - - $result2 = $this->oauth->issueAccessToken(); - - $this->assertCount(5, $result2); - $this->assertArrayHasKey('access_token', $result2); - $this->assertArrayHasKey('token_type', $result2); - $this->assertArrayHasKey('expires_in', $result2); - $this->assertArrayHasKey('expires', $result2); - $this->assertArrayHasKey('refresh_token', $result2); - - $this->assertNotEquals($result['access_token'], $result2['access_token']); - $this->assertNotEquals($result['refresh_token'], $result2['refresh_token']); - $this->assertNotEquals($result['expires'], $result2['expires']); - $this->assertEquals($result['expires_in'], $result2['expires_in']); - $this->assertEquals($result['token_type'], $result2['token_type']); - } - - /** - * @expectedException OAuth2\Authentication\ClientException - * @expectedExceptionCode 0 - */ - public function test_issueAccessToken_refresh_tokenMissingToken() - { - $this->oauth->enableGrantType('authorization_code'); - $this->oauth->enableGrantType('refresh_token'); - - $auth_code = $this->oauth->newAuthoriseRequest('user', '123', array( - 'client_id' => 'test', - 'redirect_uri' => 'http://example.com/test', - 'scopes' => array(array( - 'id' => 1, - 'scope' => 'test', - 'name' => 'test', - 'description' => 'test' - )) - )); - - $_POST['client_id'] = 'test'; - $_POST['client_secret'] = 'test'; - $_POST['redirect_uri'] = 'http://example.com/test'; - $_POST['grant_type'] = 'authorization_code'; - $_POST['code'] = $auth_code; - - $result = $this->oauth->issueAccessToken(); - - $this->assertCount(5, $result); - $this->assertArrayHasKey('access_token', $result); - $this->assertArrayHasKey('token_type', $result); - $this->assertArrayHasKey('expires_in', $result); - $this->assertArrayHasKey('expires', $result); - $this->assertArrayHasKey('refresh_token', $result); - - // Wait for a few seconds for the access token to age - sleep(1); - - // Refresh the token - $_POST['client_id'] = 'test'; - $_POST['client_secret'] = 'test'; - $_POST['redirect_uri'] = 'http://example.com/test'; - $_POST['grant_type'] = 'refresh_token'; - - $result2 = $this->oauth->issueAccessToken(); - } - - /** - * @expectedException OAuth2\Authentication\ClientException - * @expectedExceptionCode 0 - */ - public function test_issueAccessToken_invalid_refresh_token() - { - $this->oauth->enableGrantType('authorization_code'); - $this->oauth->enableGrantType('refresh_token'); - - $auth_code = $this->oauth->newAuthoriseRequest('user', '123', array( - 'client_id' => 'test', - 'redirect_uri' => 'http://example.com/test', - 'scopes' => array(array( - 'id' => 1, - 'scope' => 'test', - 'name' => 'test', - 'description' => 'test' - )) - )); - - $params['client_id'] = 'test'; - $params['client_secret'] = 'test'; - $params['redirect_uri'] = 'http://example.com/test'; - $params['grant_type'] = 'authorization_code'; - $params['code'] = $auth_code; - - $result = $this->oauth->issueAccessToken($params); - - $this->assertCount(5, $result); - $this->assertArrayHasKey('access_token', $result); - $this->assertArrayHasKey('token_type', $result); - $this->assertArrayHasKey('expires_in', $result); - $this->assertArrayHasKey('expires', $result); - $this->assertArrayHasKey('refresh_token', $result); - - // Wait for a few seconds for the access token to age - sleep(1); - - // Refresh the token - $params2['client_id'] = 'test'; - $params2['client_secret'] = 'test'; - $params2['redirect_uri'] = 'http://example.com/test'; - $params2['grant_type'] = 'refresh_token'; - $params2['refresh_token'] = 'blah'; - - $result2 = $this->oauth->issueAccessToken($params2); - } - - /** - * @expectedException OAuth2\Authentication\ServerException - * @expectedExceptionCode 0 - */ - public function test_issueAccessToken_password_grant_Missing_Callback() - { - $this->oauth->enableGrantType('password'); - } - - public function test_issueAccessToken_password_grant() - { - $this->oauth->enableGrantType('password', function(){ - return true; - }); - - $params['client_id'] = 'test'; - $params['client_secret'] = 'test'; - $params['grant_type'] = 'password'; - $params['username'] = 'alexbilbie'; - $params['password'] = 'helloworld'; - - $result = $this->oauth->issueAccessToken($params); - - $this->assertCount(4, $result); - $this->assertArrayHasKey('access_token', $result); - $this->assertArrayHasKey('token_type', $result); - $this->assertArrayHasKey('expires_in', $result); - $this->assertArrayHasKey('expires', $result); - } - - public function test_issueAccessToken_password_grantPOST() - { - $this->oauth->enableGrantType('password', function(){ - return true; - }); - - $_POST['client_id'] = 'test'; - $_POST['client_secret'] = 'test'; - $_POST['grant_type'] = 'password'; - $_POST['username'] = 'alexbilbie'; - $_POST['password'] = 'helloworld'; - - $result = $this->oauth->issueAccessToken(); - - $this->assertCount(4, $result); - $this->assertArrayHasKey('access_token', $result); - $this->assertArrayHasKey('token_type', $result); - $this->assertArrayHasKey('expires_in', $result); - $this->assertArrayHasKey('expires', $result); - } - - public function test_issueAccessToken_password_grant_withRefreshToken() - { - $this->oauth->enableGrantType('password', function(){ - return true; - }); - - $this->oauth->enableGrantType('refresh_token'); - - $params['client_id'] = 'test'; - $params['client_secret'] = 'test'; - $params['grant_type'] = 'password'; - $params['username'] = 'alexbilbie'; - $params['password'] = 'helloworld'; - - $result = $this->oauth->issueAccessToken($params); - - $this->assertCount(5, $result); - $this->assertArrayHasKey('access_token', $result); - $this->assertArrayHasKey('token_type', $result); - $this->assertArrayHasKey('expires_in', $result); - $this->assertArrayHasKey('expires', $result); - $this->assertArrayHasKey('refresh_token', $result); - } - - /** - * @expectedException OAuth2\Authentication\ClientException - * @expectedExceptionCode 0 - */ - public function test_issueAccessToken_password_grant_wrongCreds() - { - $this->oauth->enableGrantType('password', function(){ - return false; - }); - - $params['client_id'] = 'test'; - $params['client_secret'] = 'test'; - $params['grant_type'] = 'password'; - $params['username'] = 'alexbilbie'; - $params['password'] = 'helloworld'; - - $result = $this->oauth->issueAccessToken($params); - } - - /** - * @expectedException OAuth2\Authentication\ClientException - * @expectedExceptionCode 0 - */ - public function test_issueAccessToken_password_grant_missingUsername() - { - $this->oauth->enableGrantType('password', function(){ - return true; - }); - - $params['client_id'] = 'test'; - $params['client_secret'] = 'test'; - $params['grant_type'] = 'password'; - - $result = $this->oauth->issueAccessToken($params); - } - - /** - * @expectedException OAuth2\Authentication\ClientException - * @expectedExceptionCode 0 - */ - public function test_issueAccessToken_password_grant_missingPassword() - { - $this->oauth->enableGrantType('password', function(){ - return true; - }); - - $params['client_id'] = 'test'; - $params['client_secret'] = 'test'; - $params['grant_type'] = 'password'; - $params['username'] = 'alexbilbie'; - - $result = $this->oauth->issueAccessToken($params); - } - - /** - * @expectedException OAuth2\Authentication\ClientException - * @expectedExceptionCode 0 - */ - public function test_issueAccessToken_missingGrantType() - { - $this->oauth->issueAccessToken(); - } - - /** - * @expectedException OAuth2\Authentication\ClientException - * @expectedExceptionCode 7 - */ - public function test_issueAccessToken_unsupportedGrantType() - { - $params['grant_type'] = 'blah'; - - $this->oauth->issueAccessToken($params); - } - - /** - * @expectedException OAuth2\Authentication\ClientException - * @expectedExceptionCode 0 - */ - public function test_completeAuthCodeGrant_missingClientId() - { - $reflector = new ReflectionClass($this->oauth); - $method = $reflector->getMethod('_completeAuthCodeGrant'); - $method->setAccessible(true); - - $method->invoke($this->oauth); - } - - /** - * @expectedException OAuth2\Authentication\ClientException - * @expectedExceptionCode 0 - */ - public function test_completeAuthCodeGrant_missingClientSecret() - { - $reflector = new ReflectionClass($this->oauth); - $method = $reflector->getMethod('_completeAuthCodeGrant'); - $method->setAccessible(true); - - $authParams['client_id'] = 'test'; - - $method->invoke($this->oauth, $authParams); - } - - /** - * @expectedException OAuth2\Authentication\ClientException - * @expectedExceptionCode 0 - */ - public function test_completeAuthCodeGrant_missingRedirectUri() - { - $reflector = new ReflectionClass($this->oauth); - $method = $reflector->getMethod('_completeAuthCodeGrant'); - $method->setAccessible(true); - - $authParams['client_id'] = 'test'; - $authParams['client_secret'] = 'test'; - - $method->invoke($this->oauth, $authParams); - } - - /** - * @expectedException OAuth2\Authentication\ClientException - * @expectedExceptionCode 8 - */ - public function test_completeAuthCodeGrant_invalidClient() - { - $reflector = new ReflectionClass($this->oauth); - $method = $reflector->getMethod('_completeAuthCodeGrant'); - $method->setAccessible(true); - - $authParams['client_id'] = 'test'; - $authParams['client_secret'] = 'test123'; - $authParams['redirect_uri'] = 'http://example.com/test'; - - $method->invoke($this->oauth, $authParams); - } - - /** - * @expectedException OAuth2\Authentication\ClientException - * @expectedExceptionCode 0 - */ - public function test_completeAuthCodeGrant_missingCode() - { - $reflector = new ReflectionClass($this->oauth); - $method = $reflector->getMethod('_completeAuthCodeGrant'); - $method->setAccessible(true); - - $authParams['client_id'] = 'test'; - $authParams['client_secret'] = 'test'; - $authParams['redirect_uri'] = 'http://example.com/test'; - - $method->invoke($this->oauth, $authParams); - } - - /** - * @expectedException OAuth2\Authentication\ClientException - * @expectedExceptionCode 9 - */ - public function test_completeAuthCodeGrant_invalidCode() - { - $reflector = new ReflectionClass($this->oauth); - $method = $reflector->getMethod('_completeAuthCodeGrant'); - $method->setAccessible(true); - - $authParams['client_id'] = 'test'; - $authParams['client_secret'] = 'test'; - $authParams['redirect_uri'] = 'http://example.com/test'; - $authParams['code'] = 'blah'; - - $method->invoke($this->oauth, $authParams); - } - - /** - * @expectedException OAuth2\Authentication\ServerException - * @expectedExceptionMessage No registered database abstractor - */ - public function test_noRegisteredDatabaseAbstractor() - { - $reflector = new ReflectionClass($this->oauth); - $method = $reflector->getMethod('_dbCall'); - $method->setAccessible(true); - - $dbAbstractor = $reflector->getProperty('_db'); - $dbAbstractor->setAccessible(true); - $dbAbstractor->setValue($this->oauth, null); - - $result = $method->invoke($this->oauth); - } - - /** - * @expectedException OAuth2\Authentication\ServerException - * @expectedExceptionMessage Registered database abstractor is not an instance of OAuth2\Authentication\Database - */ - public function test_invalidRegisteredDatabaseAbstractor() - { - $fake = new stdClass; - $this->oauth->registerDbAbstractor($fake); - - $reflector = new ReflectionClass($this->oauth); - $method = $reflector->getMethod('_dbCall'); - $method->setAccessible(true); - - $result = $method->invoke($this->oauth); - } - -} From c7e9235db3c8b751dbc5bdffc0bece6e7660c14c Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Mon, 4 Feb 2013 19:46:29 +0000 Subject: [PATCH 068/113] Added util unit tests --- tests/util/RedirectUriTest.php | 15 +++++++ tests/util/RequestTest.php | 73 ++++++++++++++++++++++++++++++++++ tests/util/SecureKeyTest.php | 15 +++++++ 3 files changed, 103 insertions(+) create mode 100644 tests/util/RedirectUriTest.php create mode 100644 tests/util/RequestTest.php create mode 100644 tests/util/SecureKeyTest.php diff --git a/tests/util/RedirectUriTest.php b/tests/util/RedirectUriTest.php new file mode 100644 index 00000000..6f7aaa1e --- /dev/null +++ b/tests/util/RedirectUriTest.php @@ -0,0 +1,15 @@ +'bar')); + $v2 = OAuth2\Util\RedirectUri::make('https://foobar/', array('foo'=>'bar'), '#'); + $v3 = OAuth2\Util\RedirectUri::make('https://foobar/', array('foo'=>'bar', 'bar' => 'foo')); + + $this->assertEquals('https://foobar/?foo=bar', $v1); + $this->assertEquals('https://foobar/#foo=bar', $v2); + $this->assertEquals('https://foobar/?foo=bar&bar=foo', $v3); + } +} \ No newline at end of file diff --git a/tests/util/RequestTest.php b/tests/util/RequestTest.php new file mode 100644 index 00000000..91413204 --- /dev/null +++ b/tests/util/RequestTest.php @@ -0,0 +1,73 @@ +request = new OAuth2\Request( + array('foo' => 'bar'), + array('foo' => 'bar'), + array('foo' => 'bar'), + array('foo' => 'bar'), + array('HTTP_HOST' => 'foobar.com') + ); + } + + function test_buildFromIndex() + { + $r = new OAuth2\Request(); + $r->buildFromGlobals(); + + $this->assertTrue($r instanceof OAuth2\Request); + } + + function test_get() + { + $this->assertEquals('bar', $this->request->get('foo')); + $this->assertEquals(array('foo' => 'bar'), $this->request->get()); + } + + function test_post() + { + $this->assertEquals('bar', $this->request->post('foo')); + $this->assertEquals(array('foo' => 'bar'), $this->request->post()); + } + + function test_file() + { + $this->assertEquals('bar', $this->request->file('foo')); + $this->assertEquals(array('foo' => 'bar'), $this->request->file()); + } + + function test_cookie() + { + $this->assertEquals('bar', $this->request->cookie('foo')); + $this->assertEquals(array('foo' => 'bar'), $this->request->cookie()); + } + + function test_server() + { + $this->assertEquals('foobar.com', $this->request->server('HTTP_HOST')); + $this->assertEquals(array('HTTP_HOST' => 'foobar.com'), $this->request->server()); + } + + function test_header() + { + $this->assertEquals('foobar.com', $this->request->header('host')); + $this->assertEquals(array('host' => 'foobar.com'), $this->request->header()); + } + + /** + * @expectedException InvalidArgumentException + */ + function test_unknownProperty() + { + $reflector = new ReflectionClass($this->request); + $method = $reflector->getMethod('getPropertyValue'); + $method->setAccessible(true); + + $result = $method->invoke($this->request, 'blah'); + } +} \ No newline at end of file diff --git a/tests/util/SecureKeyTest.php b/tests/util/SecureKeyTest.php new file mode 100644 index 00000000..6a46c6c9 --- /dev/null +++ b/tests/util/SecureKeyTest.php @@ -0,0 +1,15 @@ +assertEquals(40, strlen($v1)); + $this->assertTrue($v1 !== $v2); + $this->assertEquals(50, strlen($v3)); + } +} \ No newline at end of file From 81f3dc9a2bef45b112487309d1de36ef2124c1bf Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Mon, 4 Feb 2013 19:46:37 +0000 Subject: [PATCH 069/113] Added new auth server unit tests --- tests/authentication/AuthServerTest.php | 601 ++++++++++++++++++++++++ 1 file changed, 601 insertions(+) create mode 100644 tests/authentication/AuthServerTest.php diff --git a/tests/authentication/AuthServerTest.php b/tests/authentication/AuthServerTest.php new file mode 100644 index 00000000..7a00bd31 --- /dev/null +++ b/tests/authentication/AuthServerTest.php @@ -0,0 +1,601 @@ +client = M::mock('OAuth2\Storage\ClientInterface'); + $this->session = M::mock('OAuth2\Storage\SessionInterface'); + $this->scope = M::mock('OAuth2\Storage\ScopeInterface'); + } + + private function returnDefault() + { + return new OAuth2\AuthServer($this->client, $this->session, $this->scope); + } + + /** + * @expectedException PHPUnit_Framework_Error + */ + public function test__construct_NoStorage() + { + $a = new OAuth2\AuthServer; + } + + public function test__contruct_WithStorage() + { + $a = $this->returnDefault(); + } + + public function test_getExceptionMessage() + { + $m = OAuth2\AuthServer::getExceptionMessage('access_denied'); + + $reflector = new ReflectionClass($this->returnDefault()); + $exceptionMessages = $reflector->getProperty('exceptionMessages'); + $exceptionMessages->setAccessible(true); + $v = $exceptionMessages->getValue(); + + $this->assertEquals($v['access_denied'], $m); + } + + public function test_hasGrantType() + { + $this->assertFalse(OAuth2\AuthServer::hasGrantType('test')); + } + + public function test_addGrantType() + { + $a = $this->returnDefault(); + $grant = M::mock('OAuth2\Grant\GrantTypeInterface'); + $grant->shouldReceive('getResponseType')->times(2)->andReturn('test'); + $a->addGrantType($grant, 'test'); + + $this->assertTrue(OAuth2\AuthServer::hasGrantType('test')); + } + + public function test_addGrantType_noIdentifier() + { + $a = $this->returnDefault(); + $grant = M::mock('OAuth2\Grant\GrantTypeInterface'); + $grant->shouldReceive('getIdentifier')->times(1)->andReturn('test'); + $grant->shouldReceive('getResponseType')->times(2)->andReturn('test'); + $a->addGrantType($grant); + + $this->assertTrue(OAuth2\AuthServer::hasGrantType('test')); + } + + public function test_getScopeDelimeter() + { + $a = $this->returnDefault(); + $this->assertEquals(',', $a->getScopeDelimeter()); + } + + public function test_setScopeDelimeter() + { + $a = $this->returnDefault(); + $a->setScopeDelimeter(';'); + $this->assertEquals(';', $a->getScopeDelimeter()); + } + + public function test_getExpiresIn() + { + $a = $this->returnDefault(); + $a->setExpiresIn(7200); + $this->assertEquals(7200, $a::getExpiresIn()); + } + + public function test_setExpiresIn() + { + $a = $this->returnDefault(); + $a->setScopeDelimeter(';'); + $this->assertEquals(';', $a->getScopeDelimeter()); + } + + public function test_setRequest() + { + $a = $this->returnDefault(); + $request = new \OAuth2\Request(); + $a->setRequest($request); + + $reflector = new ReflectionClass($a); + $requestProperty = $reflector->getProperty('request'); + $requestProperty->setAccessible(true); + $v = $requestProperty->getValue(); + + $this->assertTrue($v instanceof OAuth2\RequestInterface); + } + + public function test_getRequest() + { + $a = $this->returnDefault(); + $request = new OAuth2\Request(); + $a->setRequest($request); + $v = $a::getRequest(); + + $this->assertTrue($v instanceof OAuth2\RequestInterface); + } + + public function test_getStorage() + { + $a = $this->returnDefault(); + $this->assertTrue($a->getStorage('session') instanceof OAuth2\Storage\SessionInterface); + } + + /** + * @expectedException OAuth2\Exception\ClientException + * @expectedExceptionCode 0 + */ + public function test_checkAuthoriseParams_noClientId() + { + $a = $this->returnDefault(); + $a->checkAuthoriseParams(); + } + + /** + * @expectedException OAuth2\Exception\ClientException + * @expectedExceptionCode 0 + */ + public function test_checkAuthoriseParams_noRedirectUri() + { + $a = $this->returnDefault(); + $a->checkAuthoriseParams(array( + 'client_id' => 1234 + )); + } + + /** + * @expectedException OAuth2\Exception\ClientException + * @expectedExceptionCode 8 + */ + public function test_checkAuthoriseParams_badClient() + { + $this->client->shouldReceive('getClient')->times(1)->andReturn(false); + + $a = $this->returnDefault(); + $a->checkAuthoriseParams(array( + 'client_id' => 1234, + 'redirect_uri' => 'http://foo/redirect' + )); + } + + /** + * @expectedException OAuth2\Exception\ClientException + * @expectedExceptionCode 0 + */ + public function test_checkAuthoriseParams_missingResponseType() + { + $this->client->shouldReceive('getClient')->times(1)->andReturn(array( + 'client_id' => 1234, + 'client_secret' => 5678, + 'redirect_uri' => 'http://foo/redirect', + 'name' => 'Example Client' + )); + + $a = $this->returnDefault(); + $a->checkAuthoriseParams(array( + 'client_id' => 1234, + 'redirect_uri' => 'http://foo/redirect' + )); + } + + /** + * @expectedException OAuth2\Exception\ClientException + * @expectedExceptionCode 3 + */ + public function test_checkAuthoriseParams_badResponseType() + { + $this->client->shouldReceive('getClient')->times(1)->andReturn(array( + 'client_id' => 1234, + 'client_secret' => 5678, + 'redirect_uri' => 'http://foo/redirect', + 'name' => 'Example Client' + )); + + $a = $this->returnDefault(); + $a->checkAuthoriseParams(array( + 'client_id' => 1234, + 'redirect_uri' => 'http://foo/redirect', + 'response_type' => 'foo' + )); + } + + /** + * @expectedException OAuth2\Exception\ClientException + * @expectedExceptionCode 0 + */ + public function test_checkAuthoriseParams_missingScopes() + { + $this->client->shouldReceive('getClient')->times(1)->andReturn(array( + 'client_id' => 1234, + 'client_secret' => 5678, + 'redirect_uri' => 'http://foo/redirect', + 'name' => 'Example Client' + )); + + $a = $this->returnDefault(); + $a->addGrantType(new OAuth2\Grant\AuthCode()); + + $a->checkAuthoriseParams(array( + 'client_id' => 1234, + 'redirect_uri' => 'http://foo/redirect', + 'response_type' => 'code', + 'scope' => '' + )); + } + + /** + * @expectedException OAuth2\Exception\ClientException + * @expectedExceptionCode 4 + */ + public function test_checkAuthoriseParams_badScopes() + { + $this->client->shouldReceive('getClient')->times(1)->andReturn(array( + 'client_id' => 1234, + 'client_secret' => 5678, + 'redirect_uri' => 'http://foo/redirect', + 'name' => 'Example Client' + )); + + $this->scope->shouldReceive('getScope')->times(1)->andReturn(false); + + $a = $this->returnDefault(); + $a->addGrantType(new OAuth2\Grant\AuthCode()); + + $a->checkAuthoriseParams(array( + 'client_id' => 1234, + 'redirect_uri' => 'http://foo/redirect', + 'response_type' => 'code', + 'scope' => 'foo' + )); + } + + public function test_checkAuthoriseParams_passedInput() + { + $a = $this->returnDefault(); + $a->addGrantType(new OAuth2\Grant\AuthCode()); + + $this->client->shouldReceive('getClient')->times(1)->andReturn(array( + 'client_id' => 1234, + 'client_secret' => 5678, + 'redirect_uri' => 'http://foo/redirect', + 'name' => 'Example Client' + )); + + $this->scope->shouldReceive('getScope')->times(1)->andReturn(array( + 'id' => 1, + 'scope' => 'foo', + 'name' => 'Foo Name', + 'description' => 'Foo Name Description' + )); + + $v = $a->checkAuthoriseParams(array( + 'client_id' => 1234, + 'redirect_uri' => 'http://foo/redirect', + 'response_type' => 'code', + 'scope' => 'foo' + )); + + $this->assertEquals(array( + 'client_id' => 1234, + 'redirect_uri' => 'http://foo/redirect', + 'client_details' => array( + 'client_id' => 1234, + 'client_secret' => 5678, + 'redirect_uri' => 'http://foo/redirect', + 'name' => 'Example Client' + ), + 'response_type' => 'code', + 'scopes' => array( + array( + 'id' => 1, + 'scope' => 'foo', + 'name' => 'Foo Name', + 'description' => 'Foo Name Description' + ) + ) + ), $v); + } + + public function test_checkAuthoriseParams() + { + $this->client->shouldReceive('getClient')->times(1)->andReturn(array( + 'client_id' => 1234, + 'client_secret' => 5678, + 'redirect_uri' => 'http://foo/redirect', + 'name' => 'Example Client' + )); + + $this->scope->shouldReceive('getScope')->times(1)->andReturn(array( + 'id' => 1, + 'scope' => 'foo', + 'name' => 'Foo Name', + 'description' => 'Foo Name Description' + )); + + $a = $this->returnDefault(); + $a->addGrantType(new OAuth2\Grant\AuthCode()); + + $_GET['client_id'] = 1234; + $_GET['redirect_uri'] = 'http://foo/redirect'; + $_GET['response_type'] = 'code'; + $_GET['scope'] = 'foo'; + + $request = new OAuth2\Request($_GET); + $a->setRequest($request); + + $v = $a->checkAuthoriseParams(); + + $this->assertEquals(array( + 'client_id' => 1234, + 'redirect_uri' => 'http://foo/redirect', + 'client_details' => array( + 'client_id' => 1234, + 'client_secret' => 5678, + 'redirect_uri' => 'http://foo/redirect', + 'name' => 'Example Client' + ), + 'response_type' => 'code', + 'scopes' => array( + array( + 'id' => 1, + 'scope' => 'foo', + 'name' => 'Foo Name', + 'description' => 'Foo Name Description' + ) + ) + ), $v); + } + + function test_newAuthoriseRequest() + { + $this->session->shouldReceive('deleteSession')->times(1)->andReturn(null); + $this->session->shouldReceive('createSession')->times(1)->andReturn(1); + $this->session->shouldReceive('associateScope')->times(1)->andReturn(null); + + $a = $this->returnDefault(); + + $params = array( + 'client_id' => 1234, + 'redirect_uri' => 'http://foo/redirect', + 'client_details' => array( + 'client_id' => 1234, + 'client_secret' => 5678, + 'redirect_uri' => 'http://foo/redirect', + 'name' => 'Example Client' + ), + 'response_type' => 'code', + 'scopes' => array( + array( + 'id' => 1, + 'scope' => 'foo', + 'name' => 'Foo Name', + 'description' => 'Foo Name Description' + ) + ) + ); + + $v = $a->newAuthoriseRequest('user', 123, $params); + + $this->assertEquals(40, strlen($v)); + } + + public function test_getGrantType() + { + $a = $this->returnDefault(); + $a->addGrantType(new OAuth2\Grant\AuthCode()); + + $reflector = new ReflectionClass($a); + $method = $reflector->getMethod('getGrantType'); + $method->setAccessible(true); + + $result = $method->invoke($a, 'authorization_code'); + + $this->assertTrue($result instanceof OAuth2\Grant\GrantTypeInterface); + } + + /** + * @expectedException OAuth2\Exception\ClientException + * @expectedExceptionCode 0 + */ + public function test_issueAccessToken_missingGrantType() + { + $a = $this->returnDefault(); + $a->addGrantType(new OAuth2\Grant\AuthCode()); + + $v = $a->issueAccessToken(); + } + + /** + * @expectedException OAuth2\Exception\ClientException + * @expectedExceptionCode 7 + */ + public function test_issueAccessToken_badGrantType() + { + $a = $this->returnDefault(); + $a->addGrantType(new OAuth2\Grant\AuthCode()); + + $v = $a->issueAccessToken(array('grant_type' => 'foo')); + } + + /** + * @expectedException OAuth2\Exception\ClientException + * @expectedExceptionCode 0 + */ + public function test_issueAccessToken_missingClientId() + { + $a = $this->returnDefault(); + $a->addGrantType(new OAuth2\Grant\AuthCode()); + + $v = $a->issueAccessToken(array( + 'grant_type' => 'authorization_code' + )); + } + + /** + * @expectedException OAuth2\Exception\ClientException + * @expectedExceptionCode 0 + */ + public function test_issueAccessToken_missingClientSecret() + { + $a = $this->returnDefault(); + $a->addGrantType(new OAuth2\Grant\AuthCode()); + + $v = $a->issueAccessToken(array( + 'grant_type' => 'authorization_code', + 'client_id' => 1234 + )); + } + + /** + * @expectedException OAuth2\Exception\ClientException + * @expectedExceptionCode 0 + */ + public function test_issueAccessToken_missingRedirectUri() + { + $a = $this->returnDefault(); + $a->addGrantType(new OAuth2\Grant\AuthCode()); + + $v = $a->issueAccessToken(array( + 'grant_type' => 'authorization_code', + 'client_id' => 1234, + 'client_secret' => 5678 + )); + } + + /** + * @expectedException OAuth2\Exception\ClientException + * @expectedExceptionCode 8 + */ + public function test_issueAccessToken_badClient() + { + $this->client->shouldReceive('getClient')->times(1)->andReturn(false); + + $a = $this->returnDefault(); + $a->addGrantType(new OAuth2\Grant\AuthCode()); + + $v = $a->issueAccessToken(array( + 'grant_type' => 'authorization_code', + 'client_id' => 1234, + 'client_secret' => 5678, + 'redirect_uri' => 'http://foo/redirect' + )); + } + + /** + * @expectedException OAuth2\Exception\ClientException + * @expectedExceptionCode 0 + */ + public function test_issueAccessToken_missingCode() + { + $this->client->shouldReceive('getClient')->times(1)->andReturn(array()); + + $a = $this->returnDefault(); + $a->addGrantType(new OAuth2\Grant\AuthCode()); + + $v = $a->issueAccessToken(array( + 'grant_type' => 'authorization_code', + 'client_id' => 1234, + 'client_secret' => 5678, + 'redirect_uri' => 'http://foo/redirect' + )); + } + + /** + * @expectedException OAuth2\Exception\ClientException + * @expectedExceptionCode 9 + */ + public function test_issueAccessToken_badCode() + { + $this->client->shouldReceive('getClient')->times(1)->andReturn(array()); + $this->session->shouldReceive('validateAuthCode')->times(1)->andReturn(false); + + $a = $this->returnDefault(); + $a->addGrantType(new OAuth2\Grant\AuthCode()); + + $v = $a->issueAccessToken(array( + 'grant_type' => 'authorization_code', + 'client_id' => 1234, + 'client_secret' => 5678, + 'redirect_uri' => 'http://foo/redirect', + 'code' => 'foobar' + )); + } + + public function test_issueAccessToken_passedInput() + { + $this->client->shouldReceive('getClient')->times(1)->andReturn(array( + 'client_id' => 1234, + 'client_secret' => 5678, + 'redirect_uri' => 'http://foo/redirect', + 'name' => 'Example Client' + )); + + $this->session->shouldReceive('validateAuthCode')->andReturn(1); + $this->session->shouldReceive('updateSession')->andReturn(null); + + $a = $this->returnDefault(); + $a->addGrantType(new OAuth2\Grant\AuthCode()); + + $v = $a->issueAccessToken(array( + 'grant_type' => 'authorization_code', + 'client_id' => 1234, + 'client_secret' => 5678, + 'redirect_uri' => 'http://foo/redirect', + 'code' => 'foobar' + )); + + $this->assertArrayHasKey('access_token', $v); + $this->assertArrayHasKey('token_type', $v); + $this->assertArrayHasKey('expires', $v); + $this->assertArrayHasKey('expires_in', $v); + + $this->assertEquals($a::getExpiresIn(), $v['expires_in']); + $this->assertEquals(time()+$a::getExpiresIn(), $v['expires']); + } + + public function test_issueAccessToken() + { + $this->client->shouldReceive('getClient')->times(1)->andReturn(array( + 'client_id' => 1234, + 'client_secret' => 5678, + 'redirect_uri' => 'http://foo/redirect', + 'name' => 'Example Client' + )); + + $this->session->shouldReceive('validateAuthCode')->andReturn(1); + $this->session->shouldReceive('updateSession')->andReturn(null); + + $a = $this->returnDefault(); + $a->addGrantType(new OAuth2\Grant\AuthCode()); + + $_POST['grant_type'] = 'authorization_code'; + $_POST['client_id'] = 1234; + $_POST['client_secret'] = 5678; + $_POST['redirect_uri'] = 'http://foo/redirect'; + $_POST['code'] = 'foobar'; + + $request = new OAuth2\Request(array(), $_POST); + $a->setRequest($request); + + $v = $a->issueAccessToken(); + + $this->assertArrayHasKey('access_token', $v); + $this->assertArrayHasKey('token_type', $v); + $this->assertArrayHasKey('expires', $v); + $this->assertArrayHasKey('expires_in', $v); + + $this->assertEquals($a::getExpiresIn(), $v['expires_in']); + $this->assertEquals(time()+$a::getExpiresIn(), $v['expires']); + } + + public function tearDown() { + M::close(); + } +} \ No newline at end of file From 7214101cfc939234e6ce5fd4b9a5cfda07329978 Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Mon, 4 Feb 2013 19:47:11 +0000 Subject: [PATCH 070/113] Ensure Travis installs Mockery --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index fe21d0e2..5034e99f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,5 +4,5 @@ php: - 5.3 - 5.4 -before_script: composer install +before_script: composer install --dev script: phpunit -c build/phpunit.xml \ No newline at end of file From 66bea97e8c0075ff77b061a17417c07199f98b60 Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Tue, 5 Feb 2013 10:07:36 +0000 Subject: [PATCH 071/113] Bug fixes based on previous code changes --- src/OAuth2/Grant/RefreshToken.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/OAuth2/Grant/RefreshToken.php b/src/OAuth2/Grant/RefreshToken.php index e4e3fb51..1f89d36c 100644 --- a/src/OAuth2/Grant/RefreshToken.php +++ b/src/OAuth2/Grant/RefreshToken.php @@ -46,7 +46,7 @@ class RefreshToken implements GrantTypeInterface { } // Validate client ID and redirect URI - $clientDetails = AuthServer::getStorage('client')->get($authParams['client_id'], $authParams['client_secret']); + $clientDetails = AuthServer::getStorage('client')->getClient($authParams['client_id'], $authParams['client_secret']); if ($clientDetails === false) { throw new Exception\ClientException(AuthServer::getExceptionMessage('invalid_client'), 8); @@ -65,8 +65,8 @@ class RefreshToken implements GrantTypeInterface { // Validate refresh token $sessionId = AuthServer::getStorage('client')->validateRefreshToken( - $params['refresh_token'], - $params['client_id'] + $authParams['refresh_token'], + $authParams['client_id'] ); if ($sessionId === false) { From 14a7142ad7325ce219b4d77d1712a78c4e5b0230 Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Tue, 5 Feb 2013 10:07:45 +0000 Subject: [PATCH 072/113] Lots more tests --- tests/authentication/AuthServerTest.php | 255 ++++++++++++++++++++++-- 1 file changed, 233 insertions(+), 22 deletions(-) diff --git a/tests/authentication/AuthServerTest.php b/tests/authentication/AuthServerTest.php index 7a00bd31..b6556f02 100644 --- a/tests/authentication/AuthServerTest.php +++ b/tests/authentication/AuthServerTest.php @@ -54,7 +54,7 @@ class Authentication_Server_test extends PHPUnit_Framework_TestCase { $a = $this->returnDefault(); $grant = M::mock('OAuth2\Grant\GrantTypeInterface'); - $grant->shouldReceive('getResponseType')->times(2)->andReturn('test'); + $grant->shouldReceive('getResponseType')->andReturn('test'); $a->addGrantType($grant, 'test'); $this->assertTrue(OAuth2\AuthServer::hasGrantType('test')); @@ -64,8 +64,8 @@ class Authentication_Server_test extends PHPUnit_Framework_TestCase { $a = $this->returnDefault(); $grant = M::mock('OAuth2\Grant\GrantTypeInterface'); - $grant->shouldReceive('getIdentifier')->times(1)->andReturn('test'); - $grant->shouldReceive('getResponseType')->times(2)->andReturn('test'); + $grant->shouldReceive('getIdentifier')->andReturn('test'); + $grant->shouldReceive('getResponseType')->andReturn('test'); $a->addGrantType($grant); $this->assertTrue(OAuth2\AuthServer::hasGrantType('test')); @@ -156,7 +156,7 @@ class Authentication_Server_test extends PHPUnit_Framework_TestCase */ public function test_checkAuthoriseParams_badClient() { - $this->client->shouldReceive('getClient')->times(1)->andReturn(false); + $this->client->shouldReceive('getClient')->andReturn(false); $a = $this->returnDefault(); $a->checkAuthoriseParams(array( @@ -171,7 +171,7 @@ class Authentication_Server_test extends PHPUnit_Framework_TestCase */ public function test_checkAuthoriseParams_missingResponseType() { - $this->client->shouldReceive('getClient')->times(1)->andReturn(array( + $this->client->shouldReceive('getClient')->andReturn(array( 'client_id' => 1234, 'client_secret' => 5678, 'redirect_uri' => 'http://foo/redirect', @@ -191,7 +191,7 @@ class Authentication_Server_test extends PHPUnit_Framework_TestCase */ public function test_checkAuthoriseParams_badResponseType() { - $this->client->shouldReceive('getClient')->times(1)->andReturn(array( + $this->client->shouldReceive('getClient')->andReturn(array( 'client_id' => 1234, 'client_secret' => 5678, 'redirect_uri' => 'http://foo/redirect', @@ -212,7 +212,7 @@ class Authentication_Server_test extends PHPUnit_Framework_TestCase */ public function test_checkAuthoriseParams_missingScopes() { - $this->client->shouldReceive('getClient')->times(1)->andReturn(array( + $this->client->shouldReceive('getClient')->andReturn(array( 'client_id' => 1234, 'client_secret' => 5678, 'redirect_uri' => 'http://foo/redirect', @@ -236,14 +236,14 @@ class Authentication_Server_test extends PHPUnit_Framework_TestCase */ public function test_checkAuthoriseParams_badScopes() { - $this->client->shouldReceive('getClient')->times(1)->andReturn(array( + $this->client->shouldReceive('getClient')->andReturn(array( 'client_id' => 1234, 'client_secret' => 5678, 'redirect_uri' => 'http://foo/redirect', 'name' => 'Example Client' )); - $this->scope->shouldReceive('getScope')->times(1)->andReturn(false); + $this->scope->shouldReceive('getScope')->andReturn(false); $a = $this->returnDefault(); $a->addGrantType(new OAuth2\Grant\AuthCode()); @@ -261,14 +261,14 @@ class Authentication_Server_test extends PHPUnit_Framework_TestCase $a = $this->returnDefault(); $a->addGrantType(new OAuth2\Grant\AuthCode()); - $this->client->shouldReceive('getClient')->times(1)->andReturn(array( + $this->client->shouldReceive('getClient')->andReturn(array( 'client_id' => 1234, 'client_secret' => 5678, 'redirect_uri' => 'http://foo/redirect', 'name' => 'Example Client' )); - $this->scope->shouldReceive('getScope')->times(1)->andReturn(array( + $this->scope->shouldReceive('getScope')->andReturn(array( 'id' => 1, 'scope' => 'foo', 'name' => 'Foo Name', @@ -305,14 +305,14 @@ class Authentication_Server_test extends PHPUnit_Framework_TestCase public function test_checkAuthoriseParams() { - $this->client->shouldReceive('getClient')->times(1)->andReturn(array( + $this->client->shouldReceive('getClient')->andReturn(array( 'client_id' => 1234, 'client_secret' => 5678, 'redirect_uri' => 'http://foo/redirect', 'name' => 'Example Client' )); - $this->scope->shouldReceive('getScope')->times(1)->andReturn(array( + $this->scope->shouldReceive('getScope')->andReturn(array( 'id' => 1, 'scope' => 'foo', 'name' => 'Foo Name', @@ -355,9 +355,9 @@ class Authentication_Server_test extends PHPUnit_Framework_TestCase function test_newAuthoriseRequest() { - $this->session->shouldReceive('deleteSession')->times(1)->andReturn(null); - $this->session->shouldReceive('createSession')->times(1)->andReturn(1); - $this->session->shouldReceive('associateScope')->times(1)->andReturn(null); + $this->session->shouldReceive('deleteSession')->andReturn(null); + $this->session->shouldReceive('createSession')->andReturn(1); + $this->session->shouldReceive('associateScope')->andReturn(null); $a = $this->returnDefault(); @@ -475,7 +475,7 @@ class Authentication_Server_test extends PHPUnit_Framework_TestCase */ public function test_issueAccessToken_badClient() { - $this->client->shouldReceive('getClient')->times(1)->andReturn(false); + $this->client->shouldReceive('getClient')->andReturn(false); $a = $this->returnDefault(); $a->addGrantType(new OAuth2\Grant\AuthCode()); @@ -494,7 +494,7 @@ class Authentication_Server_test extends PHPUnit_Framework_TestCase */ public function test_issueAccessToken_missingCode() { - $this->client->shouldReceive('getClient')->times(1)->andReturn(array()); + $this->client->shouldReceive('getClient')->andReturn(array()); $a = $this->returnDefault(); $a->addGrantType(new OAuth2\Grant\AuthCode()); @@ -513,8 +513,8 @@ class Authentication_Server_test extends PHPUnit_Framework_TestCase */ public function test_issueAccessToken_badCode() { - $this->client->shouldReceive('getClient')->times(1)->andReturn(array()); - $this->session->shouldReceive('validateAuthCode')->times(1)->andReturn(false); + $this->client->shouldReceive('getClient')->andReturn(array()); + $this->session->shouldReceive('validateAuthCode')->andReturn(false); $a = $this->returnDefault(); $a->addGrantType(new OAuth2\Grant\AuthCode()); @@ -530,7 +530,7 @@ class Authentication_Server_test extends PHPUnit_Framework_TestCase public function test_issueAccessToken_passedInput() { - $this->client->shouldReceive('getClient')->times(1)->andReturn(array( + $this->client->shouldReceive('getClient')->andReturn(array( 'client_id' => 1234, 'client_secret' => 5678, 'redirect_uri' => 'http://foo/redirect', @@ -562,7 +562,7 @@ class Authentication_Server_test extends PHPUnit_Framework_TestCase public function test_issueAccessToken() { - $this->client->shouldReceive('getClient')->times(1)->andReturn(array( + $this->client->shouldReceive('getClient')->andReturn(array( 'client_id' => 1234, 'client_secret' => 5678, 'redirect_uri' => 'http://foo/redirect', @@ -595,6 +595,217 @@ class Authentication_Server_test extends PHPUnit_Framework_TestCase $this->assertEquals(time()+$a::getExpiresIn(), $v['expires']); } + public function test_issueAccessToken_with_refresh_token() + { + $this->client->shouldReceive('getClient')->andReturn(array( + 'client_id' => 1234, + 'client_secret' => 5678, + 'redirect_uri' => 'http://foo/redirect', + 'name' => 'Example Client' + )); + + $this->session->shouldReceive('validateAuthCode')->andReturn(1); + $this->session->shouldReceive('updateSession')->andReturn(null); + + $a = $this->returnDefault(); + $a->addGrantType(new OAuth2\Grant\AuthCode()); + $a->addGrantType(new OAuth2\Grant\RefreshToken()); + + $_POST['grant_type'] = 'authorization_code'; + $_POST['client_id'] = 1234; + $_POST['client_secret'] = 5678; + $_POST['redirect_uri'] = 'http://foo/redirect'; + $_POST['code'] = 'foobar'; + + $request = new OAuth2\Request(array(), $_POST); + $a->setRequest($request); + + $v = $a->issueAccessToken(); + + $this->assertArrayHasKey('access_token', $v); + $this->assertArrayHasKey('token_type', $v); + $this->assertArrayHasKey('expires', $v); + $this->assertArrayHasKey('expires_in', $v); + $this->assertArrayHasKey('refresh_token', $v); + + $this->assertEquals($a::getExpiresIn(), $v['expires_in']); + $this->assertEquals(time()+$a::getExpiresIn(), $v['expires']); + } + + /** + * @expectedException OAuth2\Exception\ClientException + * @expectedExceptionCode 0 + */ + public function test_issueAccessToken_refreshTokenGrant_missingClientId() + { + $a = $this->returnDefault(); + $a->addGrantType(new OAuth2\Grant\RefreshToken()); + + $request = new OAuth2\Request(array(), $_POST); + $a->setRequest($request); + + $v = $a->issueAccessToken(array( + 'grant_type' => 'refresh_token' + )); + } + + /** + * @expectedException OAuth2\Exception\ClientException + * @expectedExceptionCode 0 + */ + public function test_issueAccessToken_refreshTokenGrant_missingClientSecret() + { + $a = $this->returnDefault(); + $a->addGrantType(new OAuth2\Grant\RefreshToken()); + + $request = new OAuth2\Request(array(), $_POST); + $a->setRequest($request); + + $v = $a->issueAccessToken(array( + 'grant_type' => 'refresh_token', + 'client_id' => 1234 + )); + } + + /** + * @expectedException OAuth2\Exception\ClientException + * @expectedExceptionCode 8 + */ + public function test_issueAccessToken_refreshTokenGrant_badClient() + { + $this->client->shouldReceive('getClient')->andReturn(false); + + $a = $this->returnDefault(); + $a->addGrantType(new OAuth2\Grant\RefreshToken()); + + $request = new OAuth2\Request(array(), $_POST); + $a->setRequest($request); + + $v = $a->issueAccessToken(array( + 'grant_type' => 'refresh_token', + 'client_id' => 1234, + 'client_secret' => 5678 + )); + } + + /** + * @expectedException OAuth2\Exception\ClientException + * @expectedExceptionCode 0 + */ + public function test_issueAccessToken_refreshTokenGrant_missingRefreshToken() + { + $this->client->shouldReceive('getClient')->andReturn(array()); + + $a = $this->returnDefault(); + $a->addGrantType(new OAuth2\Grant\RefreshToken()); + + $request = new OAuth2\Request(array(), $_POST); + $a->setRequest($request); + + $v = $a->issueAccessToken(array( + 'grant_type' => 'refresh_token', + 'client_id' => 1234, + 'client_secret' => 5678, + //'refresh_token' => + )); + } + + /** + * @expectedException OAuth2\Exception\ClientException + * @expectedExceptionCode 0 + */ + public function test_issueAccessToken_refreshTokenGrant_badRefreshToken() + { + $this->client->shouldReceive('getClient')->andReturn(array()); + $this->client->shouldReceive('validateRefreshToken')->andReturn(false); + + $a = $this->returnDefault(); + $a->addGrantType(new OAuth2\Grant\RefreshToken()); + + $request = new OAuth2\Request(array(), $_POST); + $a->setRequest($request); + + $v = $a->issueAccessToken(array( + 'grant_type' => 'refresh_token', + 'client_id' => 1234, + 'client_secret' => 5678, + 'refresh_token' => 'abcdef' + )); + } + + public function test_issueAccessToken_refreshTokenGrant_passedInput() + { + $this->client->shouldReceive('getClient')->andReturn(array( + 'client_id' => 1234, + 'client_secret' => 5678, + 'redirect_uri' => 'http://foo/redirect', + 'name' => 'Example Client' + )); + + $this->client->shouldReceive('validateRefreshToken')->andReturn(1); + + $this->session->shouldReceive('validateAuthCode')->andReturn(1); + $this->session->shouldReceive('updateSession')->andReturn(null); + $this->session->shouldReceive('updateRefreshToken')->andReturn(null); + + $a = $this->returnDefault(); + $a->addGrantType(new OAuth2\Grant\RefreshToken()); + + $_POST['grant_type'] = 'refresh_token'; + $_POST['client_id'] = 1234; + $_POST['client_secret'] = 5678; + $_POST['refresh_token'] = 'abcdef'; + + $request = new OAuth2\Request(array(), $_POST); + $a->setRequest($request); + + $v = $a->issueAccessToken(); + + $this->assertArrayHasKey('access_token', $v); + $this->assertArrayHasKey('token_type', $v); + $this->assertArrayHasKey('expires', $v); + $this->assertArrayHasKey('expires_in', $v); + $this->assertArrayHasKey('refresh_token', $v); + + $this->assertEquals($a::getExpiresIn(), $v['expires_in']); + $this->assertEquals(time()+$a::getExpiresIn(), $v['expires']); + } + + public function test_issueAccessToken_refreshTokenGrant() + { + $this->client->shouldReceive('getClient')->andReturn(array( + 'client_id' => 1234, + 'client_secret' => 5678, + 'redirect_uri' => 'http://foo/redirect', + 'name' => 'Example Client' + )); + + $this->client->shouldReceive('validateRefreshToken')->andReturn(1); + + $this->session->shouldReceive('validateAuthCode')->andReturn(1); + $this->session->shouldReceive('updateSession')->andReturn(null); + $this->session->shouldReceive('updateRefreshToken')->andReturn(null); + + $a = $this->returnDefault(); + $a->addGrantType(new OAuth2\Grant\RefreshToken()); + + $v = $a->issueAccessToken(array( + 'grant_type' => 'refresh_token', + 'client_id' => 1234, + 'client_secret' => 5678, + 'refresh_token' => 'abcdef', + )); + + $this->assertArrayHasKey('access_token', $v); + $this->assertArrayHasKey('token_type', $v); + $this->assertArrayHasKey('expires', $v); + $this->assertArrayHasKey('expires_in', $v); + $this->assertArrayHasKey('refresh_token', $v); + + $this->assertEquals($a::getExpiresIn(), $v['expires_in']); + $this->assertEquals(time()+$a::getExpiresIn(), $v['expires']); + } + public function tearDown() { M::close(); } From 7a646d3a84dbcfbfeb3cb606d815de414360cc3f Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Tue, 5 Feb 2013 14:47:54 +0000 Subject: [PATCH 073/113] Renamed client get function --- src/OAuth2/Grant/ClientCredentials.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/OAuth2/Grant/ClientCredentials.php b/src/OAuth2/Grant/ClientCredentials.php index 75380819..c2325e81 100644 --- a/src/OAuth2/Grant/ClientCredentials.php +++ b/src/OAuth2/Grant/ClientCredentials.php @@ -46,7 +46,7 @@ class ClientCredentials implements GrantTypeInterface { } // Validate client ID and redirect URI - $clientDetails = AuthServer::getStorage('client')->get($authParams['client_id'], $authParams['client_secret']); + $clientDetails = AuthServer::getStorage('client')->getClient($authParams['client_id'], $authParams['client_secret']); if ($clientDetails === false) { throw new Exception\ClientException(AuthServer::getExceptionMessage('invalid_client'), 8); From 463803f74d646540b3adb930e875bc4e66cabcab Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Tue, 5 Feb 2013 14:48:10 +0000 Subject: [PATCH 074/113] Added client credentials grant function --- tests/authentication/AuthServerTest.php | 129 ++++++++++++++++++++++++ 1 file changed, 129 insertions(+) diff --git a/tests/authentication/AuthServerTest.php b/tests/authentication/AuthServerTest.php index b6556f02..54c29ab7 100644 --- a/tests/authentication/AuthServerTest.php +++ b/tests/authentication/AuthServerTest.php @@ -806,6 +806,135 @@ class Authentication_Server_test extends PHPUnit_Framework_TestCase $this->assertEquals(time()+$a::getExpiresIn(), $v['expires']); } + /** + * @expectedException OAuth2\Exception\ClientException + * @expectedExceptionCode 0 + */ + public function test_issueAccessToken_clientCredentialsGrant_missingClientId() + { + $a = $this->returnDefault(); + $a->addGrantType(new OAuth2\Grant\ClientCredentials()); + + $request = new OAuth2\Request(array(), $_POST); + $a->setRequest($request); + + $v = $a->issueAccessToken(array( + 'grant_type' => 'client_credentials' + )); + } + + /** + * @expectedException OAuth2\Exception\ClientException + * @expectedExceptionCode 0 + */ + public function test_issueAccessToken_clientCredentialsGrant_missingClientCredentials() + { + $a = $this->returnDefault(); + $a->addGrantType(new OAuth2\Grant\ClientCredentials()); + + $request = new OAuth2\Request(array(), $_POST); + $a->setRequest($request); + + $v = $a->issueAccessToken(array( + 'grant_type' => 'client_credentials', + 'client_id' => 1234 + )); + } + + /** + * @expectedException OAuth2\Exception\ClientException + * @expectedExceptionCode 8 + */ + public function test_issueAccessToken_clientCredentialsGrant_badClient() + { + $this->client->shouldReceive('getClient')->andReturn(false); + + $a = $this->returnDefault(); + $a->addGrantType(new OAuth2\Grant\ClientCredentials()); + + $request = new OAuth2\Request(array(), $_POST); + $a->setRequest($request); + + $v = $a->issueAccessToken(array( + 'grant_type' => 'client_credentials', + 'client_id' => 1234, + 'client_secret' => 5678 + )); + } + + function test_issueAccessToken_clientCredentialsGrant_passedInput() + { + $this->client->shouldReceive('getClient')->andReturn(array( + 'client_id' => 1234, + 'client_secret' => 5678, + 'redirect_uri' => 'http://foo/redirect', + 'name' => 'Example Client' + )); + + $this->client->shouldReceive('validateRefreshToken')->andReturn(1); + + $this->session->shouldReceive('validateAuthCode')->andReturn(1); + $this->session->shouldReceive('createSession')->andReturn(1); + $this->session->shouldReceive('deleteSession')->andReturn(null); + $this->session->shouldReceive('updateRefreshToken')->andReturn(null); + + $a = $this->returnDefault(); + $a->addGrantType(new OAuth2\Grant\ClientCredentials()); + + $v = $a->issueAccessToken(array( + 'grant_type' => 'client_credentials', + 'client_id' => 1234, + 'client_secret' => 5678 + )); + + $this->assertArrayHasKey('access_token', $v); + $this->assertArrayHasKey('token_type', $v); + $this->assertArrayHasKey('expires', $v); + $this->assertArrayHasKey('expires_in', $v); + $this->assertArrayHasKey('refresh_token', $v); + + $this->assertEquals($a::getExpiresIn(), $v['expires_in']); + $this->assertEquals(time()+$a::getExpiresIn(), $v['expires']); + } + + function test_issueAccessToken_clientCredentialsGrant() + { + $this->client->shouldReceive('getClient')->andReturn(array( + 'client_id' => 1234, + 'client_secret' => 5678, + 'redirect_uri' => 'http://foo/redirect', + 'name' => 'Example Client' + )); + + $this->client->shouldReceive('validateRefreshToken')->andReturn(1); + + $this->session->shouldReceive('validateAuthCode')->andReturn(1); + $this->session->shouldReceive('createSession')->andReturn(1); + $this->session->shouldReceive('deleteSession')->andReturn(null); + $this->session->shouldReceive('updateRefreshToken')->andReturn(null); + + $a = $this->returnDefault(); + $a->addGrantType(new OAuth2\Grant\ClientCredentials()); + + $_POST['grant_type'] = 'client_credentials'; + $_POST['client_id'] = 1234; + $_POST['client_secret'] = 5678; + + $request = new OAuth2\Request(array(), $_POST); + $a->setRequest($request); + + $v = $a->issueAccessToken(); + + $this->assertArrayHasKey('access_token', $v); + $this->assertArrayHasKey('token_type', $v); + $this->assertArrayHasKey('expires', $v); + $this->assertArrayHasKey('expires_in', $v); + $this->assertArrayHasKey('refresh_token', $v); + + $this->assertEquals($a::getExpiresIn(), $v['expires_in']); + $this->assertEquals(time()+$a::getExpiresIn(), $v['expires']); + } + public function tearDown() { M::close(); } From 920fd9344fcb3af0f35dfe68269f08dd3fe18550 Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Tue, 5 Feb 2013 15:55:04 +0000 Subject: [PATCH 075/113] Moved request class to util folder --- src/OAuth2/{ => Util}/Request.php | 2 +- src/OAuth2/{ => Util}/RequestInterface.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename src/OAuth2/{ => Util}/Request.php (99%) rename src/OAuth2/{ => Util}/RequestInterface.php (95%) diff --git a/src/OAuth2/Request.php b/src/OAuth2/Util/Request.php similarity index 99% rename from src/OAuth2/Request.php rename to src/OAuth2/Util/Request.php index 6c5c1742..0e47a1f7 100644 --- a/src/OAuth2/Request.php +++ b/src/OAuth2/Util/Request.php @@ -1,6 +1,6 @@ Date: Tue, 5 Feb 2013 15:55:38 +0000 Subject: [PATCH 076/113] Update request class namespace --- src/OAuth2/AuthServer.php | 3 ++- tests/authentication/AuthServerTest.php | 34 ++++++++++++------------- 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/src/OAuth2/AuthServer.php b/src/OAuth2/AuthServer.php index 19710b57..8bad1871 100644 --- a/src/OAuth2/AuthServer.php +++ b/src/OAuth2/AuthServer.php @@ -2,6 +2,7 @@ namespace OAuth2; +use OAuth2\Util\Request; use OAuth2\Util\SecureKey; use OAuth2\Storage\SessionInterface; use OAuth2\Storage\ClientInterface; @@ -122,7 +123,7 @@ class AuthServer * * @param RequestInterface The Request Object */ - public function setRequest(RequestInterface $request) + public function setRequest(Util\RequestInterface $request) { self::$request = $request; } diff --git a/tests/authentication/AuthServerTest.php b/tests/authentication/AuthServerTest.php index 54c29ab7..0ec7219d 100644 --- a/tests/authentication/AuthServerTest.php +++ b/tests/authentication/AuthServerTest.php @@ -101,7 +101,7 @@ class Authentication_Server_test extends PHPUnit_Framework_TestCase public function test_setRequest() { $a = $this->returnDefault(); - $request = new \OAuth2\Request(); + $request = new OAuth2\Util\Request(); $a->setRequest($request); $reflector = new ReflectionClass($a); @@ -109,17 +109,17 @@ class Authentication_Server_test extends PHPUnit_Framework_TestCase $requestProperty->setAccessible(true); $v = $requestProperty->getValue(); - $this->assertTrue($v instanceof OAuth2\RequestInterface); + $this->assertTrue($v instanceof OAuth2\Util\RequestInterface); } public function test_getRequest() { $a = $this->returnDefault(); - $request = new OAuth2\Request(); + $request = new OAuth2\Util\Request(); $a->setRequest($request); $v = $a::getRequest(); - $this->assertTrue($v instanceof OAuth2\RequestInterface); + $this->assertTrue($v instanceof OAuth2\Util\RequestInterface); } public function test_getStorage() @@ -327,7 +327,7 @@ class Authentication_Server_test extends PHPUnit_Framework_TestCase $_GET['response_type'] = 'code'; $_GET['scope'] = 'foo'; - $request = new OAuth2\Request($_GET); + $request = new OAuth2\Util\Request($_GET); $a->setRequest($request); $v = $a->checkAuthoriseParams(); @@ -581,7 +581,7 @@ class Authentication_Server_test extends PHPUnit_Framework_TestCase $_POST['redirect_uri'] = 'http://foo/redirect'; $_POST['code'] = 'foobar'; - $request = new OAuth2\Request(array(), $_POST); + $request = new OAuth2\Util\Request(array(), $_POST); $a->setRequest($request); $v = $a->issueAccessToken(); @@ -617,7 +617,7 @@ class Authentication_Server_test extends PHPUnit_Framework_TestCase $_POST['redirect_uri'] = 'http://foo/redirect'; $_POST['code'] = 'foobar'; - $request = new OAuth2\Request(array(), $_POST); + $request = new OAuth2\Util\Request(array(), $_POST); $a->setRequest($request); $v = $a->issueAccessToken(); @@ -641,7 +641,7 @@ class Authentication_Server_test extends PHPUnit_Framework_TestCase $a = $this->returnDefault(); $a->addGrantType(new OAuth2\Grant\RefreshToken()); - $request = new OAuth2\Request(array(), $_POST); + $request = new OAuth2\Util\Request(array(), $_POST); $a->setRequest($request); $v = $a->issueAccessToken(array( @@ -658,7 +658,7 @@ class Authentication_Server_test extends PHPUnit_Framework_TestCase $a = $this->returnDefault(); $a->addGrantType(new OAuth2\Grant\RefreshToken()); - $request = new OAuth2\Request(array(), $_POST); + $request = new OAuth2\Util\Request(array(), $_POST); $a->setRequest($request); $v = $a->issueAccessToken(array( @@ -678,7 +678,7 @@ class Authentication_Server_test extends PHPUnit_Framework_TestCase $a = $this->returnDefault(); $a->addGrantType(new OAuth2\Grant\RefreshToken()); - $request = new OAuth2\Request(array(), $_POST); + $request = new OAuth2\Util\Request(array(), $_POST); $a->setRequest($request); $v = $a->issueAccessToken(array( @@ -699,7 +699,7 @@ class Authentication_Server_test extends PHPUnit_Framework_TestCase $a = $this->returnDefault(); $a->addGrantType(new OAuth2\Grant\RefreshToken()); - $request = new OAuth2\Request(array(), $_POST); + $request = new OAuth2\Util\Request(array(), $_POST); $a->setRequest($request); $v = $a->issueAccessToken(array( @@ -722,7 +722,7 @@ class Authentication_Server_test extends PHPUnit_Framework_TestCase $a = $this->returnDefault(); $a->addGrantType(new OAuth2\Grant\RefreshToken()); - $request = new OAuth2\Request(array(), $_POST); + $request = new OAuth2\Util\Request(array(), $_POST); $a->setRequest($request); $v = $a->issueAccessToken(array( @@ -756,7 +756,7 @@ class Authentication_Server_test extends PHPUnit_Framework_TestCase $_POST['client_secret'] = 5678; $_POST['refresh_token'] = 'abcdef'; - $request = new OAuth2\Request(array(), $_POST); + $request = new OAuth2\Util\Request(array(), $_POST); $a->setRequest($request); $v = $a->issueAccessToken(); @@ -815,7 +815,7 @@ class Authentication_Server_test extends PHPUnit_Framework_TestCase $a = $this->returnDefault(); $a->addGrantType(new OAuth2\Grant\ClientCredentials()); - $request = new OAuth2\Request(array(), $_POST); + $request = new OAuth2\Util\Request(array(), $_POST); $a->setRequest($request); $v = $a->issueAccessToken(array( @@ -832,7 +832,7 @@ class Authentication_Server_test extends PHPUnit_Framework_TestCase $a = $this->returnDefault(); $a->addGrantType(new OAuth2\Grant\ClientCredentials()); - $request = new OAuth2\Request(array(), $_POST); + $request = new OAuth2\Util\Request(array(), $_POST); $a->setRequest($request); $v = $a->issueAccessToken(array( @@ -852,7 +852,7 @@ class Authentication_Server_test extends PHPUnit_Framework_TestCase $a = $this->returnDefault(); $a->addGrantType(new OAuth2\Grant\ClientCredentials()); - $request = new OAuth2\Request(array(), $_POST); + $request = new OAuth2\Util\Request(array(), $_POST); $a->setRequest($request); $v = $a->issueAccessToken(array( @@ -920,7 +920,7 @@ class Authentication_Server_test extends PHPUnit_Framework_TestCase $_POST['client_id'] = 1234; $_POST['client_secret'] = 5678; - $request = new OAuth2\Request(array(), $_POST); + $request = new OAuth2\Util\Request(array(), $_POST); $a->setRequest($request); $v = $a->issueAccessToken(); From daa352d12638888fdd37e8841b5a7df6ed01aec4 Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Tue, 5 Feb 2013 15:55:48 +0000 Subject: [PATCH 077/113] Added resource server tests --- build/phpunit.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/build/phpunit.xml b/build/phpunit.xml index 48e085c6..517c342a 100644 --- a/build/phpunit.xml +++ b/build/phpunit.xml @@ -4,6 +4,9 @@ ../tests/authentication + + ../tests/resource + ../tests/util From 6b4e51b3a36661f36cf87c36250525d1067b5113 Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Tue, 5 Feb 2013 15:56:03 +0000 Subject: [PATCH 078/113] Removed unnecessary interfaces --- src/OAuth2/Storage/ClientEndpointInterface.php | 8 -------- src/OAuth2/Storage/SessionScopeInterface.php | 8 -------- 2 files changed, 16 deletions(-) delete mode 100644 src/OAuth2/Storage/ClientEndpointInterface.php delete mode 100644 src/OAuth2/Storage/SessionScopeInterface.php diff --git a/src/OAuth2/Storage/ClientEndpointInterface.php b/src/OAuth2/Storage/ClientEndpointInterface.php deleted file mode 100644 index ae83eb93..00000000 --- a/src/OAuth2/Storage/ClientEndpointInterface.php +++ /dev/null @@ -1,8 +0,0 @@ - Date: Tue, 5 Feb 2013 15:57:24 +0000 Subject: [PATCH 079/113] Revert "Removed unnecessary code" This reverts commit c89a2346a84a7a1aabe9db7443cde04fc53e8a28. --- src/OAuth2/Util/Request.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/OAuth2/Util/Request.php b/src/OAuth2/Util/Request.php index 0e47a1f7..1b201057 100644 --- a/src/OAuth2/Util/Request.php +++ b/src/OAuth2/Util/Request.php @@ -67,8 +67,8 @@ class Request implements RequestInterface { $headers = array(); foreach ($this->server() as $name => $value) { - if (substr($name, 0, 5) === 'HTTP_') { - $name = str_replace(' ', '-', strtolower(str_replace('_', ' ', substr($name, 5)))); + if (substr($name, 0, 5) == 'HTTP_') { + $name = str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5))))); $headers[$name] = $value; } } From f481a9baeb29d7e2a18f1e87a80615efcfbf77a0 Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Tue, 5 Feb 2013 15:59:44 +0000 Subject: [PATCH 080/113] Bug fix --- tests/util/RequestTest.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/util/RequestTest.php b/tests/util/RequestTest.php index 91413204..dd4cd43e 100644 --- a/tests/util/RequestTest.php +++ b/tests/util/RequestTest.php @@ -6,7 +6,7 @@ class Request_test extends PHPUnit_Framework_TestCase function setUp() { - $this->request = new OAuth2\Request( + $this->request = new OAuth2\Util\Request( array('foo' => 'bar'), array('foo' => 'bar'), array('foo' => 'bar'), @@ -17,10 +17,10 @@ class Request_test extends PHPUnit_Framework_TestCase function test_buildFromIndex() { - $r = new OAuth2\Request(); + $r = new OAuth2\Util\Request(); $r->buildFromGlobals(); - $this->assertTrue($r instanceof OAuth2\Request); + $this->assertTrue($r instanceof OAuth2\Util\Request); } function test_get() @@ -55,8 +55,8 @@ class Request_test extends PHPUnit_Framework_TestCase function test_header() { - $this->assertEquals('foobar.com', $this->request->header('host')); - $this->assertEquals(array('host' => 'foobar.com'), $this->request->header()); + $this->assertEquals('foobar.com', $this->request->header('Host')); + $this->assertEquals(array('Host' => 'foobar.com'), $this->request->header()); } /** From 562c257596da7c316d6333574974f9b736f737f2 Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Tue, 5 Feb 2013 16:20:45 +0000 Subject: [PATCH 081/113] Various bug fixes --- src/OAuth2/ResourceServer.php | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/OAuth2/ResourceServer.php b/src/OAuth2/ResourceServer.php index ba0d6801..2da1103c 100644 --- a/src/OAuth2/ResourceServer.php +++ b/src/OAuth2/ResourceServer.php @@ -5,6 +5,7 @@ namespace OAuth2; use OutOfBoundsException; use OAuth2\Storage\SessionInterface; use OAuth2\Storage\SessionScopeInterface; +use OAuth2\Util\RequestInterface; class ResourceServer { @@ -30,10 +31,9 @@ class ResourceServer * @param SessionInterface The Session Storage Object * @param SessionScopeInterface The Session Scope Storage Object */ - public function __construct(SessionInterface $session, SessionScopeInterface $session_scope) + public function __construct(SessionInterface $session) { $this->storages['session'] = $session; - $this->storages['session_scope'] = $session_scope; } /** @@ -54,12 +54,24 @@ class ResourceServer public function getRequest() { if ($this->request === null) { + // @codeCoverageIgnoreStart $this->request = Request::buildFromGlobals(); } + // @codeCoverageIgnoreEnd return $this->request; } + public function getTokenKey() + { + return $this->tokenKey; + } + + public function setTokenKey($key) + { + $this->tokenKey = $key; + } + /** * Gets the Owner ID. * @@ -77,7 +89,7 @@ class ResourceServer */ public function getOwnerType() { - return $this->ownerId; + return $this->ownerType; } /** @@ -110,7 +122,7 @@ class ResourceServer $this->ownerType = $result['owner_type']; $this->ownerId = $result['owner_id']; - $this->sessionScopes = $this->storages['session_scope']->getScopes($this->sessionId); + $this->sessionScopes = $this->storages['session']->getScopes($this->sessionId); return true; } From 37331c4dc84a9a1c75d9eb1ebbb1257bb77ab797 Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Tue, 5 Feb 2013 16:20:56 +0000 Subject: [PATCH 082/113] Added resource server tests --- tests/resource/ResourceServerTest.php | 159 ++++++++++++++++++++++++++ 1 file changed, 159 insertions(+) create mode 100644 tests/resource/ResourceServerTest.php diff --git a/tests/resource/ResourceServerTest.php b/tests/resource/ResourceServerTest.php new file mode 100644 index 00000000..5f7361f7 --- /dev/null +++ b/tests/resource/ResourceServerTest.php @@ -0,0 +1,159 @@ +client = M::mock('OAuth2\Storage\ClientInterface'); + $this->session = M::mock('OAuth2\Storage\SessionInterface'); + //$this->scope = M::mock('OAuth2\Storage\ScopeInterface'); + } + + private function returnDefault() + { + return new OAuth2\ResourceServer($this->session); + } + + public function test_setRequest() + { + $s = $this->returnDefault(); + $request = new OAuth2\Util\Request(); + $s->setRequest($request); + + $reflector = new ReflectionClass($s); + $requestProperty = $reflector->getProperty('request'); + $requestProperty->setAccessible(true); + $v = $requestProperty->getValue($s); + + $this->assertTrue($v instanceof OAuth2\Util\RequestInterface); + } + + public function test_getRequest() + { + $s = $this->returnDefault(); + $request = new OAuth2\Util\Request(); + $s->setRequest($request); + $v = $s->getRequest(); + + $this->assertTrue($v instanceof OAuth2\Util\RequestInterface); + } + + public function test_getTokenKey() + { + $s = $this->returnDefault(); + $this->assertEquals('oauth_token', $s->getTokenKey()); + } + + public function test_setTokenKey() + { + $s = $this->returnDefault(); + $s->setTokenKey('access_token'); + + $reflector = new ReflectionClass($s); + $requestProperty = $reflector->getProperty('tokenKey'); + $requestProperty->setAccessible(true); + $v = $requestProperty->getValue($s); + + $this->assertEquals('access_token', $v); + } + + /** + * @expectedException OAuth2\Exception\MissingAccessTokenException + */ + public function test_determineAccessToken_missingToken() + { + $_SERVER['HTTP_AUTHORIZATION'] = 'Bearer'; + $request = new OAuth2\Util\Request(array(), array(), array(), array(), $_SERVER); + + $s = $this->returnDefault(); + $s->setRequest($request); + + $reflector = new ReflectionClass($s); + $method = $reflector->getMethod('determineAccessToken'); + $method->setAccessible(true); + + $result = $method->invoke($s); + } + + public function test_determineAccessToken_fromHeader() + { + $_SERVER['HTTP_AUTHORIZATION'] = 'Bearer abcdef'; + $request = new OAuth2\Util\Request(array(), array(), array(), array(), $_SERVER); + + $s = $this->returnDefault(); + $s->setRequest($request); + + $reflector = new ReflectionClass($s); + $method = $reflector->getMethod('determineAccessToken'); + $method->setAccessible(true); + + $result = $method->invoke($s); + + $this->assertEquals('abcdef', $result); + } + + public function test_determineAccessToken_fromMethod() + { + $s = $this->returnDefault(); + + $_GET[$s->getTokenKey()] = 'abcdef'; + $_SERVER['REQUEST_METHOD'] = 'get'; + + $request = new OAuth2\Util\Request($_GET, array(), array(), array(), $_SERVER); + $s->setRequest($request); + + $reflector = new ReflectionClass($s); + $method = $reflector->getMethod('determineAccessToken'); + $method->setAccessible(true); + + $result = $method->invoke($s); + + $this->assertEquals('abcdef', $result); + } + + public function test_isValid_notValid() + { + $this->session->shouldReceive('validateAccessToken')->andReturn(false); + + $_SERVER['HTTP_AUTHORIZATION'] = 'Bearer abcdef'; + $request = new OAuth2\Util\Request(array(), array(), array(), array(), $_SERVER); + + $s = $this->returnDefault(); + $s->setRequest($request); + + $this->assertFalse($s->isValid()); + } + + public function test_isValid_valid() + { + $this->session->shouldReceive('validateAccessToken')->andReturn(array( + 'id' => 1, + 'owner_type' => 'user', + 'owner_id' => 123 + )); + $this->session->shouldReceive('getScopes')->andReturn(array('foo', 'bar')); + + $_SERVER['HTTP_AUTHORIZATION'] = 'Bearer abcdef'; + $request = new OAuth2\Util\Request(array(), array(), array(), array(), $_SERVER); + + $s = $this->returnDefault(); + $s->setRequest($request); + + $this->assertTrue($s->isValid()); + $this->assertEquals(123, $s->getOwnerId()); + $this->assertEquals('user', $s->getOwnerType()); + $this->assertEquals('abcdef', $s->getAccessToken()); + $this->assertTrue($s->hasScope('foo')); + $this->assertTrue($s->hasScope('bar')); + $this->assertTrue($s->hasScope(array('foo', 'bar'))); + $this->assertFalse($s->hasScope(array('foobar'))); + $this->assertFalse($s->hasScope('foobar')); + $this->assertFalse($s->hasScope(new StdClass)); + } +} \ No newline at end of file From 49e0088f7273abc2432c4805a42f70289de73259 Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Tue, 5 Feb 2013 16:26:55 +0000 Subject: [PATCH 083/113] Removed old unit tests --- tests/resource/database_mock.php | 31 -------- tests/resource/server_test.php | 121 ------------------------------- 2 files changed, 152 deletions(-) delete mode 100644 tests/resource/database_mock.php delete mode 100644 tests/resource/server_test.php diff --git a/tests/resource/database_mock.php b/tests/resource/database_mock.php deleted file mode 100644 index 39469bac..00000000 --- a/tests/resource/database_mock.php +++ /dev/null @@ -1,31 +0,0 @@ - array( - 'id' => 1, - 'owner_type' => 'user', - 'owner_id' => 123 - ) - ); - - private $sessionScopes = array( - 1 => array( - 'foo', - 'bar' - ) - ); - - public function validateAccessToken($accessToken) - { - return (isset($this->accessTokens[$accessToken])) ? $this->accessTokens[$accessToken] : false; - } - - public function sessionScopes($sessionId) - { - return (isset($this->sessionScopes[$sessionId])) ? $this->sessionScopes[$sessionId] : array(); - } -} \ No newline at end of file diff --git a/tests/resource/server_test.php b/tests/resource/server_test.php deleted file mode 100644 index b5710077..00000000 --- a/tests/resource/server_test.php +++ /dev/null @@ -1,121 +0,0 @@ -server = new OAuth2\Resource\Server(); - $this->db = new ResourceDB(); - - $this->assertInstanceOf('OAuth2\Resource\Database', $this->db); - $this->server->registerDbAbstractor($this->db); - } - - function test_init_POST() - { - $_SERVER['REQUEST_METHOD'] = 'POST'; - $_POST['oauth_token'] = 'test12345'; - - $this->server->init(); - - $reflector = new ReflectionClass($this->server); - - $_accessToken = $reflector->getProperty('_accessToken'); - $_accessToken->setAccessible(true); - - $_type = $reflector->getProperty('_type'); - $_type->setAccessible(true); - - $_typeId = $reflector->getProperty('_typeId'); - $_typeId->setAccessible(true); - - $_scopes = $reflector->getProperty('_scopes'); - $_scopes->setAccessible(true); - - $this->assertEquals($_accessToken->getValue($this->server), $_POST['oauth_token']); - $this->assertEquals($_type->getValue($this->server), 'user'); - $this->assertEquals($_typeId->getValue($this->server), 123); - $this->assertEquals($_scopes->getValue($this->server), array('foo', 'bar')); - } - - function test_init_GET() - { - $_GET['oauth_token'] = 'test12345'; - - $this->server->init(); - - $reflector = new ReflectionClass($this->server); - - $_accessToken = $reflector->getProperty('_accessToken'); - $_accessToken->setAccessible(true); - - $_type = $reflector->getProperty('_type'); - $_type->setAccessible(true); - - $_typeId = $reflector->getProperty('_typeId'); - $_typeId->setAccessible(true); - - $_scopes = $reflector->getProperty('_scopes'); - $_scopes->setAccessible(true); - - $this->assertEquals($_accessToken->getValue($this->server), $_GET['oauth_token']); - $this->assertEquals($_type->getValue($this->server), 'user'); - $this->assertEquals($_typeId->getValue($this->server), 123); - $this->assertEquals($_scopes->getValue($this->server), array('foo', 'bar')); - } - - function test_init_header() - { - // Test with authorisation header - $this->markTestIncomplete('Authorisation header test has not been implemented yet.'); - } - - /** - * @expectedException \OAuth2\Resource\ClientException - * @expectedExceptionMessage An access token was not presented with the request - */ - function test_init_missingToken() - { - $this->server->init(); - } - - /** - * @expectedException \OAuth2\Resource\ClientException - * @expectedExceptionMessage The access token is not registered with the resource server - */ - function test_init_wrongToken() - { - $_POST['oauth_token'] = 'blah'; - $_SERVER['REQUEST_METHOD'] = 'POST'; - - $this->server->init(); - } - - function test_hasScope() - { - $_POST['oauth_token'] = 'test12345'; - $_SERVER['REQUEST_METHOD'] = 'POST'; - - $this->server->init(); - - $this->assertEquals(true, $this->server->hasScope('foo')); - $this->assertEquals(true, $this->server->hasScope('bar')); - $this->assertEquals(true, $this->server->hasScope(array('foo', 'bar'))); - - $this->assertEquals(false, $this->server->hasScope('foobar')); - $this->assertEquals(false, $this->server->hasScope(array('foobar'))); - } - - function test___call() - { - $_POST['oauth_token'] = 'test12345'; - $_SERVER['REQUEST_METHOD'] = 'POST'; - - $this->server->init(); - - $this->assertEquals(123, $this->server->isUser()); - $this->assertEquals(false, $this->server->isMachine()); - } - -} \ No newline at end of file From 55d68bd10533e1abab3c9dd82b9385fcea78326d Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Thu, 7 Feb 2013 14:54:56 +0000 Subject: [PATCH 084/113] Import namespace for util\request --- src/OAuth2/ResourceServer.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/OAuth2/ResourceServer.php b/src/OAuth2/ResourceServer.php index 2da1103c..2f7ef991 100644 --- a/src/OAuth2/ResourceServer.php +++ b/src/OAuth2/ResourceServer.php @@ -6,6 +6,7 @@ use OutOfBoundsException; use OAuth2\Storage\SessionInterface; use OAuth2\Storage\SessionScopeInterface; use OAuth2\Util\RequestInterface; +use OAuth2\Util\Request; class ResourceServer { From 89f3c35466bebf187837d9c619b976871c516a48 Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Thu, 7 Feb 2013 16:16:09 +0000 Subject: [PATCH 085/113] Authorization header fixes --- src/OAuth2/ResourceServer.php | 2 +- src/OAuth2/Util/Request.php | 16 ++++++++++------ 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/OAuth2/ResourceServer.php b/src/OAuth2/ResourceServer.php index 2f7ef991..6bf3578c 100644 --- a/src/OAuth2/ResourceServer.php +++ b/src/OAuth2/ResourceServer.php @@ -161,7 +161,7 @@ class ResourceServer protected function determineAccessToken() { if ($header = $this->getRequest()->header('Authorization')) { - $access_token = trim(str_replace('Bearer', '', $header)); + $access_token = base64_decode(trim(str_replace('Bearer', '', $header))); } else { $method = $this->getRequest()->server('REQUEST_METHOD'); $access_token = $this->getRequest()->{$method}($this->tokenKey); diff --git a/src/OAuth2/Util/Request.php b/src/OAuth2/Util/Request.php index 1b201057..eefe37d0 100644 --- a/src/OAuth2/Util/Request.php +++ b/src/OAuth2/Util/Request.php @@ -65,11 +65,15 @@ class Request implements RequestInterface 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; + if (function_exists('getallheaders')) { + $headers = getallheaders(); + } else { + $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; + } } } @@ -91,4 +95,4 @@ class Request implements RequestInterface return $this->{$property}[$index]; } -} +} \ No newline at end of file From 60b2caf41d41491d28c7f8a07a9d403a687c082d Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Fri, 8 Feb 2013 11:40:33 +0000 Subject: [PATCH 086/113] Various fixes and tweaks --- src/OAuth2/ResourceServer.php | 2 +- src/OAuth2/Util/Request.php | 2 ++ tests/resource/ResourceServerTest.php | 48 ++++++++++++++++----------- 3 files changed, 32 insertions(+), 20 deletions(-) diff --git a/src/OAuth2/ResourceServer.php b/src/OAuth2/ResourceServer.php index 6bf3578c..f48a19f8 100644 --- a/src/OAuth2/ResourceServer.php +++ b/src/OAuth2/ResourceServer.php @@ -168,7 +168,7 @@ class ResourceServer } if (empty($access_token)) { - throw new Exception\MissingAccessTokenException('Access Token is Missing'); + throw new Exception\InvalidAccessTokenException('Access token is missing'); } return $access_token; diff --git a/src/OAuth2/Util/Request.php b/src/OAuth2/Util/Request.php index eefe37d0..ccb19dac 100644 --- a/src/OAuth2/Util/Request.php +++ b/src/OAuth2/Util/Request.php @@ -66,8 +66,10 @@ class Request implements RequestInterface protected function readHeaders() { if (function_exists('getallheaders')) { + // @codeCoverageIgnoreStart $headers = getallheaders(); } else { + // @codeCoverageIgnoreEnd $headers = array(); foreach ($this->server() as $name => $value) { if (substr($name, 0, 5) == 'HTTP_') { diff --git a/tests/resource/ResourceServerTest.php b/tests/resource/ResourceServerTest.php index 5f7361f7..3da9a991 100644 --- a/tests/resource/ResourceServerTest.php +++ b/tests/resource/ResourceServerTest.php @@ -4,15 +4,11 @@ use \Mockery as m; class Resource_Server_test extends PHPUnit_Framework_TestCase { - private $client; private $session; - private $scope; public function setUp() { - $this->client = M::mock('OAuth2\Storage\ClientInterface'); $this->session = M::mock('OAuth2\Storage\SessionInterface'); - //$this->scope = M::mock('OAuth2\Storage\ScopeInterface'); } private function returnDefault() @@ -64,7 +60,7 @@ class Resource_Server_test extends PHPUnit_Framework_TestCase } /** - * @expectedException OAuth2\Exception\MissingAccessTokenException + * @expectedException OAuth2\Exception\InvalidAccessTokenException */ public function test_determineAccessToken_missingToken() { @@ -83,13 +79,19 @@ class Resource_Server_test extends PHPUnit_Framework_TestCase public function test_determineAccessToken_fromHeader() { - $_SERVER['HTTP_AUTHORIZATION'] = 'Bearer abcdef'; - $request = new OAuth2\Util\Request(array(), array(), array(), array(), $_SERVER); + $request = new OAuth2\Util\Request(); - $s = $this->returnDefault(); - $s->setRequest($request); + $requestReflector = new ReflectionClass($request); + $param = $requestReflector->getProperty('headers'); + $param->setAccessible(true); + $param->setValue($request, array( + 'Authorization' => 'Bearer YWJjZGVm' + )); + $s = $this->returnDefault(); + $s->setRequest($request); $reflector = new ReflectionClass($s); + $method = $reflector->getMethod('determineAccessToken'); $method->setAccessible(true); @@ -121,11 +123,15 @@ class Resource_Server_test extends PHPUnit_Framework_TestCase { $this->session->shouldReceive('validateAccessToken')->andReturn(false); - $_SERVER['HTTP_AUTHORIZATION'] = 'Bearer abcdef'; - $request = new OAuth2\Util\Request(array(), array(), array(), array(), $_SERVER); - - $s = $this->returnDefault(); - $s->setRequest($request); + $request = new OAuth2\Util\Request(); + $requestReflector = new ReflectionClass($request); + $param = $requestReflector->getProperty('headers'); + $param->setAccessible(true); + $param->setValue($request, array( + 'Authorization' => 'Bearer YWJjZGVm' + )); + $s = $this->returnDefault(); + $s->setRequest($request); $this->assertFalse($s->isValid()); } @@ -139,11 +145,15 @@ class Resource_Server_test extends PHPUnit_Framework_TestCase )); $this->session->shouldReceive('getScopes')->andReturn(array('foo', 'bar')); - $_SERVER['HTTP_AUTHORIZATION'] = 'Bearer abcdef'; - $request = new OAuth2\Util\Request(array(), array(), array(), array(), $_SERVER); - - $s = $this->returnDefault(); - $s->setRequest($request); + $request = new OAuth2\Util\Request(); + $requestReflector = new ReflectionClass($request); + $param = $requestReflector->getProperty('headers'); + $param->setAccessible(true); + $param->setValue($request, array( + 'Authorization' => 'Bearer YWJjZGVm' + )); + $s = $this->returnDefault(); + $s->setRequest($request); $this->assertTrue($s->isValid()); $this->assertEquals(123, $s->getOwnerId()); From e76111c2b7a1f1b7c78824fbd917a5f0aab5d502 Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Fri, 8 Feb 2013 11:45:51 +0000 Subject: [PATCH 087/113] Fixed silliness with access token verification --- src/OAuth2/Exception/InvalidAccessTokenException.php | 8 ++++++++ src/OAuth2/Exception/MissingAccessTokenException.php | 8 -------- src/OAuth2/ResourceServer.php | 2 +- tests/resource/ResourceServerTest.php | 7 +++++-- 4 files changed, 14 insertions(+), 11 deletions(-) create mode 100644 src/OAuth2/Exception/InvalidAccessTokenException.php delete mode 100644 src/OAuth2/Exception/MissingAccessTokenException.php diff --git a/src/OAuth2/Exception/InvalidAccessTokenException.php b/src/OAuth2/Exception/InvalidAccessTokenException.php new file mode 100644 index 00000000..a7240992 --- /dev/null +++ b/src/OAuth2/Exception/InvalidAccessTokenException.php @@ -0,0 +1,8 @@ +storages['session']->validateAccessToken($access_token); if ( ! $result) { - return false; + throw new Exception\InvalidAccessTokenException('Access token is not valid'); } $this->accessToken = $access_token; diff --git a/tests/resource/ResourceServerTest.php b/tests/resource/ResourceServerTest.php index 3da9a991..b8fed73e 100644 --- a/tests/resource/ResourceServerTest.php +++ b/tests/resource/ResourceServerTest.php @@ -60,7 +60,7 @@ class Resource_Server_test extends PHPUnit_Framework_TestCase } /** - * @expectedException OAuth2\Exception\InvalidAccessTokenException + * @expectedException OAuth2\Exception\InvalidAccessTokenException */ public function test_determineAccessToken_missingToken() { @@ -119,6 +119,9 @@ class Resource_Server_test extends PHPUnit_Framework_TestCase $this->assertEquals('abcdef', $result); } + /** + * @expectedException OAuth2\Exception\InvalidAccessTokenException + */ public function test_isValid_notValid() { $this->session->shouldReceive('validateAccessToken')->andReturn(false); @@ -133,7 +136,7 @@ class Resource_Server_test extends PHPUnit_Framework_TestCase $s = $this->returnDefault(); $s->setRequest($request); - $this->assertFalse($s->isValid()); + $s->isValid(); } public function test_isValid_valid() From 87186d73b7d3b04cb9bd568eb5a203a4a838a663 Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Tue, 12 Feb 2013 16:01:02 +0000 Subject: [PATCH 088/113] Removed old client code which can be now be found at lncd/oauth2-client --- src/OAuth2/Client/IDP.php | 230 --------------------- src/OAuth2/Client/Provider.php | 19 -- src/OAuth2/Client/Provider/Blooie.php | 42 ---- src/OAuth2/Client/Provider/Facebook.php | 49 ----- src/OAuth2/Client/Provider/Foursquare.php | 45 ---- src/OAuth2/Client/Provider/Github.php | 43 ---- src/OAuth2/Client/Provider/Google.php | 84 -------- src/OAuth2/Client/Provider/Instagram.php | 48 ----- src/OAuth2/Client/Provider/Mailchimp.php | 36 ---- src/OAuth2/Client/Provider/Mailru.php | 73 ------- src/OAuth2/Client/Provider/Paypal.php | 59 ------ src/OAuth2/Client/Provider/Soundcloud.php | 51 ----- src/OAuth2/Client/Provider/Vkontakte.php | 54 ----- src/OAuth2/Client/Provider/Windowslive.php | 60 ------ src/OAuth2/Client/Provider/Yandex.php | 115 ----------- src/OAuth2/Client/Token.php | 46 ----- src/OAuth2/Client/Token/Access.php | 79 ------- src/OAuth2/Client/Token/Authorize.php | 55 ----- 18 files changed, 1188 deletions(-) delete mode 100644 src/OAuth2/Client/IDP.php delete mode 100755 src/OAuth2/Client/Provider.php delete mode 100755 src/OAuth2/Client/Provider/Blooie.php delete mode 100755 src/OAuth2/Client/Provider/Facebook.php delete mode 100755 src/OAuth2/Client/Provider/Foursquare.php delete mode 100755 src/OAuth2/Client/Provider/Github.php delete mode 100755 src/OAuth2/Client/Provider/Google.php delete mode 100755 src/OAuth2/Client/Provider/Instagram.php delete mode 100755 src/OAuth2/Client/Provider/Mailchimp.php delete mode 100755 src/OAuth2/Client/Provider/Mailru.php delete mode 100755 src/OAuth2/Client/Provider/Paypal.php delete mode 100755 src/OAuth2/Client/Provider/Soundcloud.php delete mode 100755 src/OAuth2/Client/Provider/Vkontakte.php delete mode 100755 src/OAuth2/Client/Provider/Windowslive.php delete mode 100755 src/OAuth2/Client/Provider/Yandex.php delete mode 100755 src/OAuth2/Client/Token.php delete mode 100755 src/OAuth2/Client/Token/Access.php delete mode 100755 src/OAuth2/Client/Token/Authorize.php diff --git a/src/OAuth2/Client/IDP.php b/src/OAuth2/Client/IDP.php deleted file mode 100644 index 092da0e6..00000000 --- a/src/OAuth2/Client/IDP.php +++ /dev/null @@ -1,230 +0,0 @@ -result = $result; - - $code = isset($result['code']) ? $result['code'] : 0; - - if (isset($result['error'])) { - - // OAuth 2.0 Draft 10 style - $message = $result['error']; - - } elseif (isset($result['message'])) { - - // cURL style - $message = $result['message']; - - } else { - - $message = 'Unknown Error.'; - - } - - parent::__construct($message['message'], $message['code']); - } - - public function getType() - { - if (isset($this->result['error'])) { - - $message = $this->result['error']; - - if (is_string($message)) { - // OAuth 2.0 Draft 10 style - return $message; - } - } - - return 'Exception'; - } - - /** - * To make debugging easier. - * - * @returns - * The string representation of the error. - */ - public function __toString() - { - $str = $this->getType() . ': '; - - if ($this->code != 0) { - $str .= $this->code . ': '; - } - - return $str . $this->message; - } - -} - -abstract class IDP { - - public $clientId = ''; - - public $clientSecret = ''; - - public $redirectUri = ''; - - public $name; - - public $uidKey = 'uid'; - - public $scopes = array(); - - public $method = 'post'; - - public $scopeSeperator = ','; - - public $responseType = 'json'; - - public function __construct($options) - { - foreach ($options as $option => $value) { - if (isset($this->{$option})) { - $this->{$option} = $value; - } - } - } - - abstract public function urlAuthorize(); - - abstract public function urlAccessToken(); - - abstract public function urlUserDetails(\OAuth2\Client\Token\Access $token); - - abstract public function userDetails($response, \OAuth2\Client\Token\Access $token); - - public function authorize($options = array()) - { - $state = md5(uniqid(rand(), TRUE)); - setcookie($this->name.'_authorize_state', $state); - - $params = array( - 'client_id' => $this->clientId, - 'redirect_uri' => $this->redirectUri, - 'state' => $state, - 'scope' => is_array($this->scope) ? implode($this->scopeSeperator, $this->scope) : $this->scope, - 'response_type' => isset($options['response_type']) ? $options['response_type'] : 'code', - 'approval_prompt' => 'force' // - google force-recheck - ); - - header('Location: ' . $this->urlAuthorize().'?'.http_build_query($params)); - exit; - } - - public function getAccessToken($code = NULL, $options = array()) - { - if ($code === NULL) { - throw new \BadMethodCallException('Missing authorization code'); - } - - $params = array( - 'client_id' => $this->clientId, - 'client_secret' => $this->clientSecret, - 'grant_type' => isset($options['grantType']) ? $options['grantType'] : 'authorization_code', - ); - - switch ($params['grant_type']) { - - case 'authorization_code': - $params['code'] = $code; - $params['redirect_uri'] = isset($options['redirectUri']) ? $options['redirectUri'] : $this->redirectUri; - break; - - case 'refresh_token': - $params['refresh_token'] = $code; - break; - - } - - try { - - switch ($this->method) { - - case 'get': - - $client = new GuzzleClient($this->urlAccessToken() . '?' . http_build_query($params)); - $request = $client->send(); - $response = $request->getBody(); - - break; - - case 'post': - - $client = new GuzzleClient($this->urlAccessToken()); - $request = $client->post(null, null, $params)->send(); - $response = $request->getBody(); - - break; - - } - - } - - catch (\Guzzle\Http\Exception\BadResponseException $e) - { - $raw_response = explode("\n", $e->getResponse()); - $response = end($raw_response); - } - - switch ($this->responseType) { - - case 'json': - $result = json_decode($response, true); - break; - - case 'string': - parse_str($response, $result); - break; - - } - - if (isset($result['error']) && ! empty($result['error'])) { - - throw new \OAuth2\Client\IDPException($result); - - } - - switch ($params['grant_type']) { - - case 'authorization_code': - return \OAuth2\Client\Token::factory('access', $result); - break; - - case 'refresh_token': - return \OAuth2\Client\Token::factory('refresh', $result); - break; - - } - } - - public function getUserDetails(\OAuth2\Client\Token\Access $token) - { - $url = $this->urlUserDetails($token); - - try { - $client = new GuzzleClient($url); - $request = $client->get()->send(); - $response = $request->getBody(); - - return $this->userDetails(json_decode($response), $token); - } - - catch (\Guzzle\Http\Exception\BadResponseException $e) - { - $raw_response = explode("\n", $e->getResponse()); - throw new \OAuth2\Client\IDPException(end($raw_response)); - } - } - -} \ No newline at end of file diff --git a/src/OAuth2/Client/Provider.php b/src/OAuth2/Client/Provider.php deleted file mode 100755 index 0762d57e..00000000 --- a/src/OAuth2/Client/Provider.php +++ /dev/null @@ -1,19 +0,0 @@ - $token->access_token, - )); - - $user = json_decode(file_get_contents($url)); - - return array( - 'uid' => $user->id, - 'nickname' => $user->username, - 'name' => $user->name, - 'first_name' => $user->first_name, - 'last_name' => $user->last_name, - 'email' => isset($user->email) ? $user->email : null, - 'location' => isset($user->hometown->name) ? $user->hometown->name : null, - 'description' => isset($user->bio) ? $user->bio : null, - 'image' => 'https://graph.facebook.com/me/picture?type=normal&access_token='.$token->access_token, - 'urls' => array( - 'Facebook' => $user->link, - ), - ); - } -} diff --git a/src/OAuth2/Client/Provider/Facebook.php b/src/OAuth2/Client/Provider/Facebook.php deleted file mode 100755 index cd41be17..00000000 --- a/src/OAuth2/Client/Provider/Facebook.php +++ /dev/null @@ -1,49 +0,0 @@ - $token->access_token, - )); - - $user = json_decode(file_get_contents($url)); - - return array( - 'uid' => $user->id, - 'nickname' => isset($user->username) ? $user->username : null, - 'name' => $user->name, - 'first_name' => $user->first_name, - 'last_name' => $user->last_name, - 'email' => isset($user->email) ? $user->email : null, - 'location' => isset($user->hometown->name) ? $user->hometown->name : null, - 'description' => isset($user->bio) ? $user->bio : null, - 'image' => 'https://graph.facebook.com/me/picture?type=normal&access_token='.$token->access_token, - 'urls' => array( - 'Facebook' => $user->link, - ), - ); - } -} diff --git a/src/OAuth2/Client/Provider/Foursquare.php b/src/OAuth2/Client/Provider/Foursquare.php deleted file mode 100755 index 1c2740f8..00000000 --- a/src/OAuth2/Client/Provider/Foursquare.php +++ /dev/null @@ -1,45 +0,0 @@ - $token->access_token, - )); - - $response = json_decode(file_get_contents($url)); - - $user = $response->response->user; - - // Create a response from the request - return array( - 'uid' => $user->id, - 'name' => sprintf('%s %s', $user->firstName, $user->lastName), - 'email' => $user->contact->email, - 'image' => $user->photo, - 'location' => $user->homeCity, - ); - } -} \ No newline at end of file diff --git a/src/OAuth2/Client/Provider/Github.php b/src/OAuth2/Client/Provider/Github.php deleted file mode 100755 index 5ca9b512..00000000 --- a/src/OAuth2/Client/Provider/Github.php +++ /dev/null @@ -1,43 +0,0 @@ - $token->access_token, - )); - - $user = json_decode(file_get_contents($url)); - - return array( - 'uid' => $user->id, - 'nickname' => $user->login, - 'name' => $user->name, - 'email' => $user->email, - 'urls' => array( - 'GitHub' => 'http://github.com/'.$user->login, - 'Blog' => $user->blog, - ), - ); - } -} \ No newline at end of file diff --git a/src/OAuth2/Client/Provider/Google.php b/src/OAuth2/Client/Provider/Google.php deleted file mode 100755 index b76d343b..00000000 --- a/src/OAuth2/Client/Provider/Google.php +++ /dev/null @@ -1,84 +0,0 @@ - 'Expected Authorization Code from '.ucfirst($this->name).' is missing')); - } - - return parent::access($code, $options); - } - - public function get_user_info(OAuth2_Token_Access $token) - { - $url = 'https://www.googleapis.com/oauth2/v1/userinfo?alt=json&'.http_build_query(array( - 'access_token' => $token->access_token, - )); - - $user = json_decode(file_get_contents($url), true); - return array( - 'uid' => $user['id'], - 'nickname' => url_title($user['name'], '_', true), - 'name' => $user['name'], - 'first_name' => $user['given_name'], - 'last_name' => $user['family_name'], - 'email' => $user['email'], - 'location' => null, - 'image' => (isset($user['picture'])) ? $user['picture'] : null, - 'description' => null, - 'urls' => array(), - ); - } -} diff --git a/src/OAuth2/Client/Provider/Instagram.php b/src/OAuth2/Client/Provider/Instagram.php deleted file mode 100755 index 39c8bef1..00000000 --- a/src/OAuth2/Client/Provider/Instagram.php +++ /dev/null @@ -1,48 +0,0 @@ -user; - - return array( - 'uid' => $user->id, - 'nickname' => $user->username, - 'name' => $user->full_name, - 'image' => $user->profile_picture, - 'urls' => array( - 'website' => $user->website, - ), - ); - } -} \ No newline at end of file diff --git a/src/OAuth2/Client/Provider/Mailchimp.php b/src/OAuth2/Client/Provider/Mailchimp.php deleted file mode 100755 index 818bd40d..00000000 --- a/src/OAuth2/Client/Provider/Mailchimp.php +++ /dev/null @@ -1,36 +0,0 @@ - $token->access_token, - ); - } -} diff --git a/src/OAuth2/Client/Provider/Mailru.php b/src/OAuth2/Client/Provider/Mailru.php deleted file mode 100755 index 25234a20..00000000 --- a/src/OAuth2/Client/Provider/Mailru.php +++ /dev/null @@ -1,73 +0,0 @@ - $value) { - $params .= "$key=$value"; - } - return md5($params . $secret_key); - } - - public function get_user_info(OAuth2_Token_Access $token) - { - $request_params = array( - 'app_id' => $this->client_id, - 'method' => 'users.getInfo', - 'uids' => $token->uid, - 'access_token' => $token->access_token, - 'secure' => 1 - ); - - $sig = $this->sign_server_server($request_params,$this->client_secret); - $url = 'http://www.appsmail.ru/platform/api?'.http_build_query($request_params).'&sig='.$sig; - - $user = json_decode(file_get_contents($url)); - - return array( - 'uid' => $user[0]->uid, - 'nickname' => $user[0]->nick, - 'name' => $user[0]->first_name.' '.$user[0]->last_name, - 'first_name' => $user[0]->first_name, - 'last_name' => $user[0]->last_name, - 'email' => isset($user[0]->email) ? $user[0]->email : null, - 'image' => isset($user[0]->pic_big) ? $user[0]->pic_big : null, - ); - } - - public function authorize($options = array()) - { - $state = md5(uniqid(rand(), TRUE)); - get_instance()->session->set_userdata('state', $state); - - $params = array( - 'client_id' => $this->client_id, - 'redirect_uri' => isset($options['redirect_uri']) ? $options['redirect_uri'] : $this->redirect_uri, - 'response_type' => 'code', - ); - - redirect($this->url_authorize().'?'.http_build_query($params)); - } -} diff --git a/src/OAuth2/Client/Provider/Paypal.php b/src/OAuth2/Client/Provider/Paypal.php deleted file mode 100755 index 72d065fe..00000000 --- a/src/OAuth2/Client/Provider/Paypal.php +++ /dev/null @@ -1,59 +0,0 @@ - $token->access_token - )); - - $user = json_decode(file_get_contents($url)); - $user = $user->identity; - - return array( - 'uid' => $user['userId'], - 'nickname' => url_title($user['fullName'], '_', true), - 'name' => $user['fullName'], - 'first_name' => $user['firstName'], - 'last_name' => $user['lastName'], - 'email' => $user['emails'][0], - 'location' => $user->addresses[0], - 'image' => null, - 'description' => null, - 'urls' => array( - 'PayPal' => null - ) - ); - } - -} diff --git a/src/OAuth2/Client/Provider/Soundcloud.php b/src/OAuth2/Client/Provider/Soundcloud.php deleted file mode 100755 index 83d9afbc..00000000 --- a/src/OAuth2/Client/Provider/Soundcloud.php +++ /dev/null @@ -1,51 +0,0 @@ - $token->access_token, - )); - - $user = json_decode(file_get_contents($url)); - - // Create a response from the request - return array( - 'uid' => $user->id, - 'nickname' => $user->username, - 'name' => $user->full_name, - 'location' => $user->country.' ,'.$user->country, - 'description' => $user->description, - 'image' => $user->avatar_url, - 'urls' => array( - 'MySpace' => $user->myspace_name, - 'Website' => $user->website, - ), - ); - } -} diff --git a/src/OAuth2/Client/Provider/Vkontakte.php b/src/OAuth2/Client/Provider/Vkontakte.php deleted file mode 100755 index bdad78e4..00000000 --- a/src/OAuth2/Client/Provider/Vkontakte.php +++ /dev/null @@ -1,54 +0,0 @@ - $token->uid, - 'fields' => implode(",",$scope), - 'access_token' => $token->access_token, - )); - - $user = json_decode(file_get_contents($url))->response; - - if(sizeof($user)==0) - return null; - else - $user = $user[0]; - - return array( - 'uid' => $user->uid, - 'nickname' => isset($user->nickname) ? $user->nickname : null, - 'name' => isset($user->name) ? $user->name : null, - 'first_name' => isset($user->first_name) ? $user->first_name : null, - 'last_name' => isset($user->last_name) ? $user->last_name : null, - 'email' => null, - 'location' => null, - 'description' => null, - 'image' => isset($user->photo_big) ? $user->photo_big : null, - 'urls' => array(), - ); - } -} diff --git a/src/OAuth2/Client/Provider/Windowslive.php b/src/OAuth2/Client/Provider/Windowslive.php deleted file mode 100755 index 8d489c3d..00000000 --- a/src/OAuth2/Client/Provider/Windowslive.php +++ /dev/null @@ -1,60 +0,0 @@ - $token->access_token, - )); - - // perform network request - $user = json_decode(file_get_contents($url)); - - // create a response from the request and return it - return array( - 'uid' => $user->id, - 'name' => $user->name, - 'nickname' => url_title($user->name, '_', true), -// 'location' => $user[''], # scope wl.postal_addresses is required - # but won't be implemented by default - 'locale' => $user->locale, - 'urls' => array('Windows Live' => $user->link), - ); - } -} diff --git a/src/OAuth2/Client/Provider/Yandex.php b/src/OAuth2/Client/Provider/Yandex.php deleted file mode 100755 index 7a8f4f80..00000000 --- a/src/OAuth2/Client/Provider/Yandex.php +++ /dev/null @@ -1,115 +0,0 @@ - array( - 'method' => 'GET', - 'header' => 'Authorization: OAuth '.$token->access_token - ) - ); - $_default_opts = stream_context_get_params(stream_context_get_default()); - - $opts = array_merge_recursive($_default_opts['options'], $opts); - $context = stream_context_create($opts); - $url = 'http://api-yaru.yandex.ru/me/?format=json'; - - $user = json_decode(file_get_contents($url,false,$context)); - - preg_match("/\d+$/",$user->id,$uid); - - return array( - 'uid' => $uid[0], - 'nickname' => isset($user->name) ? $user->name : null, - 'name' => isset($user->name) ? $user->name : null, - 'first_name' => isset($user->first_name) ? $user->first_name : null, - 'last_name' => isset($user->last_name) ? $user->last_name : null, - 'email' => isset($user->email) ? $user->email : null, - 'location' => isset($user->hometown->name) ? $user->hometown->name : null, - 'description' => isset($user->bio) ? $user->bio : null, - 'image' => $user->links->userpic, - ); - } - - public function access($code, $options = array()) - { - $params = array( - 'client_id' => $this->client_id, - 'client_secret' => $this->client_secret, - 'grant_type' => isset($options['grant_type']) ? $options['grant_type'] : 'authorization_code', - ); - - switch ($params['grant_type']) - { - case 'authorization_code': - $params['code'] = $code; - $params['redirect_uri'] = isset($options['redirect_uri']) ? $options['redirect_uri'] : $this->redirect_uri; - break; - - case 'refresh_token': - $params['refresh_token'] = $code; - break; - } - - $response = null; - $url = $this->url_access_token(); - - $curl = curl_init($url); - - $headers[] = 'Content-Type: application/x-www-form-urlencoded; charset=UTF-8;'; - curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); - -// curl_setopt($curl, CURLOPT_USERAGENT, 'yamolib-php'); - curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); - curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 30); - curl_setopt($curl, CURLOPT_TIMEOUT, 80); - curl_setopt($curl, CURLOPT_POST, true); - curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($params)); - curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); - // curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, true); - // curl_setopt($curl, CURLOPT_CAINFO, dirname(__FILE__) . '/../data/ca-certificate.crt'); - - $response = curl_exec($curl); - curl_close($curl); - - $return = json_decode($response, true); - - if ( ! empty($return['error'])) - { - throw new OAuth2_Exception($return); - } - - switch ($params['grant_type']) - { - case 'authorization_code': - return OAuth2_Token::factory('access', $return); - break; - - case 'refresh_token': - return OAuth2_Token::factory('refresh', $return); - break; - } - } - -} diff --git a/src/OAuth2/Client/Token.php b/src/OAuth2/Client/Token.php deleted file mode 100755 index e4bae4bc..00000000 --- a/src/OAuth2/Client/Token.php +++ /dev/null @@ -1,46 +0,0 @@ -$key; - } - - /** - * Return a boolean if the property is set - * - * @param string variable name - * @return bool - */ - public function __isset($key) - { - return isset($this->$key); - } - -} // End Token diff --git a/src/OAuth2/Client/Token/Access.php b/src/OAuth2/Client/Token/Access.php deleted file mode 100755 index dd508c41..00000000 --- a/src/OAuth2/Client/Token/Access.php +++ /dev/null @@ -1,79 +0,0 @@ -accessToken = $options['access_token']; - - // Some providers (not many) give the uid here, so lets take it - isset($options['uid']) and $this->uid = $options['uid']; - - //Vkontakte uses user_id instead of uid - isset($options['user_id']) and $this->uid = $options['user_id']; - - //Mailru uses x_mailru_vid instead of uid - isset($options['x_mailru_vid']) and $this->uid = $options['x_mailru_vid']; - - // We need to know when the token expires, add num. seconds to current time - isset($options['expires_in']) and $this->expires = time() + ((int) $options['expires_in']); - - // Facebook is just being a spec ignoring jerk - isset($options['expires']) and $this->expires = time() + ((int) $options['expires']); - - // Grab a refresh token so we can update access tokens when they expires - isset($options['refresh_token']) and $this->refreshToken = $options['refresh_token']; - } - - /** - * Returns the token key. - * - * @return string - */ - public function __toString() - { - return (string) $this->accessToken; - } - -} \ No newline at end of file diff --git a/src/OAuth2/Client/Token/Authorize.php b/src/OAuth2/Client/Token/Authorize.php deleted file mode 100755 index 2e9695cf..00000000 --- a/src/OAuth2/Client/Token/Authorize.php +++ /dev/null @@ -1,55 +0,0 @@ -code = $options['code']; - $this->redirectUri = $options['redirect_uri']; - } - - /** - * Returns the token key. - * - * @return string - */ - public function __toString() - { - return (string) $this->code; - } - -} \ No newline at end of file From d2267dbd245402c24cd3558fd69cff3f1c4f6d76 Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Tue, 12 Feb 2013 16:22:14 +0000 Subject: [PATCH 089/113] Added Password grant --- src/OAuth2/Grant/Password.php | 134 ++++++++++++++++++++++++++++++++++ 1 file changed, 134 insertions(+) create mode 100644 src/OAuth2/Grant/Password.php diff --git a/src/OAuth2/Grant/Password.php b/src/OAuth2/Grant/Password.php new file mode 100644 index 00000000..b3fbaea0 --- /dev/null +++ b/src/OAuth2/Grant/Password.php @@ -0,0 +1,134 @@ +identifier; + } + + public function getResponseType() + { + return $this->responseType; + } + + public function setVerifyCredentialsCallback($callback) + { + $this->callback = $callback; + } + + protected function getVerifyCredentialsCallback($username, $password) + { + if (is_null($this->callback) || ! is_callable($this->callback)) { + throw new Exception\InvalidGrantTypeException('Null or non-callable callback set'); + } + + return call_user_func($this->callback, $username, $password); + } + + public function completeFlow($inputParams = null, $authParams = array()) + { + // Client ID + $authParams['client_id'] = (isset($inputParams['client_id'])) ? + $inputParams['client_id'] : + AuthServer::getRequest()->post('client_id'); + + if (is_null($authParams['client_id'])) { + throw new Exception\ClientException(sprintf(AuthServer::getExceptionMessage('invalid_request'), 'client_id'), 0); + } + + // Client secret + $authParams['client_secret'] = (isset($inputParams['client_secret'])) ? + $inputParams['client_secret'] : + AuthServer::getRequest()->post('client_secret'); + + if (is_null($authParams['client_secret'])) { + throw new Exception\ClientException(sprintf(AuthServer::getExceptionMessage('invalid_request'), 'client_secret'), 0); + } + + // Validate client ID and redirect URI + $clientDetails = AuthServer::getStorage('client')->getClient($authParams['client_id'], $authParams['client_secret']); + + if ($clientDetails === false) { + throw new Exception\ClientException(AuthServer::getExceptionMessage('invalid_client'), 8); + } + + $authParams['client_details'] = $clientDetails; + + // User's username + $authParams['username'] = (isset($inputParams['username'])) ? + $inputParams['username'] : + AuthServer::getRequest()->post('username'); + + if (is_null($authParams['username'])) { + throw new Exception\ClientException(sprintf(AuthServer::getExceptionMessage('invalid_request'), 'username'), 0); + } + + // User's password + $authParams['password'] = (isset($inputParams['password'])) ? + $inputParams['password'] : + AuthServer::getRequest()->post('password'); + + if (is_null($authParams['password'])) { + throw new Exception\ClientException(sprintf(AuthServer::getExceptionMessage('invalid_request'), 'password'), 0); + } + + // Check if user's username and password are correct + $userId = call_user_func($this->getVerifyCredentialsCallback, $params['username'], $params['password']); + + if ($userId === false) { + throw new Exception\ClientException(AuthServer::getExceptionMessage('invalid_credentials'), 0); + } + + // Generate an access token + $accessToken = SecureKey::make(); + $refreshToken = (AuthServer::hasGrantType('refresh_token')) ? SecureKey::make() : null; + + $accessTokenExpires = time() + AuthServer::getExpiresIn(); + $accessTokenExpiresIn = AuthServer::getExpiresIn(); + + // Delete any existing sessions just to be sure + AuthServer::getStorage('session')->deleteSession($authParams['client_id'], 'user', $userId); + + // Create a new session + AuthServer::getStorage('session')->createSession( + $authParams['client_id'], + null, + 'user', + $userId, + null, + $accessToken, + $refreshToken, + $accessTokenExpires, + 'granted' + ); + + $response = array( + 'access_token' => $accessToken, + 'token_type' => 'bearer', + 'expires' => $accessTokenExpires, + 'expires_in' => $accessTokenExpiresIn + ); + + if (AuthServer::hasGrantType('refresh_token')) { + $response['refresh_token'] = $refreshToken; + } + + return $response; + } + +} \ No newline at end of file From 61d1685e84df79cb566b714f0ee1cae085c2763c Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Tue, 12 Feb 2013 16:45:33 +0000 Subject: [PATCH 090/113] Minor fixes to password grant --- src/OAuth2/Grant/Password.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/OAuth2/Grant/Password.php b/src/OAuth2/Grant/Password.php index b3fbaea0..b227083e 100644 --- a/src/OAuth2/Grant/Password.php +++ b/src/OAuth2/Grant/Password.php @@ -31,13 +31,13 @@ class Password implements GrantTypeInterface { $this->callback = $callback; } - protected function getVerifyCredentialsCallback($username, $password) + protected function getVerifyCredentialsCallback() { if (is_null($this->callback) || ! is_callable($this->callback)) { throw new Exception\InvalidGrantTypeException('Null or non-callable callback set'); } - return call_user_func($this->callback, $username, $password); + return $this->callback; } public function completeFlow($inputParams = null, $authParams = array()) @@ -88,7 +88,7 @@ class Password implements GrantTypeInterface { } // Check if user's username and password are correct - $userId = call_user_func($this->getVerifyCredentialsCallback, $params['username'], $params['password']); + $userId = call_user_func($this->getVerifyCredentialsCallback(), $authParams['username'], $authParams['password']); if ($userId === false) { throw new Exception\ClientException(AuthServer::getExceptionMessage('invalid_credentials'), 0); From a361fbab14bb4f3981b33369f13b2d4985fd8d97 Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Tue, 12 Feb 2013 16:45:45 +0000 Subject: [PATCH 091/113] Finished unit tests for AuthServer --- tests/authentication/AuthServerTest.php | 283 +++++++++++++++++++++++- 1 file changed, 282 insertions(+), 1 deletion(-) diff --git a/tests/authentication/AuthServerTest.php b/tests/authentication/AuthServerTest.php index 0ec7219d..f5f534cd 100644 --- a/tests/authentication/AuthServerTest.php +++ b/tests/authentication/AuthServerTest.php @@ -827,7 +827,7 @@ class Authentication_Server_test extends PHPUnit_Framework_TestCase * @expectedException OAuth2\Exception\ClientException * @expectedExceptionCode 0 */ - public function test_issueAccessToken_clientCredentialsGrant_missingClientCredentials() + public function test_issueAccessToken_clientCredentialsGrant_missingClientPassword() { $a = $this->returnDefault(); $a->addGrantType(new OAuth2\Grant\ClientCredentials()); @@ -935,6 +935,287 @@ class Authentication_Server_test extends PHPUnit_Framework_TestCase $this->assertEquals(time()+$a::getExpiresIn(), $v['expires']); } + /** + * @expectedException OAuth2\Exception\ClientException + * @expectedExceptionCode 0 + */ + public function test_issueAccessToken_passwordGrant_missingClientId() + { + $a = $this->returnDefault(); + $a->addGrantType(new OAuth2\Grant\Password()); + + $request = new OAuth2\Util\Request(array(), $_POST); + $a->setRequest($request); + + $v = $a->issueAccessToken(array( + 'grant_type' => 'client_credentials' + )); + } + + /** + * @expectedException OAuth2\Exception\ClientException + * @expectedExceptionCode 0 + */ + public function test_issueAccessToken_passwordGrant_missingClientPassword() + { + $a = $this->returnDefault(); + $a->addGrantType(new OAuth2\Grant\Password()); + + $request = new OAuth2\Util\Request(array(), $_POST); + $a->setRequest($request); + + $v = $a->issueAccessToken(array( + 'grant_type' => 'password', + 'client_id' => 1234 + )); + } + + /** + * @expectedException OAuth2\Exception\ClientException + * @expectedExceptionCode 8 + */ + public function test_issueAccessToken_passwordGrant_badClient() + { + $this->client->shouldReceive('getClient')->andReturn(false); + + $a = $this->returnDefault(); + $a->addGrantType(new OAuth2\Grant\Password()); + + $request = new OAuth2\Util\Request(array(), $_POST); + $a->setRequest($request); + + $v = $a->issueAccessToken(array( + 'grant_type' => 'password', + 'client_id' => 1234, + 'client_secret' => 5678 + )); + } + + /** + * @expectedException OAuth2\Exception\InvalidGrantTypeException + */ + function test_issueAccessToken_passwordGrant_invalidCallback() + { + $this->client->shouldReceive('getClient')->andReturn(array( + 'client_id' => 1234, + 'client_secret' => 5678, + 'redirect_uri' => 'http://foo/redirect', + 'name' => 'Example Client' + )); + + $this->client->shouldReceive('validateRefreshToken')->andReturn(1); + + $this->session->shouldReceive('validateAuthCode')->andReturn(1); + $this->session->shouldReceive('createSession')->andReturn(1); + $this->session->shouldReceive('deleteSession')->andReturn(null); + $this->session->shouldReceive('updateRefreshToken')->andReturn(null); + + $testCredentials = null; + + $a = $this->returnDefault(); + $pgrant = new OAuth2\Grant\Password(); + $pgrant->setVerifyCredentialsCallback($testCredentials); + $a->addGrantType($pgrant); + + $v = $a->issueAccessToken(array( + 'grant_type' => 'password', + 'client_id' => 1234, + 'client_secret' => 5678, + 'username' => 'foo', + 'password' => 'bar' + )); + } + + /** + * @expectedException OAuth2\Exception\ClientException + * @expectedExceptionCode 0 + */ + function test_issueAccessToken_passwordGrant_missingUsername() + { + $this->client->shouldReceive('getClient')->andReturn(array( + 'client_id' => 1234, + 'client_secret' => 5678, + 'redirect_uri' => 'http://foo/redirect', + 'name' => 'Example Client' + )); + + $this->client->shouldReceive('validateRefreshToken')->andReturn(1); + + $this->session->shouldReceive('validateAuthCode')->andReturn(1); + $this->session->shouldReceive('createSession')->andReturn(1); + $this->session->shouldReceive('deleteSession')->andReturn(null); + $this->session->shouldReceive('updateRefreshToken')->andReturn(null); + + $testCredentials = function($u, $p) { return false; }; + + $a = $this->returnDefault(); + $pgrant = new OAuth2\Grant\Password(); + $pgrant->setVerifyCredentialsCallback($testCredentials); + $a->addGrantType($pgrant); + + $v = $a->issueAccessToken(array( + 'grant_type' => 'password', + 'client_id' => 1234, + 'client_secret' => 5678 + )); + } + + /** + * @expectedException OAuth2\Exception\ClientException + * @expectedExceptionCode 0 + */ + function test_issueAccessToken_passwordGrant_missingPassword() + { + $this->client->shouldReceive('getClient')->andReturn(array( + 'client_id' => 1234, + 'client_secret' => 5678, + 'redirect_uri' => 'http://foo/redirect', + 'name' => 'Example Client' + )); + + $this->client->shouldReceive('validateRefreshToken')->andReturn(1); + + $this->session->shouldReceive('validateAuthCode')->andReturn(1); + $this->session->shouldReceive('createSession')->andReturn(1); + $this->session->shouldReceive('deleteSession')->andReturn(null); + $this->session->shouldReceive('updateRefreshToken')->andReturn(null); + + $testCredentials = function($u, $p) { return false; }; + + $a = $this->returnDefault(); + $pgrant = new OAuth2\Grant\Password(); + $pgrant->setVerifyCredentialsCallback($testCredentials); + $a->addGrantType($pgrant); + + $v = $a->issueAccessToken(array( + 'grant_type' => 'password', + 'client_id' => 1234, + 'client_secret' => 5678, + 'username' => 'foo' + )); + } + + /** + * @expectedException OAuth2\Exception\ClientException + * @expectedExceptionCode 0 + */ + function test_issueAccessToken_passwordGrant_badCredentials() + { + $this->client->shouldReceive('getClient')->andReturn(array( + 'client_id' => 1234, + 'client_secret' => 5678, + 'redirect_uri' => 'http://foo/redirect', + 'name' => 'Example Client' + )); + + $this->client->shouldReceive('validateRefreshToken')->andReturn(1); + + $this->session->shouldReceive('validateAuthCode')->andReturn(1); + $this->session->shouldReceive('createSession')->andReturn(1); + $this->session->shouldReceive('deleteSession')->andReturn(null); + $this->session->shouldReceive('updateRefreshToken')->andReturn(null); + + $testCredentials = function($u, $p) { return false; }; + + $a = $this->returnDefault(); + $pgrant = new OAuth2\Grant\Password(); + $pgrant->setVerifyCredentialsCallback($testCredentials); + $a->addGrantType($pgrant); + + $v = $a->issueAccessToken(array( + 'grant_type' => 'password', + 'client_id' => 1234, + 'client_secret' => 5678, + 'username' => 'foo', + 'password' => 'bar' + )); + } + + function test_issueAccessToken_passwordGrant_passedInput() + { + $this->client->shouldReceive('getClient')->andReturn(array( + 'client_id' => 1234, + 'client_secret' => 5678, + 'redirect_uri' => 'http://foo/redirect', + 'name' => 'Example Client' + )); + + $this->client->shouldReceive('validateRefreshToken')->andReturn(1); + + $this->session->shouldReceive('validateAuthCode')->andReturn(1); + $this->session->shouldReceive('createSession')->andReturn(1); + $this->session->shouldReceive('deleteSession')->andReturn(null); + $this->session->shouldReceive('updateRefreshToken')->andReturn(null); + + $testCredentials = function($u, $p) { return 1; }; + + $a = $this->returnDefault(); + $pgrant = new OAuth2\Grant\Password(); + $pgrant->setVerifyCredentialsCallback($testCredentials); + $a->addGrantType($pgrant); + + $v = $a->issueAccessToken(array( + 'grant_type' => 'password', + 'client_id' => 1234, + 'client_secret' => 5678, + 'username' => 'foo', + 'password' => 'bar' + )); + + $this->assertArrayHasKey('access_token', $v); + $this->assertArrayHasKey('token_type', $v); + $this->assertArrayHasKey('expires', $v); + $this->assertArrayHasKey('expires_in', $v); + $this->assertArrayHasKey('refresh_token', $v); + + $this->assertEquals($a::getExpiresIn(), $v['expires_in']); + $this->assertEquals(time()+$a::getExpiresIn(), $v['expires']); + } + + function test_issueAccessToken_passwordGrant() + { + $this->client->shouldReceive('getClient')->andReturn(array( + 'client_id' => 1234, + 'client_secret' => 5678, + 'redirect_uri' => 'http://foo/redirect', + 'name' => 'Example Client' + )); + + $this->client->shouldReceive('validateRefreshToken')->andReturn(1); + + $this->session->shouldReceive('validateAuthCode')->andReturn(1); + $this->session->shouldReceive('createSession')->andReturn(1); + $this->session->shouldReceive('deleteSession')->andReturn(null); + $this->session->shouldReceive('updateRefreshToken')->andReturn(null); + + $testCredentials = function($u, $p) { return 1; }; + + $a = $this->returnDefault(); + $pgrant = new OAuth2\Grant\Password(); + $pgrant->setVerifyCredentialsCallback($testCredentials); + $a->addGrantType($pgrant); + + $_POST['grant_type'] = 'password'; + $_POST['client_id'] = 1234; + $_POST['client_secret'] = 5678; + $_POST['username'] = 'foo'; + $_POST['password'] = 'bar'; + + $request = new OAuth2\Util\Request(array(), $_POST); + $a->setRequest($request); + + $v = $a->issueAccessToken(); + + $this->assertArrayHasKey('access_token', $v); + $this->assertArrayHasKey('token_type', $v); + $this->assertArrayHasKey('expires', $v); + $this->assertArrayHasKey('expires_in', $v); + $this->assertArrayHasKey('refresh_token', $v); + + $this->assertEquals($a::getExpiresIn(), $v['expires_in']); + $this->assertEquals(time()+$a::getExpiresIn(), $v['expires']); + } + public function tearDown() { M::close(); } From e771099568759eb5cd8a2e4a473180cac5659d5a Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Tue, 12 Feb 2013 17:22:15 +0000 Subject: [PATCH 092/113] Removed unnecessary functions --- src/OAuth2/Storage/SessionInterface.php | 55 ------------------------- 1 file changed, 55 deletions(-) diff --git a/src/OAuth2/Storage/SessionInterface.php b/src/OAuth2/Storage/SessionInterface.php index f886339a..7e9fd368 100644 --- a/src/OAuth2/Storage/SessionInterface.php +++ b/src/OAuth2/Storage/SessionInterface.php @@ -84,28 +84,6 @@ interface SessionInterface $typeId ); - /** - * Return the session ID for a given session owner and client combination - * - * Example SQL query: - * - * - * SELECT id FROM oauth_sessions WHERE client_id = $clientId - * AND owner_type = $type AND owner_id = $typeId - * - * - * @param string $type The session owner's type - * @param string $typeId The session owner's ID - * @param string $clientId The client ID - * @return string|null Return the session ID as an integer if - * found otherwise returns false - */ - public function sessionExists( - $type, - $typeId, - $clientId - ); - /** * Validate that an authorisation code is valid * @@ -147,39 +125,6 @@ interface SessionInterface $authCode ); - /** - * Removes an authorisation code associated with a session - * - * Example SQL query: - * - * - * UPDATE oauth_sessions SET auth_code = NULL WHERE id = $sessionId - * - * - * @param int $sessionId The OAuth session ID - * @return void - */ - public function removeAuthCode($sessionId); - - /** - * Sets a sessions access token - * - * Example SQL query: - * - * - * UPDATE oauth_sessions SET access_token = $accessToken WHERE id = - * $sessionId - * - * - * @param int $sessionId The OAuth session ID - * @param string $accessToken The access token - * @return void - */ - public function setAccessToken( - $sessionId, - $accessToken - ); - public function validateAccessToken($accessToken); /** From 77399232732f162b688562f88380144b6a7f678f Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Tue, 12 Feb 2013 20:33:03 +0000 Subject: [PATCH 093/113] Updated database --- sql/database.sql | 77 ++++++++++++++++++++++-------------------------- 1 file changed, 35 insertions(+), 42 deletions(-) diff --git a/sql/database.sql b/sql/database.sql index e733253b..e2e31c8e 100644 --- a/sql/database.sql +++ b/sql/database.sql @@ -1,5 +1,13 @@ --- Create syntax for TABLE 'clients' -CREATE TABLE `clients` ( +CREATE TABLE `oauth_client_endpoints` ( + `id` int(11) unsigned NOT NULL AUTO_INCREMENT, + `client_id` varchar(40) NOT NULL DEFAULT '', + `redirect_uri` varchar(255) DEFAULT NULL, + PRIMARY KEY (`id`), + KEY `client_id` (`client_id`), + CONSTRAINT `oauth_client_endpoints_ibfk_1` FOREIGN KEY (`client_id`) REFERENCES `oauth_clients` (`id`) ON DELETE CASCADE ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE `oauth_clients` ( `id` varchar(40) NOT NULL DEFAULT '', `secret` varchar(40) NOT NULL DEFAULT '', `name` varchar(255) NOT NULL DEFAULT '', @@ -7,45 +15,6 @@ CREATE TABLE `clients` ( PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; --- Create syntax for TABLE 'client_endpoints' -CREATE TABLE `client_endpoints` ( - `id` int(11) unsigned NOT NULL AUTO_INCREMENT, - `client_id` varchar(40) NOT NULL DEFAULT '', - `redirect_uri` varchar(255) DEFAULT NULL, - PRIMARY KEY (`id`), - KEY `client_id` (`client_id`), - CONSTRAINT `client_endpoints_ibfk_1` FOREIGN KEY (`client_id`) REFERENCES `clients` (`id`) ON DELETE CASCADE ON UPDATE CASCADE -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - --- Create syntax for TABLE 'oauth_sessions' -CREATE TABLE `oauth_sessions` ( - `id` int(11) unsigned NOT NULL AUTO_INCREMENT, - `client_id` varchar(40) NOT NULL DEFAULT '', - `redirect_uri` varchar(250) DEFAULT '', - `owner_type` enum('user','client') NOT NULL DEFAULT 'user', - `owner_id` varchar(255) DEFAULT NULL, - `auth_code` varchar(40) DEFAULT '', - `access_token` varchar(40) DEFAULT '', - `refresh_token` varchar(40) NOT NULL, - `access_token_expires` int(10) DEFAULT NULL, - `stage` enum('requested','granted') NOT NULL DEFAULT 'requested', - `first_requested` int(10) unsigned NOT NULL, - `last_updated` int(10) unsigned NOT NULL, - PRIMARY KEY (`id`), - KEY `client_id` (`client_id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - --- Create syntax for TABLE 'scopes' -CREATE TABLE `scopes` ( - `id` int(11) unsigned NOT NULL AUTO_INCREMENT, - `scope` varchar(255) NOT NULL DEFAULT '', - `name` varchar(255) NOT NULL DEFAULT '', - `description` varchar(255) DEFAULT '', - PRIMARY KEY (`id`), - UNIQUE KEY `scope` (`scope`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - --- Create syntax for TABLE 'oauth_session_scopes' CREATE TABLE `oauth_session_scopes` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `session_id` int(11) unsigned NOT NULL, @@ -53,6 +22,30 @@ CREATE TABLE `oauth_session_scopes` ( PRIMARY KEY (`id`), KEY `session_id` (`session_id`), KEY `scope_id` (`scope_id`), - CONSTRAINT `oauth_session_scopes_ibfk_5` FOREIGN KEY (`scope_id`) REFERENCES `scopes` (`id`) ON DELETE CASCADE, + CONSTRAINT `oauth_session_scopes_ibfk_5` FOREIGN KEY (`scope_id`) REFERENCES `oauth_scopes` (`id`) ON DELETE CASCADE, CONSTRAINT `oauth_session_scopes_ibfk_4` FOREIGN KEY (`session_id`) REFERENCES `oauth_sessions` (`id`) ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE `oauth_sessions` ( + `id` int(11) unsigned NOT NULL AUTO_INCREMENT, + `client_id` varchar(40) NOT NULL DEFAULT '', + `redirect_uri` varchar(250) DEFAULT '', + `owner_type` enum('user','client') NOT NULL DEFAULT 'user', + `owner_id` varchar(255) DEFAULT '', + `auth_code` varchar(40) DEFAULT '', + `access_token` varchar(40) DEFAULT '', + `refresh_token` varchar(40) DEFAULT '', + `access_token_expires` int(10) DEFAULT NULL, + `stage` enum('requested','granted') NOT NULL DEFAULT 'requested', + PRIMARY KEY (`id`), + KEY `client_id` (`client_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE `oauth_scopes` ( + `id` int(11) unsigned NOT NULL AUTO_INCREMENT, + `scope` varchar(255) NOT NULL DEFAULT '', + `name` varchar(255) NOT NULL DEFAULT '', + `description` varchar(255) DEFAULT '', + PRIMARY KEY (`id`), + UNIQUE KEY `scope` (`scope`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; \ No newline at end of file From 1cfe10105a691707538fc156f2cbf10b0b235375 Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Tue, 12 Feb 2013 20:33:23 +0000 Subject: [PATCH 094/113] Updated docblocks for the two main classes --- src/OAuth2/AuthServer.php | 102 ++++++++++++++++++++++++++++++---- src/OAuth2/ResourceServer.php | 83 ++++++++++++++++++++++----- 2 files changed, 161 insertions(+), 24 deletions(-) diff --git a/src/OAuth2/AuthServer.php b/src/OAuth2/AuthServer.php index 8bad1871..4a360d01 100644 --- a/src/OAuth2/AuthServer.php +++ b/src/OAuth2/AuthServer.php @@ -1,4 +1,13 @@ + * @copyright Copyright (c) 2013 University of Lincoln + * @license http://mit-license.org/ + * @link http://github.com/lncd/oauth2 + */ namespace OAuth2; @@ -9,6 +18,9 @@ use OAuth2\Storage\ClientInterface; use OAuth2\Storage\ScopeInterface; use OAuth2\Grant\GrantTypeInterface; +/** + * OAuth 2.0 authentication server class + */ class AuthServer { /** @@ -21,14 +33,34 @@ class AuthServer */ protected $scopeDelimeter = ','; + /** + * The TTL (time to live) of an access token in seconds (default: 3600) + * @var integer + */ static protected $expiresIn = 3600; + /** + * The registered grant response types + * @var array + */ protected $responseTypes = array(); + /** + * The client, scope and session storage classes + * @var array + */ static protected $storages = array(); + /** + * The registered grant types + * @var array + */ static protected $grantTypes = array(); + /** + * The request object + * @var Util\RequestInterface + */ static protected $request = null; /** @@ -67,11 +99,24 @@ class AuthServer 'invalid_refresh' => 'The refresh token is invalid.', ); + /** + * Get an exception message + * + * @param string $error The error message key + * @return string The error message + */ public static function getExceptionMessage($error = '') { return self::$exceptionMessages[$error]; } + /** + * Create a new OAuth2 authentication server + * + * @param ClientInterface $client A class which inherits from Storage/ClientInterface + * @param SessionInterface $session A class which inherits from Storage/SessionInterface + * @param ScopeInterface $scope A class which inherits from Storage/ScopeInterface + */ public function __construct(ClientInterface $client, SessionInterface $session, ScopeInterface $scope) { self::$storages = array( @@ -81,6 +126,11 @@ class AuthServer ); } + /** + * Enable support for a grant + * @param GrantTypeInterface $grantType A grant class which conforms to Interface/GrantTypeInterface + * @param null|string $identifier An identifier for the grant (autodetected if not passed) + */ public function addGrantType(GrantTypeInterface $grantType, $identifier = null) { if (is_null($identifier)) { @@ -93,26 +143,49 @@ class AuthServer } } + /** + * Check if a grant type has been enabled + * @param string $identifier The grant type identifier + * @return boolean Returns "true" if enabled, "false" if not + */ public static function hasGrantType($identifier) { return (array_key_exists($identifier, self::$grantTypes)); } + /** + * Get the scope delimeter + * + * @return string The scope delimiter (default: ",") + */ public function getScopeDelimeter() { return $this->scopeDelimeter; } - public function setScopeDelimeter($scope_delimeter) + /** + * Set the scope delimiter + * + * @param string $scopeDelimeter + */ + public function setScopeDelimeter($scopeDelimeter) { - $this->scopeDelimeter = $scope_delimeter; + $this->scopeDelimeter = $scopeDelimeter; } + /** + * Get the TTL for an access token + * @return int The TTL + */ public static function getExpiresIn() { return self::$expiresIn; } + /** + * Set the TTL for an access token + * @param int $expiresIn The new TTL + */ public function setExpiresIn($expiresIn) { self::$expiresIn = $expiresIn; @@ -121,7 +194,7 @@ class AuthServer /** * Sets the Request Object * - * @param RequestInterface The Request Object + * @param Util\RequestInterface The Request Object */ public function setRequest(Util\RequestInterface $request) { @@ -131,7 +204,7 @@ class AuthServer /** * Gets the Request object. It will create one from the globals if one is not set. * - * @return RequestInterface + * @return Util\RequestInterface */ public static function getRequest() { @@ -145,6 +218,11 @@ class AuthServer return self::$request; } + /** + * Return a storage class + * @param string $obj The class required + * @return Storage\ClientInterface|Storage\ScopeInterface|Storage\SessionInterface + */ public static function getStorage($obj) { return self::$storages[$obj]; @@ -153,8 +231,8 @@ class AuthServer /** * Check authorise parameters * - * @access public * @param array $inputParams Optional array of parsed $_GET keys + * @throws \OAuth2\Exception\ClientException * @return array Authorise request parameters */ public function checkAuthoriseParams($inputParams = array()) @@ -236,10 +314,10 @@ class AuthServer /** * Parse a new authorise request * - * @param string $type The session owner's type - * @param string $typeId The session owner's ID - * @param array $authoriseParams The authorise request $_GET parameters - * @return string An authorisation code + * @param string $type The session owner's type + * @param string $typeId The session owner's ID + * @param array $authParams The authorise request $_GET parameters + * @return string An authorisation code */ public function newAuthoriseRequest($type, $typeId, $authParams = array()) { @@ -264,7 +342,6 @@ class AuthServer /** * Issue an access token * - * @access public * @param array $inputParams Optional array of parsed $_POST keys * @return array Authorise request parameters */ @@ -287,6 +364,11 @@ class AuthServer return $this->getGrantType($authParams['grant_type'])->completeFlow($inputParams, $authParams); } + /** + * Return a grant type class + * @param string $grantType The grant type identifer + * @return class + */ protected function getGrantType($grantType) { return self::$grantTypes[$grantType]; diff --git a/src/OAuth2/ResourceServer.php b/src/OAuth2/ResourceServer.php index f170e3ad..96a5bd4d 100644 --- a/src/OAuth2/ResourceServer.php +++ b/src/OAuth2/ResourceServer.php @@ -1,4 +1,13 @@ + * @copyright Copyright (c) 2013 University of Lincoln + * @license http://mit-license.org/ + * @link http://github.com/lncd/oauth2 + */ namespace OAuth2; @@ -8,29 +17,63 @@ use OAuth2\Storage\SessionScopeInterface; use OAuth2\Util\RequestInterface; use OAuth2\Util\Request; +/** + * OAuth 2.0 Resource Server + */ class ResourceServer { + /** + * The access token + * @var string + */ protected $accessToken = null; + /** + * The session ID + * @var string + */ protected $sessionId = null; + /** + * The type of the owner of the access token + * @var string + */ protected $ownerType = null; + /** + * The ID of the owner of the access token + * @var string + */ protected $ownerId = null; + /** + * The scopes associated with the access token + * @var array + */ protected $sessionScopes = array(); + /** + * The client, scope and session storage classes + * @var array + */ protected $storages = array(); + /** + * The request object + * @var Util\RequestInterface + */ protected $request = null; + /** + * The query string key which is used by clients to present the access token (default: oauth_token) + * @var string + */ protected $tokenKey = 'oauth_token'; /** * Sets up the Resource * - * @param SessionInterface The Session Storage Object - * @param SessionScopeInterface The Session Scope Storage Object + * @param SessionInterface The Session Storage Object */ public function __construct(SessionInterface $session) { @@ -50,7 +93,7 @@ class ResourceServer /** * Gets the Request object. It will create one from the globals if one is not set. * - * @return RequestInterface + * @return Util\RequestInterface */ public function getRequest() { @@ -63,20 +106,30 @@ class ResourceServer return $this->request; } + /** + * Returns the query string key for the access token. + * + * @return string + */ public function getTokenKey() { return $this->tokenKey; } + /** + * Sets the query string key for the access token. + * + * @param $key The new query string key + */ public function setTokenKey($key) { $this->tokenKey = $key; } /** - * Gets the Owner ID. + * Gets the access token owner ID. * - * @return int + * @return string */ public function getOwnerId() { @@ -84,9 +137,9 @@ class ResourceServer } /** - * Gets the Owner Type. + * Gets the owner type. * - * @return string + * @return string */ public function getOwnerType() { @@ -94,9 +147,9 @@ class ResourceServer } /** - * Gets the Access Token. + * Gets the access token. * - * @return string + * @return string */ public function getAccessToken() { @@ -104,8 +157,9 @@ class ResourceServer } /** - * Checks if the Access Token is valid or not. + * Checks if the access token is valid or not. * + * @throws Exception\InvalidAccessTokenException Thrown if the presented access token is not valid * @return bool */ public function isValid() @@ -129,9 +183,10 @@ class ResourceServer } /** - * Checks if the current session has the given scope(s). + * Checks if the presented access token has the given scope(s). * - * @param array + * @param array|string An array of scopes or a single scope as a string + * @return bool Returns bool if all scopes are found, false if any fail */ public function hasScope($scopes) { @@ -153,10 +208,10 @@ class ResourceServer } /** - * Reads in the Access Token from the headers. + * Reads in the access token from the headers. * + * @throws Exception\MissingAccessTokenException Thrown if there is no access token presented * @return string - * @throws Exception\MissingAccessTokenException */ protected function determineAccessToken() { From d0b1034f35175980c8af33650d5eff472332aff0 Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Tue, 12 Feb 2013 20:33:40 +0000 Subject: [PATCH 095/113] Ignore vendor/phpunit --- build/phpunit.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/build/phpunit.xml b/build/phpunit.xml index 517c342a..5b44b45c 100644 --- a/build/phpunit.xml +++ b/build/phpunit.xml @@ -17,6 +17,7 @@ PHP_LIBDIR ../vendor/composer ../vendor/mockery + ../vendor/phpunit ../tests ../testing From 0f4546db472ef7990f1aa4dc5cbc8929a39016f5 Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Wed, 13 Feb 2013 17:10:44 +0000 Subject: [PATCH 096/113] Changed 'oauth_token' to 'access_token' --- src/OAuth2/ResourceServer.php | 4 ++-- tests/resource/ResourceServerTest.php | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/OAuth2/ResourceServer.php b/src/OAuth2/ResourceServer.php index 96a5bd4d..e7cc7d2f 100644 --- a/src/OAuth2/ResourceServer.php +++ b/src/OAuth2/ResourceServer.php @@ -65,10 +65,10 @@ class ResourceServer protected $request = null; /** - * The query string key which is used by clients to present the access token (default: oauth_token) + * The query string key which is used by clients to present the access token (default: access_token) * @var string */ - protected $tokenKey = 'oauth_token'; + protected $tokenKey = 'access_token'; /** * Sets up the Resource diff --git a/tests/resource/ResourceServerTest.php b/tests/resource/ResourceServerTest.php index b8fed73e..c6bc058d 100644 --- a/tests/resource/ResourceServerTest.php +++ b/tests/resource/ResourceServerTest.php @@ -43,20 +43,20 @@ class Resource_Server_test extends PHPUnit_Framework_TestCase public function test_getTokenKey() { $s = $this->returnDefault(); - $this->assertEquals('oauth_token', $s->getTokenKey()); + $this->assertEquals('access_token', $s->getTokenKey()); } public function test_setTokenKey() { $s = $this->returnDefault(); - $s->setTokenKey('access_token'); + $s->setTokenKey('oauth_token'); $reflector = new ReflectionClass($s); $requestProperty = $reflector->getProperty('tokenKey'); $requestProperty->setAccessible(true); $v = $requestProperty->getValue($s); - $this->assertEquals('access_token', $v); + $this->assertEquals('oauth_token', $v); } /** From 1e2d2b3d2553c17c5daa2e91bbb2005178fb8708 Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Wed, 13 Feb 2013 18:25:10 +0000 Subject: [PATCH 097/113] Added AuthServer::getParam() function to reduce repetitive code --- src/OAuth2/AuthServer.php | 20 ++++++++++++++++++++ src/OAuth2/Grant/AuthCode.php | 25 ++++--------------------- src/OAuth2/Grant/GrantTypeInterface.php | 2 +- 3 files changed, 25 insertions(+), 22 deletions(-) diff --git a/src/OAuth2/AuthServer.php b/src/OAuth2/AuthServer.php index 4a360d01..2612c065 100644 --- a/src/OAuth2/AuthServer.php +++ b/src/OAuth2/AuthServer.php @@ -374,4 +374,24 @@ class AuthServer return self::$grantTypes[$grantType]; } + /** + * Get a parameter from passed input parameters or the Request class + * @param string|array $param Requried parameter + * @param string $method Get/put/post/delete + * @param array $inputParams Passed input parameters + * @return mixed 'Null' if parameter is missing + */ + public static function getParam($param = '', $method = 'get', $inputParams = array()) + { + if (is_string($param)) { + return (isset($inputParams[$param])) ? $inputParams['client_id'] : self::getRequest()->{$method}($param); + } else { + $response = array(); + foreach ($param as $p) { + $response[$p] = self::getParam($p, $method, $inputParams); + } + return $response; + } + } + } diff --git a/src/OAuth2/Grant/AuthCode.php b/src/OAuth2/Grant/AuthCode.php index b055d896..9760694e 100644 --- a/src/OAuth2/Grant/AuthCode.php +++ b/src/OAuth2/Grant/AuthCode.php @@ -25,31 +25,18 @@ class AuthCode implements GrantTypeInterface { return $this->responseType; } - public function completeFlow($inputParams = null, $authParams = array()) + public function completeFlow($inputParams = null) { - // Client ID - $authParams['client_id'] = (isset($inputParams['client_id'])) ? - $inputParams['client_id'] : - AuthServer::getRequest()->post('client_id'); + $authParams = AuthServer::getParam(array('client_id', 'client_secret', 'redirect_uri', 'code'), 'post', $inputParams); - if (is_null($authParams['client_id'])) { + if (is_null($authParams['client_id'])) { throw new Exception\ClientException(sprintf(AuthServer::getExceptionMessage('invalid_request'), 'client_id'), 0); } - // Client secret - $authParams['client_secret'] = (isset($inputParams['client_secret'])) ? - $inputParams['client_secret'] : - AuthServer::getRequest()->post('client_secret'); - if (is_null($authParams['client_secret'])) { throw new Exception\ClientException(sprintf(AuthServer::getExceptionMessage('invalid_request'), 'client_secret'), 0); } - // Redirect URI - $authParams['redirect_uri'] = (isset($inputParams['redirect_uri'])) ? - $inputParams['redirect_uri'] : - AuthServer::getRequest()->post('redirect_uri'); - if (is_null($authParams['redirect_uri'])) { throw new Exception\ClientException(sprintf(AuthServer::getExceptionMessage('invalid_request'), 'redirect_uri'), 0); } @@ -63,11 +50,7 @@ class AuthCode implements GrantTypeInterface { $authParams['client_details'] = $clientDetails; - // The authorization code - $authParams['code'] = (isset($inputParams['code'])) ? - $inputParams['code'] : - AuthServer::getRequest()->post('code'); - + // Validate the authorization code if (is_null($authParams['code'])) { throw new Exception\ClientException(sprintf(AuthServer::getExceptionMessage('invalid_request'), 'code'), 0); } diff --git a/src/OAuth2/Grant/GrantTypeInterface.php b/src/OAuth2/Grant/GrantTypeInterface.php index f64b3e9f..e9444537 100644 --- a/src/OAuth2/Grant/GrantTypeInterface.php +++ b/src/OAuth2/Grant/GrantTypeInterface.php @@ -42,5 +42,5 @@ interface GrantTypeInterface * @param array $authParams The authorisation paramaters that have been set so far in the request * @return array An array of parameters to be passed back to the client */ - public function completeFlow($inputParams = null, $authParams = array()); + public function completeFlow($inputParams = null); } From a98dcea6fe2cf4eb621621bfb557068d71b14385 Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Wed, 13 Feb 2013 19:35:42 +0000 Subject: [PATCH 098/113] Fixed missing fields in `oauth_sessions` table --- sql/database.sql | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sql/database.sql b/sql/database.sql index e2e31c8e..9d30a76d 100644 --- a/sql/database.sql +++ b/sql/database.sql @@ -37,6 +37,8 @@ CREATE TABLE `oauth_sessions` ( `refresh_token` varchar(40) DEFAULT '', `access_token_expires` int(10) DEFAULT NULL, `stage` enum('requested','granted') NOT NULL DEFAULT 'requested', + `first_requested` int(10) unsigned NOT NULL, + `last_updated` int(10) unsigned NOT NULL, PRIMARY KEY (`id`), KEY `client_id` (`client_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; From d99002ef2f860e88bbc37414237fe7d85934ea66 Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Wed, 13 Feb 2013 19:36:10 +0000 Subject: [PATCH 099/113] Renamed variable as $authParams is no longer used --- src/OAuth2/AuthServer.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/OAuth2/AuthServer.php b/src/OAuth2/AuthServer.php index 2612c065..69a78831 100644 --- a/src/OAuth2/AuthServer.php +++ b/src/OAuth2/AuthServer.php @@ -347,21 +347,21 @@ class AuthServer */ public function issueAccessToken($inputParams = array()) { - $authParams['grant_type'] = (isset($inputParams['grant_type'])) ? + $grantType = (isset($inputParams['grant_type'])) ? $inputParams['grant_type'] : self::getRequest()->post('grant_type'); - if (is_null($authParams['grant_type'])) { + if (is_null($grantType)) { throw new Exception\ClientException(sprintf(self::$exceptionMessages['invalid_request'], 'grant_type'), 0); } // Ensure grant type is one that is recognised and is enabled - if ( ! in_array($authParams['grant_type'], array_keys(self::$grantTypes))) { - throw new Exception\ClientException(sprintf(self::$exceptionMessages['unsupported_grant_type'], $authParams['grant_type']), 7); + if ( ! in_array($grantType, array_keys(self::$grantTypes))) { + throw new Exception\ClientException(sprintf(self::$exceptionMessages['unsupported_grant_type'], $grantType), 7); } // Complete the flow - return $this->getGrantType($authParams['grant_type'])->completeFlow($inputParams, $authParams); + return $this->getGrantType($grantType)->completeFlow($inputParams); } /** From 4506037bda66979b8081d74d94ca3c17309c83f1 Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Wed, 13 Feb 2013 19:36:56 +0000 Subject: [PATCH 100/113] Docblock updates --- src/OAuth2/Exception/ClientException.php | 12 ++++++ .../Exception/InvalidAccessTokenException.php | 12 ++++++ .../Exception/InvalidGrantTypeException.php | 12 ++++++ src/OAuth2/Exception/OAuth2Exception.php | 12 ++++++ src/OAuth2/Grant/AuthCode.php | 37 ++++++++++++++++++- src/OAuth2/Grant/GrantTypeInterface.php | 10 ++++- 6 files changed, 93 insertions(+), 2 deletions(-) diff --git a/src/OAuth2/Exception/ClientException.php b/src/OAuth2/Exception/ClientException.php index 0a732431..cfd8090a 100644 --- a/src/OAuth2/Exception/ClientException.php +++ b/src/OAuth2/Exception/ClientException.php @@ -1,7 +1,19 @@ + * @copyright Copyright (c) 2013 University of Lincoln + * @license http://mit-license.org/ + * @link http://github.com/lncd/oauth2 + */ namespace OAuth2\Exception; +/** + * ClientException Exception + */ class ClientException extends OAuth2Exception { diff --git a/src/OAuth2/Exception/InvalidAccessTokenException.php b/src/OAuth2/Exception/InvalidAccessTokenException.php index a7240992..fa598bd6 100644 --- a/src/OAuth2/Exception/InvalidAccessTokenException.php +++ b/src/OAuth2/Exception/InvalidAccessTokenException.php @@ -1,7 +1,19 @@ + * @copyright Copyright (c) 2013 University of Lincoln + * @license http://mit-license.org/ + * @link http://github.com/lncd/oauth2 + */ namespace OAuth2\Exception; +/** + * InvalidAccessToken Exception + */ class InvalidAccessTokenException extends OAuth2Exception { diff --git a/src/OAuth2/Exception/InvalidGrantTypeException.php b/src/OAuth2/Exception/InvalidGrantTypeException.php index 08b31e6a..4cf5c99f 100644 --- a/src/OAuth2/Exception/InvalidGrantTypeException.php +++ b/src/OAuth2/Exception/InvalidGrantTypeException.php @@ -1,7 +1,19 @@ + * @copyright Copyright (c) 2013 University of Lincoln + * @license http://mit-license.org/ + * @link http://github.com/lncd/oauth2 + */ namespace OAuth2\Exception; +/** + * InvalidGrantTypeException Exception + */ class InvalidGrantTypeException extends OAuth2Exception { diff --git a/src/OAuth2/Exception/OAuth2Exception.php b/src/OAuth2/Exception/OAuth2Exception.php index df4b6bb8..ad294199 100644 --- a/src/OAuth2/Exception/OAuth2Exception.php +++ b/src/OAuth2/Exception/OAuth2Exception.php @@ -1,7 +1,19 @@ + * @copyright Copyright (c) 2013 University of Lincoln + * @license http://mit-license.org/ + * @link http://github.com/lncd/oauth2 + */ namespace OAuth2\Exception; +/** + * Exception class + */ class OAuth2Exception extends \Exception { diff --git a/src/OAuth2/Grant/AuthCode.php b/src/OAuth2/Grant/AuthCode.php index 9760694e..38c0316c 100644 --- a/src/OAuth2/Grant/AuthCode.php +++ b/src/OAuth2/Grant/AuthCode.php @@ -1,4 +1,13 @@ + * @copyright Copyright (c) 2013 University of Lincoln + * @license http://mit-license.org/ + * @link http://github.com/lncd/oauth2 + */ namespace OAuth2\Grant; @@ -10,26 +19,52 @@ use OAuth2\Storage\SessionInterface; use OAuth2\Storage\ClientInterface; use OAuth2\Storage\ScopeInterface; +/** + * Auth code grant class + */ class AuthCode implements GrantTypeInterface { + /** + * Grant identifier + * @var string + */ protected $identifier = 'authorization_code'; + + /** + * Response type + * @var string + */ protected $responseType = 'code'; + /** + * Return the identifier + * @return string + */ public function getIdentifier() { return $this->identifier; } + /** + * Return the response type + * @return string + */ public function getResponseType() { return $this->responseType; } + /** + * Complete the auth code grant + * @param null|array $inputParams + * @return array + */ public function completeFlow($inputParams = null) { + // Get the required params $authParams = AuthServer::getParam(array('client_id', 'client_secret', 'redirect_uri', 'code'), 'post', $inputParams); - if (is_null($authParams['client_id'])) { + if (is_null($authParams['client_id'])) { throw new Exception\ClientException(sprintf(AuthServer::getExceptionMessage('invalid_request'), 'client_id'), 0); } diff --git a/src/OAuth2/Grant/GrantTypeInterface.php b/src/OAuth2/Grant/GrantTypeInterface.php index e9444537..b05c959e 100644 --- a/src/OAuth2/Grant/GrantTypeInterface.php +++ b/src/OAuth2/Grant/GrantTypeInterface.php @@ -1,4 +1,13 @@ + * @copyright Copyright (c) 2013 University of Lincoln + * @license http://mit-license.org/ + * @link http://github.com/lncd/oauth2 + */ namespace OAuth2\Grant; @@ -39,7 +48,6 @@ interface GrantTypeInterface * * * @param null|array $inputParams Null unless the input parameters have been manually set - * @param array $authParams The authorisation paramaters that have been set so far in the request * @return array An array of parameters to be passed back to the client */ public function completeFlow($inputParams = null); From 92ce378a9364fac27f80c4c9b3bb0c6f5c98dc49 Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Wed, 13 Feb 2013 19:37:40 +0000 Subject: [PATCH 101/113] Added more files+folders to ignore --- .gitignore | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 3c44ccf9..e9100837 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,6 @@ /docs/build/ /build/logs/ /build/coverage/ -test \ No newline at end of file +test +/docs/ +/testing/ \ No newline at end of file From 246732153cd59c1c04db97287ba5349e33f3e0cf Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Wed, 13 Feb 2013 19:39:43 +0000 Subject: [PATCH 102/113] Updated grantTypes to use AuthServer::getParam() --- src/OAuth2/Grant/ClientCredentials.php | 49 ++++++++++++++---- src/OAuth2/Grant/Password.php | 70 ++++++++++++++++++-------- src/OAuth2/Grant/RefreshToken.php | 18 ++----- 3 files changed, 91 insertions(+), 46 deletions(-) diff --git a/src/OAuth2/Grant/ClientCredentials.php b/src/OAuth2/Grant/ClientCredentials.php index c2325e81..3bb590bb 100644 --- a/src/OAuth2/Grant/ClientCredentials.php +++ b/src/OAuth2/Grant/ClientCredentials.php @@ -1,4 +1,13 @@ + * @copyright Copyright (c) 2013 University of Lincoln + * @license http://mit-license.org/ + * @link http://github.com/lncd/oauth2 + */ namespace OAuth2\Grant; @@ -10,42 +19,60 @@ use OAuth2\Storage\SessionInterface; use OAuth2\Storage\ClientInterface; use OAuth2\Storage\ScopeInterface; +/** + * Client credentials grant class + */ class ClientCredentials implements GrantTypeInterface { + /** + * Grant identifier + * @var string + */ protected $identifier = 'client_credentials'; + + /** + * Response type + * @var string + */ protected $responseType = null; + /** + * Return the identifier + * @return string + */ public function getIdentifier() { return $this->identifier; } + /** + * Return the response type + * @return string + */ public function getResponseType() { return $this->responseType; } - public function completeFlow($inputParams = null, $authParams = array()) + /** + * Complete the client credentials grant + * @param null|array $inputParams + * @return array + */ + public function completeFlow($inputParams = null) { - // Client ID - $authParams['client_id'] = (isset($inputParams['client_id'])) ? - $inputParams['client_id'] : - AuthServer::getRequest()->post('client_id'); + // Get the required params + $authParams = AuthServer::getParam(array('client_id', 'client_secret'), 'post', $inputParams); if (is_null($authParams['client_id'])) { throw new Exception\ClientException(sprintf(AuthServer::getExceptionMessage('invalid_request'), 'client_id'), 0); } - // Client secret - $authParams['client_secret'] = (isset($inputParams['client_secret'])) ? - $inputParams['client_secret'] : - AuthServer::getRequest()->post('client_secret'); - if (is_null($authParams['client_secret'])) { throw new Exception\ClientException(sprintf(AuthServer::getExceptionMessage('invalid_request'), 'client_secret'), 0); } - // Validate client ID and redirect URI + // Validate client ID and client secret $clientDetails = AuthServer::getStorage('client')->getClient($authParams['client_id'], $authParams['client_secret']); if ($clientDetails === false) { diff --git a/src/OAuth2/Grant/Password.php b/src/OAuth2/Grant/Password.php index b227083e..1cf61c74 100644 --- a/src/OAuth2/Grant/Password.php +++ b/src/OAuth2/Grant/Password.php @@ -1,4 +1,13 @@ + * @copyright Copyright (c) 2013 University of Lincoln + * @license http://mit-license.org/ + * @link http://github.com/lncd/oauth2 + */ namespace OAuth2\Grant; @@ -10,27 +19,60 @@ use OAuth2\Storage\SessionInterface; use OAuth2\Storage\ClientInterface; use OAuth2\Storage\ScopeInterface; +/** + * Password grant class + */ class Password implements GrantTypeInterface { + /** + * Grant identifier + * @var string + */ protected $identifier = 'password'; + + /** + * Response type + * @var string + */ protected $responseType = null; + + /** + * Callback to authenticate a user's name and password + * @var function + */ protected $callback = null; + /** + * Return the identifier + * @return string + */ public function getIdentifier() { return $this->identifier; } + /** + * Return the response type + * @return string + */ public function getResponseType() { return $this->responseType; } + /** + * Set the callback to verify a user's username and password + * @param function $callback The callback function + */ public function setVerifyCredentialsCallback($callback) { $this->callback = $callback; } + /** + * Return the callback function + * @return function + */ protected function getVerifyCredentialsCallback() { if (is_null($this->callback) || ! is_callable($this->callback)) { @@ -40,22 +82,20 @@ class Password implements GrantTypeInterface { return $this->callback; } - public function completeFlow($inputParams = null, $authParams = array()) + /** + * Complete the password grant + * @param null|array $inputParams + * @return array + */ + public function completeFlow($inputParams = null) { - // Client ID - $authParams['client_id'] = (isset($inputParams['client_id'])) ? - $inputParams['client_id'] : - AuthServer::getRequest()->post('client_id'); + // Get the required params + $authParams = AuthServer::getParam(array('client_id', 'client_secret', 'username', 'password'), 'post', $inputParams); if (is_null($authParams['client_id'])) { throw new Exception\ClientException(sprintf(AuthServer::getExceptionMessage('invalid_request'), 'client_id'), 0); } - // Client secret - $authParams['client_secret'] = (isset($inputParams['client_secret'])) ? - $inputParams['client_secret'] : - AuthServer::getRequest()->post('client_secret'); - if (is_null($authParams['client_secret'])) { throw new Exception\ClientException(sprintf(AuthServer::getExceptionMessage('invalid_request'), 'client_secret'), 0); } @@ -69,20 +109,10 @@ class Password implements GrantTypeInterface { $authParams['client_details'] = $clientDetails; - // User's username - $authParams['username'] = (isset($inputParams['username'])) ? - $inputParams['username'] : - AuthServer::getRequest()->post('username'); - if (is_null($authParams['username'])) { throw new Exception\ClientException(sprintf(AuthServer::getExceptionMessage('invalid_request'), 'username'), 0); } - // User's password - $authParams['password'] = (isset($inputParams['password'])) ? - $inputParams['password'] : - AuthServer::getRequest()->post('password'); - if (is_null($authParams['password'])) { throw new Exception\ClientException(sprintf(AuthServer::getExceptionMessage('invalid_request'), 'password'), 0); } diff --git a/src/OAuth2/Grant/RefreshToken.php b/src/OAuth2/Grant/RefreshToken.php index 1f89d36c..b396e2d1 100644 --- a/src/OAuth2/Grant/RefreshToken.php +++ b/src/OAuth2/Grant/RefreshToken.php @@ -27,25 +27,18 @@ class RefreshToken implements GrantTypeInterface { public function completeFlow($inputParams = null, $authParams = array()) { - // Client ID - $authParams['client_id'] = (isset($inputParams['client_id'])) ? - $inputParams['client_id'] : - AuthServer::getRequest()->post('client_id'); + // Get the required params + $authParams = AuthServer::getParam(array('client_id', 'client_secret', 'refresh_token'), 'post', $inputParams); if (is_null($authParams['client_id'])) { throw new Exception\ClientException(sprintf(AuthServer::getExceptionMessage('invalid_request'), 'client_id'), 0); } - // Client secret - $authParams['client_secret'] = (isset($inputParams['client_secret'])) ? - $inputParams['client_secret'] : - AuthServer::getRequest()->post('client_secret'); - if (is_null($authParams['client_secret'])) { throw new Exception\ClientException(sprintf(AuthServer::getExceptionMessage('invalid_request'), 'client_secret'), 0); } - // Validate client ID and redirect URI + // Validate client ID and client secret $clientDetails = AuthServer::getStorage('client')->getClient($authParams['client_id'], $authParams['client_secret']); if ($clientDetails === false) { @@ -54,11 +47,6 @@ class RefreshToken implements GrantTypeInterface { $authParams['client_details'] = $clientDetails; - // Refresh token - $authParams['refresh_token'] = (isset($inputParams['refresh_token'])) ? - $inputParams['refresh_token'] : - AuthServer::getRequest()->post('refresh_token'); - if (is_null($authParams['refresh_token'])) { throw new Exception\ClientException(sprintf(AuthServer::getExceptionMessage('invalid_request'), 'refresh_token'), 0); } From f818bdf40e47eb441d057a722337ae3938c04cac Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Wed, 13 Feb 2013 19:59:08 +0000 Subject: [PATCH 103/113] Updated docblocks --- src/OAuth2/Grant/RefreshToken.php | 36 ++++++++++++- src/OAuth2/Storage/ClientInterface.php | 9 ++++ src/OAuth2/Storage/ScopeInterface.php | 9 ++++ src/OAuth2/Storage/SessionInterface.php | 70 +++++++++++++++++++------ src/OAuth2/Util/RedirectUri.php | 19 +++++++ src/OAuth2/Util/SecureKey.php | 17 ++++++ 6 files changed, 144 insertions(+), 16 deletions(-) diff --git a/src/OAuth2/Grant/RefreshToken.php b/src/OAuth2/Grant/RefreshToken.php index b396e2d1..bd7839ca 100644 --- a/src/OAuth2/Grant/RefreshToken.php +++ b/src/OAuth2/Grant/RefreshToken.php @@ -1,4 +1,13 @@ + * @copyright Copyright (c) 2013 University of Lincoln + * @license http://mit-license.org/ + * @link http://github.com/lncd/oauth2 + */ namespace OAuth2\Grant; @@ -10,22 +19,47 @@ use OAuth2\Storage\SessionInterface; use OAuth2\Storage\ClientInterface; use OAuth2\Storage\ScopeInterface; +/** + * Referesh token grant + */ class RefreshToken implements GrantTypeInterface { + /** + * Grant identifier + * @var string + */ protected $identifier = 'refresh_token'; + + /** + * Response type + * @var string + */ protected $responseType = null; + /** + * Return the identifier + * @return string + */ public function getIdentifier() { return $this->identifier; } + /** + * Return the response type + * @return string + */ public function getResponseType() { return $this->responseType; } - public function completeFlow($inputParams = null, $authParams = array()) + /** + * Complete the refresh token grant + * @param null|array $inputParams + * @return array + */ + public function completeFlow($inputParams = null) { // Get the required params $authParams = AuthServer::getParam(array('client_id', 'client_secret', 'refresh_token'), 'post', $inputParams); diff --git a/src/OAuth2/Storage/ClientInterface.php b/src/OAuth2/Storage/ClientInterface.php index 2abee251..605c42a9 100644 --- a/src/OAuth2/Storage/ClientInterface.php +++ b/src/OAuth2/Storage/ClientInterface.php @@ -1,4 +1,13 @@ + * @copyright Copyright (c) 2013 University of Lincoln + * @license http://mit-license.org/ + * @link http://github.com/lncd/oauth2 + */ namespace OAuth2\Storage; diff --git a/src/OAuth2/Storage/ScopeInterface.php b/src/OAuth2/Storage/ScopeInterface.php index 8777aee6..82c71c39 100644 --- a/src/OAuth2/Storage/ScopeInterface.php +++ b/src/OAuth2/Storage/ScopeInterface.php @@ -1,4 +1,13 @@ + * @copyright Copyright (c) 2013 University of Lincoln + * @license http://mit-license.org/ + * @link http://github.com/lncd/oauth2 + */ namespace OAuth2\Storage; diff --git a/src/OAuth2/Storage/SessionInterface.php b/src/OAuth2/Storage/SessionInterface.php index 7e9fd368..1c2632f6 100644 --- a/src/OAuth2/Storage/SessionInterface.php +++ b/src/OAuth2/Storage/SessionInterface.php @@ -1,4 +1,13 @@ + * @copyright Copyright (c) 2013 University of Lincoln + * @license http://mit-license.org/ + * @link http://github.com/lncd/oauth2 + */ namespace OAuth2\Storage; @@ -16,15 +25,16 @@ interface SessionInterface * $accessToken, $stage, UNIX_TIMESTAMP(NOW()), UNIX_TIMESTAMP(NOW())) * * - * @param string $clientId The client ID - * @param string $redirectUri The redirect URI - * @param string $type The session owner's type (default = "user") - * @param string $typeId The session owner's ID (default = "null") - * @param string $authCode The authorisation code (default = "null") - * @param string $accessToken The access token (default = "null") - * @param string $refreshToken The refresh token (default = "null") - * @param string $stage The stage of the session (default ="request") - * @return int The session ID + * @param string $clientId The client ID + * @param string $redirectUri The redirect URI + * @param string $type The session owner's type (default = "user") + * @param string $typeId The session owner's ID (default = "null") + * @param string $authCode The authorisation code (default = "null") + * @param string $accessToken The access token (default = "null") + * @param string $refreshToken The refresh token (default = "null") + * @param int $accessTokenExpire The expiry time of an access token as a unix timestamp + * @param string $stage The stage of the session (default ="request") + * @return int The session ID */ public function createSession( $clientId, @@ -49,11 +59,12 @@ interface SessionInterface * id = $sessionId * * - * @param string $sessionId The session ID - * @param string $authCode The authorisation code (default = "null") - * @param string $accessToken The access token (default = "null") - * @param string $refreshToken The refresh token (default = "null") - * @param string $stage The stage of the session (default ="request") + * @param string $sessionId The session ID + * @param string $authCode The authorisation code (default = "null") + * @param string $accessToken The access token (default = "null") + * @param string $refreshToken The refresh token (default = "null") + * @param int $accessTokenExpire The expiry time of an access token as a unix timestamp + * @param string $stage The stage of the session (default ="request") * @return void */ public function updateSession( @@ -125,6 +136,29 @@ interface SessionInterface $authCode ); + /** + * Validate an access token + * + * Example SQL query: + * + * + * SELECT id, owner_id, owner_type FROM oauth_sessions WHERE access_token = $accessToken + * + * + * Response: + * + * + * Array + * ( + * [id] => (int) The session ID + * [owner_type] => (string) The owner type + * [owner_id] => (string) The owner ID + * ) + * + * + * @param [type] $accessToken [description] + * @return [type] [description] + */ public function validateAccessToken($accessToken); /** @@ -142,6 +176,12 @@ interface SessionInterface */ public function getAccessToken($sessionId); + /** + * Validate a refresh token + * @param string $refreshToken The refresh token + * @param string $clientId The client ID + * @return int The session ID + */ public function validateRefreshToken($refreshToken, $clientId); /** @@ -174,7 +214,7 @@ interface SessionInterface * * * @param int $sessionId The session ID - * @param string $scope The scope ID + * @param string $scopeId The scope ID * @return void */ public function associateScope($sessionId, $scopeId); diff --git a/src/OAuth2/Util/RedirectUri.php b/src/OAuth2/Util/RedirectUri.php index 580758e5..c123b187 100644 --- a/src/OAuth2/Util/RedirectUri.php +++ b/src/OAuth2/Util/RedirectUri.php @@ -1,9 +1,28 @@ + * @copyright Copyright (c) 2013 University of Lincoln + * @license http://mit-license.org/ + * @link http://github.com/lncd/oauth2 + */ namespace OAuth2\Util; +/** + * RedirectUri class + */ class RedirectUri { + /** + * Generate a new redirect uri + * @param string $uri The base URI + * @param array $params The query string parameters + * @param string $queryDelimeter The query string delimeter (default: "?") + * @return string The updated URI + */ public static function make($uri, $params = array(), $queryDelimeter = '?') { $uri .= (strstr($uri, $queryDelimeter) === false) ? $queryDelimeter : '&'; diff --git a/src/OAuth2/Util/SecureKey.php b/src/OAuth2/Util/SecureKey.php index 35a55298..d6450146 100644 --- a/src/OAuth2/Util/SecureKey.php +++ b/src/OAuth2/Util/SecureKey.php @@ -1,9 +1,26 @@ + * @copyright Copyright (c) 2013 University of Lincoln + * @license http://mit-license.org/ + * @link http://github.com/lncd/oauth2 + */ namespace OAuth2\Util; +/** + * SecureKey class + */ class SecureKey { + /** + * Generate a new unique code + * @param integer $len Length of the generated code + * @return string + */ public static function make($len = 40) { // We generate twice as many bytes here because we want to ensure we have From e86d5cb3f1be8c916302801c963432c383d80a4e Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Wed, 13 Feb 2013 20:12:51 +0000 Subject: [PATCH 104/113] Broke up grants into their own tests --- tests/authentication/AuthServerTest.php | 621 ------------------ .../ClientCredentialsGrantTest.php | 189 ++++++ tests/authentication/PasswordGrantTest.php | 347 ++++++++++ tests/authentication/RefreshTokenTest.php | 233 +++++++ 4 files changed, 769 insertions(+), 621 deletions(-) create mode 100644 tests/authentication/ClientCredentialsGrantTest.php create mode 100644 tests/authentication/PasswordGrantTest.php create mode 100644 tests/authentication/RefreshTokenTest.php diff --git a/tests/authentication/AuthServerTest.php b/tests/authentication/AuthServerTest.php index f5f534cd..a6b2b1b3 100644 --- a/tests/authentication/AuthServerTest.php +++ b/tests/authentication/AuthServerTest.php @@ -595,627 +595,6 @@ class Authentication_Server_test extends PHPUnit_Framework_TestCase $this->assertEquals(time()+$a::getExpiresIn(), $v['expires']); } - public function test_issueAccessToken_with_refresh_token() - { - $this->client->shouldReceive('getClient')->andReturn(array( - 'client_id' => 1234, - 'client_secret' => 5678, - 'redirect_uri' => 'http://foo/redirect', - 'name' => 'Example Client' - )); - - $this->session->shouldReceive('validateAuthCode')->andReturn(1); - $this->session->shouldReceive('updateSession')->andReturn(null); - - $a = $this->returnDefault(); - $a->addGrantType(new OAuth2\Grant\AuthCode()); - $a->addGrantType(new OAuth2\Grant\RefreshToken()); - - $_POST['grant_type'] = 'authorization_code'; - $_POST['client_id'] = 1234; - $_POST['client_secret'] = 5678; - $_POST['redirect_uri'] = 'http://foo/redirect'; - $_POST['code'] = 'foobar'; - - $request = new OAuth2\Util\Request(array(), $_POST); - $a->setRequest($request); - - $v = $a->issueAccessToken(); - - $this->assertArrayHasKey('access_token', $v); - $this->assertArrayHasKey('token_type', $v); - $this->assertArrayHasKey('expires', $v); - $this->assertArrayHasKey('expires_in', $v); - $this->assertArrayHasKey('refresh_token', $v); - - $this->assertEquals($a::getExpiresIn(), $v['expires_in']); - $this->assertEquals(time()+$a::getExpiresIn(), $v['expires']); - } - - /** - * @expectedException OAuth2\Exception\ClientException - * @expectedExceptionCode 0 - */ - public function test_issueAccessToken_refreshTokenGrant_missingClientId() - { - $a = $this->returnDefault(); - $a->addGrantType(new OAuth2\Grant\RefreshToken()); - - $request = new OAuth2\Util\Request(array(), $_POST); - $a->setRequest($request); - - $v = $a->issueAccessToken(array( - 'grant_type' => 'refresh_token' - )); - } - - /** - * @expectedException OAuth2\Exception\ClientException - * @expectedExceptionCode 0 - */ - public function test_issueAccessToken_refreshTokenGrant_missingClientSecret() - { - $a = $this->returnDefault(); - $a->addGrantType(new OAuth2\Grant\RefreshToken()); - - $request = new OAuth2\Util\Request(array(), $_POST); - $a->setRequest($request); - - $v = $a->issueAccessToken(array( - 'grant_type' => 'refresh_token', - 'client_id' => 1234 - )); - } - - /** - * @expectedException OAuth2\Exception\ClientException - * @expectedExceptionCode 8 - */ - public function test_issueAccessToken_refreshTokenGrant_badClient() - { - $this->client->shouldReceive('getClient')->andReturn(false); - - $a = $this->returnDefault(); - $a->addGrantType(new OAuth2\Grant\RefreshToken()); - - $request = new OAuth2\Util\Request(array(), $_POST); - $a->setRequest($request); - - $v = $a->issueAccessToken(array( - 'grant_type' => 'refresh_token', - 'client_id' => 1234, - 'client_secret' => 5678 - )); - } - - /** - * @expectedException OAuth2\Exception\ClientException - * @expectedExceptionCode 0 - */ - public function test_issueAccessToken_refreshTokenGrant_missingRefreshToken() - { - $this->client->shouldReceive('getClient')->andReturn(array()); - - $a = $this->returnDefault(); - $a->addGrantType(new OAuth2\Grant\RefreshToken()); - - $request = new OAuth2\Util\Request(array(), $_POST); - $a->setRequest($request); - - $v = $a->issueAccessToken(array( - 'grant_type' => 'refresh_token', - 'client_id' => 1234, - 'client_secret' => 5678, - //'refresh_token' => - )); - } - - /** - * @expectedException OAuth2\Exception\ClientException - * @expectedExceptionCode 0 - */ - public function test_issueAccessToken_refreshTokenGrant_badRefreshToken() - { - $this->client->shouldReceive('getClient')->andReturn(array()); - $this->client->shouldReceive('validateRefreshToken')->andReturn(false); - - $a = $this->returnDefault(); - $a->addGrantType(new OAuth2\Grant\RefreshToken()); - - $request = new OAuth2\Util\Request(array(), $_POST); - $a->setRequest($request); - - $v = $a->issueAccessToken(array( - 'grant_type' => 'refresh_token', - 'client_id' => 1234, - 'client_secret' => 5678, - 'refresh_token' => 'abcdef' - )); - } - - public function test_issueAccessToken_refreshTokenGrant_passedInput() - { - $this->client->shouldReceive('getClient')->andReturn(array( - 'client_id' => 1234, - 'client_secret' => 5678, - 'redirect_uri' => 'http://foo/redirect', - 'name' => 'Example Client' - )); - - $this->client->shouldReceive('validateRefreshToken')->andReturn(1); - - $this->session->shouldReceive('validateAuthCode')->andReturn(1); - $this->session->shouldReceive('updateSession')->andReturn(null); - $this->session->shouldReceive('updateRefreshToken')->andReturn(null); - - $a = $this->returnDefault(); - $a->addGrantType(new OAuth2\Grant\RefreshToken()); - - $_POST['grant_type'] = 'refresh_token'; - $_POST['client_id'] = 1234; - $_POST['client_secret'] = 5678; - $_POST['refresh_token'] = 'abcdef'; - - $request = new OAuth2\Util\Request(array(), $_POST); - $a->setRequest($request); - - $v = $a->issueAccessToken(); - - $this->assertArrayHasKey('access_token', $v); - $this->assertArrayHasKey('token_type', $v); - $this->assertArrayHasKey('expires', $v); - $this->assertArrayHasKey('expires_in', $v); - $this->assertArrayHasKey('refresh_token', $v); - - $this->assertEquals($a::getExpiresIn(), $v['expires_in']); - $this->assertEquals(time()+$a::getExpiresIn(), $v['expires']); - } - - public function test_issueAccessToken_refreshTokenGrant() - { - $this->client->shouldReceive('getClient')->andReturn(array( - 'client_id' => 1234, - 'client_secret' => 5678, - 'redirect_uri' => 'http://foo/redirect', - 'name' => 'Example Client' - )); - - $this->client->shouldReceive('validateRefreshToken')->andReturn(1); - - $this->session->shouldReceive('validateAuthCode')->andReturn(1); - $this->session->shouldReceive('updateSession')->andReturn(null); - $this->session->shouldReceive('updateRefreshToken')->andReturn(null); - - $a = $this->returnDefault(); - $a->addGrantType(new OAuth2\Grant\RefreshToken()); - - $v = $a->issueAccessToken(array( - 'grant_type' => 'refresh_token', - 'client_id' => 1234, - 'client_secret' => 5678, - 'refresh_token' => 'abcdef', - )); - - $this->assertArrayHasKey('access_token', $v); - $this->assertArrayHasKey('token_type', $v); - $this->assertArrayHasKey('expires', $v); - $this->assertArrayHasKey('expires_in', $v); - $this->assertArrayHasKey('refresh_token', $v); - - $this->assertEquals($a::getExpiresIn(), $v['expires_in']); - $this->assertEquals(time()+$a::getExpiresIn(), $v['expires']); - } - - /** - * @expectedException OAuth2\Exception\ClientException - * @expectedExceptionCode 0 - */ - public function test_issueAccessToken_clientCredentialsGrant_missingClientId() - { - $a = $this->returnDefault(); - $a->addGrantType(new OAuth2\Grant\ClientCredentials()); - - $request = new OAuth2\Util\Request(array(), $_POST); - $a->setRequest($request); - - $v = $a->issueAccessToken(array( - 'grant_type' => 'client_credentials' - )); - } - - /** - * @expectedException OAuth2\Exception\ClientException - * @expectedExceptionCode 0 - */ - public function test_issueAccessToken_clientCredentialsGrant_missingClientPassword() - { - $a = $this->returnDefault(); - $a->addGrantType(new OAuth2\Grant\ClientCredentials()); - - $request = new OAuth2\Util\Request(array(), $_POST); - $a->setRequest($request); - - $v = $a->issueAccessToken(array( - 'grant_type' => 'client_credentials', - 'client_id' => 1234 - )); - } - - /** - * @expectedException OAuth2\Exception\ClientException - * @expectedExceptionCode 8 - */ - public function test_issueAccessToken_clientCredentialsGrant_badClient() - { - $this->client->shouldReceive('getClient')->andReturn(false); - - $a = $this->returnDefault(); - $a->addGrantType(new OAuth2\Grant\ClientCredentials()); - - $request = new OAuth2\Util\Request(array(), $_POST); - $a->setRequest($request); - - $v = $a->issueAccessToken(array( - 'grant_type' => 'client_credentials', - 'client_id' => 1234, - 'client_secret' => 5678 - )); - } - - function test_issueAccessToken_clientCredentialsGrant_passedInput() - { - $this->client->shouldReceive('getClient')->andReturn(array( - 'client_id' => 1234, - 'client_secret' => 5678, - 'redirect_uri' => 'http://foo/redirect', - 'name' => 'Example Client' - )); - - $this->client->shouldReceive('validateRefreshToken')->andReturn(1); - - $this->session->shouldReceive('validateAuthCode')->andReturn(1); - $this->session->shouldReceive('createSession')->andReturn(1); - $this->session->shouldReceive('deleteSession')->andReturn(null); - $this->session->shouldReceive('updateRefreshToken')->andReturn(null); - - $a = $this->returnDefault(); - $a->addGrantType(new OAuth2\Grant\ClientCredentials()); - - $v = $a->issueAccessToken(array( - 'grant_type' => 'client_credentials', - 'client_id' => 1234, - 'client_secret' => 5678 - )); - - $this->assertArrayHasKey('access_token', $v); - $this->assertArrayHasKey('token_type', $v); - $this->assertArrayHasKey('expires', $v); - $this->assertArrayHasKey('expires_in', $v); - $this->assertArrayHasKey('refresh_token', $v); - - $this->assertEquals($a::getExpiresIn(), $v['expires_in']); - $this->assertEquals(time()+$a::getExpiresIn(), $v['expires']); - } - - function test_issueAccessToken_clientCredentialsGrant() - { - $this->client->shouldReceive('getClient')->andReturn(array( - 'client_id' => 1234, - 'client_secret' => 5678, - 'redirect_uri' => 'http://foo/redirect', - 'name' => 'Example Client' - )); - - $this->client->shouldReceive('validateRefreshToken')->andReturn(1); - - $this->session->shouldReceive('validateAuthCode')->andReturn(1); - $this->session->shouldReceive('createSession')->andReturn(1); - $this->session->shouldReceive('deleteSession')->andReturn(null); - $this->session->shouldReceive('updateRefreshToken')->andReturn(null); - - $a = $this->returnDefault(); - $a->addGrantType(new OAuth2\Grant\ClientCredentials()); - - $_POST['grant_type'] = 'client_credentials'; - $_POST['client_id'] = 1234; - $_POST['client_secret'] = 5678; - - $request = new OAuth2\Util\Request(array(), $_POST); - $a->setRequest($request); - - $v = $a->issueAccessToken(); - - $this->assertArrayHasKey('access_token', $v); - $this->assertArrayHasKey('token_type', $v); - $this->assertArrayHasKey('expires', $v); - $this->assertArrayHasKey('expires_in', $v); - $this->assertArrayHasKey('refresh_token', $v); - - $this->assertEquals($a::getExpiresIn(), $v['expires_in']); - $this->assertEquals(time()+$a::getExpiresIn(), $v['expires']); - } - - /** - * @expectedException OAuth2\Exception\ClientException - * @expectedExceptionCode 0 - */ - public function test_issueAccessToken_passwordGrant_missingClientId() - { - $a = $this->returnDefault(); - $a->addGrantType(new OAuth2\Grant\Password()); - - $request = new OAuth2\Util\Request(array(), $_POST); - $a->setRequest($request); - - $v = $a->issueAccessToken(array( - 'grant_type' => 'client_credentials' - )); - } - - /** - * @expectedException OAuth2\Exception\ClientException - * @expectedExceptionCode 0 - */ - public function test_issueAccessToken_passwordGrant_missingClientPassword() - { - $a = $this->returnDefault(); - $a->addGrantType(new OAuth2\Grant\Password()); - - $request = new OAuth2\Util\Request(array(), $_POST); - $a->setRequest($request); - - $v = $a->issueAccessToken(array( - 'grant_type' => 'password', - 'client_id' => 1234 - )); - } - - /** - * @expectedException OAuth2\Exception\ClientException - * @expectedExceptionCode 8 - */ - public function test_issueAccessToken_passwordGrant_badClient() - { - $this->client->shouldReceive('getClient')->andReturn(false); - - $a = $this->returnDefault(); - $a->addGrantType(new OAuth2\Grant\Password()); - - $request = new OAuth2\Util\Request(array(), $_POST); - $a->setRequest($request); - - $v = $a->issueAccessToken(array( - 'grant_type' => 'password', - 'client_id' => 1234, - 'client_secret' => 5678 - )); - } - - /** - * @expectedException OAuth2\Exception\InvalidGrantTypeException - */ - function test_issueAccessToken_passwordGrant_invalidCallback() - { - $this->client->shouldReceive('getClient')->andReturn(array( - 'client_id' => 1234, - 'client_secret' => 5678, - 'redirect_uri' => 'http://foo/redirect', - 'name' => 'Example Client' - )); - - $this->client->shouldReceive('validateRefreshToken')->andReturn(1); - - $this->session->shouldReceive('validateAuthCode')->andReturn(1); - $this->session->shouldReceive('createSession')->andReturn(1); - $this->session->shouldReceive('deleteSession')->andReturn(null); - $this->session->shouldReceive('updateRefreshToken')->andReturn(null); - - $testCredentials = null; - - $a = $this->returnDefault(); - $pgrant = new OAuth2\Grant\Password(); - $pgrant->setVerifyCredentialsCallback($testCredentials); - $a->addGrantType($pgrant); - - $v = $a->issueAccessToken(array( - 'grant_type' => 'password', - 'client_id' => 1234, - 'client_secret' => 5678, - 'username' => 'foo', - 'password' => 'bar' - )); - } - - /** - * @expectedException OAuth2\Exception\ClientException - * @expectedExceptionCode 0 - */ - function test_issueAccessToken_passwordGrant_missingUsername() - { - $this->client->shouldReceive('getClient')->andReturn(array( - 'client_id' => 1234, - 'client_secret' => 5678, - 'redirect_uri' => 'http://foo/redirect', - 'name' => 'Example Client' - )); - - $this->client->shouldReceive('validateRefreshToken')->andReturn(1); - - $this->session->shouldReceive('validateAuthCode')->andReturn(1); - $this->session->shouldReceive('createSession')->andReturn(1); - $this->session->shouldReceive('deleteSession')->andReturn(null); - $this->session->shouldReceive('updateRefreshToken')->andReturn(null); - - $testCredentials = function($u, $p) { return false; }; - - $a = $this->returnDefault(); - $pgrant = new OAuth2\Grant\Password(); - $pgrant->setVerifyCredentialsCallback($testCredentials); - $a->addGrantType($pgrant); - - $v = $a->issueAccessToken(array( - 'grant_type' => 'password', - 'client_id' => 1234, - 'client_secret' => 5678 - )); - } - - /** - * @expectedException OAuth2\Exception\ClientException - * @expectedExceptionCode 0 - */ - function test_issueAccessToken_passwordGrant_missingPassword() - { - $this->client->shouldReceive('getClient')->andReturn(array( - 'client_id' => 1234, - 'client_secret' => 5678, - 'redirect_uri' => 'http://foo/redirect', - 'name' => 'Example Client' - )); - - $this->client->shouldReceive('validateRefreshToken')->andReturn(1); - - $this->session->shouldReceive('validateAuthCode')->andReturn(1); - $this->session->shouldReceive('createSession')->andReturn(1); - $this->session->shouldReceive('deleteSession')->andReturn(null); - $this->session->shouldReceive('updateRefreshToken')->andReturn(null); - - $testCredentials = function($u, $p) { return false; }; - - $a = $this->returnDefault(); - $pgrant = new OAuth2\Grant\Password(); - $pgrant->setVerifyCredentialsCallback($testCredentials); - $a->addGrantType($pgrant); - - $v = $a->issueAccessToken(array( - 'grant_type' => 'password', - 'client_id' => 1234, - 'client_secret' => 5678, - 'username' => 'foo' - )); - } - - /** - * @expectedException OAuth2\Exception\ClientException - * @expectedExceptionCode 0 - */ - function test_issueAccessToken_passwordGrant_badCredentials() - { - $this->client->shouldReceive('getClient')->andReturn(array( - 'client_id' => 1234, - 'client_secret' => 5678, - 'redirect_uri' => 'http://foo/redirect', - 'name' => 'Example Client' - )); - - $this->client->shouldReceive('validateRefreshToken')->andReturn(1); - - $this->session->shouldReceive('validateAuthCode')->andReturn(1); - $this->session->shouldReceive('createSession')->andReturn(1); - $this->session->shouldReceive('deleteSession')->andReturn(null); - $this->session->shouldReceive('updateRefreshToken')->andReturn(null); - - $testCredentials = function($u, $p) { return false; }; - - $a = $this->returnDefault(); - $pgrant = new OAuth2\Grant\Password(); - $pgrant->setVerifyCredentialsCallback($testCredentials); - $a->addGrantType($pgrant); - - $v = $a->issueAccessToken(array( - 'grant_type' => 'password', - 'client_id' => 1234, - 'client_secret' => 5678, - 'username' => 'foo', - 'password' => 'bar' - )); - } - - function test_issueAccessToken_passwordGrant_passedInput() - { - $this->client->shouldReceive('getClient')->andReturn(array( - 'client_id' => 1234, - 'client_secret' => 5678, - 'redirect_uri' => 'http://foo/redirect', - 'name' => 'Example Client' - )); - - $this->client->shouldReceive('validateRefreshToken')->andReturn(1); - - $this->session->shouldReceive('validateAuthCode')->andReturn(1); - $this->session->shouldReceive('createSession')->andReturn(1); - $this->session->shouldReceive('deleteSession')->andReturn(null); - $this->session->shouldReceive('updateRefreshToken')->andReturn(null); - - $testCredentials = function($u, $p) { return 1; }; - - $a = $this->returnDefault(); - $pgrant = new OAuth2\Grant\Password(); - $pgrant->setVerifyCredentialsCallback($testCredentials); - $a->addGrantType($pgrant); - - $v = $a->issueAccessToken(array( - 'grant_type' => 'password', - 'client_id' => 1234, - 'client_secret' => 5678, - 'username' => 'foo', - 'password' => 'bar' - )); - - $this->assertArrayHasKey('access_token', $v); - $this->assertArrayHasKey('token_type', $v); - $this->assertArrayHasKey('expires', $v); - $this->assertArrayHasKey('expires_in', $v); - $this->assertArrayHasKey('refresh_token', $v); - - $this->assertEquals($a::getExpiresIn(), $v['expires_in']); - $this->assertEquals(time()+$a::getExpiresIn(), $v['expires']); - } - - function test_issueAccessToken_passwordGrant() - { - $this->client->shouldReceive('getClient')->andReturn(array( - 'client_id' => 1234, - 'client_secret' => 5678, - 'redirect_uri' => 'http://foo/redirect', - 'name' => 'Example Client' - )); - - $this->client->shouldReceive('validateRefreshToken')->andReturn(1); - - $this->session->shouldReceive('validateAuthCode')->andReturn(1); - $this->session->shouldReceive('createSession')->andReturn(1); - $this->session->shouldReceive('deleteSession')->andReturn(null); - $this->session->shouldReceive('updateRefreshToken')->andReturn(null); - - $testCredentials = function($u, $p) { return 1; }; - - $a = $this->returnDefault(); - $pgrant = new OAuth2\Grant\Password(); - $pgrant->setVerifyCredentialsCallback($testCredentials); - $a->addGrantType($pgrant); - - $_POST['grant_type'] = 'password'; - $_POST['client_id'] = 1234; - $_POST['client_secret'] = 5678; - $_POST['username'] = 'foo'; - $_POST['password'] = 'bar'; - - $request = new OAuth2\Util\Request(array(), $_POST); - $a->setRequest($request); - - $v = $a->issueAccessToken(); - - $this->assertArrayHasKey('access_token', $v); - $this->assertArrayHasKey('token_type', $v); - $this->assertArrayHasKey('expires', $v); - $this->assertArrayHasKey('expires_in', $v); - $this->assertArrayHasKey('refresh_token', $v); - - $this->assertEquals($a::getExpiresIn(), $v['expires_in']); - $this->assertEquals(time()+$a::getExpiresIn(), $v['expires']); - } - public function tearDown() { M::close(); } diff --git a/tests/authentication/ClientCredentialsGrantTest.php b/tests/authentication/ClientCredentialsGrantTest.php new file mode 100644 index 00000000..72e68919 --- /dev/null +++ b/tests/authentication/ClientCredentialsGrantTest.php @@ -0,0 +1,189 @@ +client = M::mock('OAuth2\Storage\ClientInterface'); + $this->session = M::mock('OAuth2\Storage\SessionInterface'); + $this->scope = M::mock('OAuth2\Storage\ScopeInterface'); + } + + private function returnDefault() + { + return new OAuth2\AuthServer($this->client, $this->session, $this->scope); + } + + /** + * @expectedException OAuth2\Exception\ClientException + * @expectedExceptionCode 0 + */ + public function test_issueAccessToken_clientCredentialsGrant_missingClientId() + { + $a = $this->returnDefault(); + $a->addGrantType(new OAuth2\Grant\ClientCredentials()); + + $request = new OAuth2\Util\Request(array(), $_POST); + $a->setRequest($request); + + $v = $a->issueAccessToken(array( + 'grant_type' => 'client_credentials' + )); + } + + /** + * @expectedException OAuth2\Exception\ClientException + * @expectedExceptionCode 0 + */ + public function test_issueAccessToken_clientCredentialsGrant_missingClientPassword() + { + $a = $this->returnDefault(); + $a->addGrantType(new OAuth2\Grant\ClientCredentials()); + + $request = new OAuth2\Util\Request(array(), $_POST); + $a->setRequest($request); + + $v = $a->issueAccessToken(array( + 'grant_type' => 'client_credentials', + 'client_id' => 1234 + )); + } + + /** + * @expectedException OAuth2\Exception\ClientException + * @expectedExceptionCode 8 + */ + public function test_issueAccessToken_clientCredentialsGrant_badClient() + { + $this->client->shouldReceive('getClient')->andReturn(false); + + $a = $this->returnDefault(); + $a->addGrantType(new OAuth2\Grant\ClientCredentials()); + + $request = new OAuth2\Util\Request(array(), $_POST); + $a->setRequest($request); + + $v = $a->issueAccessToken(array( + 'grant_type' => 'client_credentials', + 'client_id' => 1234, + 'client_secret' => 5678 + )); + } + + function test_issueAccessToken_clientCredentialsGrant_passedInput() + { + $this->client->shouldReceive('getClient')->andReturn(array( + 'client_id' => 1234, + 'client_secret' => 5678, + 'redirect_uri' => 'http://foo/redirect', + 'name' => 'Example Client' + )); + + $this->client->shouldReceive('validateRefreshToken')->andReturn(1); + + $this->session->shouldReceive('validateAuthCode')->andReturn(1); + $this->session->shouldReceive('createSession')->andReturn(1); + $this->session->shouldReceive('deleteSession')->andReturn(null); + $this->session->shouldReceive('updateRefreshToken')->andReturn(null); + + $a = $this->returnDefault(); + $a->addGrantType(new OAuth2\Grant\ClientCredentials()); + + $v = $a->issueAccessToken(array( + 'grant_type' => 'client_credentials', + 'client_id' => 1234, + 'client_secret' => 5678 + )); + + $this->assertArrayHasKey('access_token', $v); + $this->assertArrayHasKey('token_type', $v); + $this->assertArrayHasKey('expires', $v); + $this->assertArrayHasKey('expires_in', $v); + + $this->assertEquals($a::getExpiresIn(), $v['expires_in']); + $this->assertEquals(time()+$a::getExpiresIn(), $v['expires']); + } + + function test_issueAccessToken_clientCredentialsGrant() + { + $this->client->shouldReceive('getClient')->andReturn(array( + 'client_id' => 1234, + 'client_secret' => 5678, + 'redirect_uri' => 'http://foo/redirect', + 'name' => 'Example Client' + )); + + $this->client->shouldReceive('validateRefreshToken')->andReturn(1); + + $this->session->shouldReceive('validateAuthCode')->andReturn(1); + $this->session->shouldReceive('createSession')->andReturn(1); + $this->session->shouldReceive('deleteSession')->andReturn(null); + $this->session->shouldReceive('updateRefreshToken')->andReturn(null); + + $a = $this->returnDefault(); + $a->addGrantType(new OAuth2\Grant\ClientCredentials()); + + $_POST['grant_type'] = 'client_credentials'; + $_POST['client_id'] = 1234; + $_POST['client_secret'] = 5678; + + $request = new OAuth2\Util\Request(array(), $_POST); + $a->setRequest($request); + + $v = $a->issueAccessToken(); + + $this->assertArrayHasKey('access_token', $v); + $this->assertArrayHasKey('token_type', $v); + $this->assertArrayHasKey('expires', $v); + $this->assertArrayHasKey('expires_in', $v); + + $this->assertEquals($a::getExpiresIn(), $v['expires_in']); + $this->assertEquals(time()+$a::getExpiresIn(), $v['expires']); + } + + function test_issueAccessToken_clientCredentialsGrant_withRefreshToken() + { + $this->client->shouldReceive('getClient')->andReturn(array( + 'client_id' => 1234, + 'client_secret' => 5678, + 'redirect_uri' => 'http://foo/redirect', + 'name' => 'Example Client' + )); + + $this->client->shouldReceive('validateRefreshToken')->andReturn(1); + + $this->session->shouldReceive('validateAuthCode')->andReturn(1); + $this->session->shouldReceive('createSession')->andReturn(1); + $this->session->shouldReceive('deleteSession')->andReturn(null); + $this->session->shouldReceive('updateRefreshToken')->andReturn(null); + + $a = $this->returnDefault(); + $a->addGrantType(new OAuth2\Grant\ClientCredentials()); + $a->addGrantType(new OAuth2\Grant\RefreshToken()); + + $_POST['grant_type'] = 'client_credentials'; + $_POST['client_id'] = 1234; + $_POST['client_secret'] = 5678; + + $request = new OAuth2\Util\Request(array(), $_POST); + $a->setRequest($request); + + $v = $a->issueAccessToken(); + + $this->assertArrayHasKey('access_token', $v); + $this->assertArrayHasKey('token_type', $v); + $this->assertArrayHasKey('expires', $v); + $this->assertArrayHasKey('expires_in', $v); + $this->assertArrayHasKey('refresh_token', $v); + + $this->assertEquals($a::getExpiresIn(), $v['expires_in']); + $this->assertEquals(time()+$a::getExpiresIn(), $v['expires']); + } + +} \ No newline at end of file diff --git a/tests/authentication/PasswordGrantTest.php b/tests/authentication/PasswordGrantTest.php new file mode 100644 index 00000000..ac6a7c83 --- /dev/null +++ b/tests/authentication/PasswordGrantTest.php @@ -0,0 +1,347 @@ +client = M::mock('OAuth2\Storage\ClientInterface'); + $this->session = M::mock('OAuth2\Storage\SessionInterface'); + $this->scope = M::mock('OAuth2\Storage\ScopeInterface'); + } + + private function returnDefault() + { + return new OAuth2\AuthServer($this->client, $this->session, $this->scope); + } + + /** + * @expectedException OAuth2\Exception\ClientException + * @expectedExceptionCode 0 + */ + public function test_issueAccessToken_passwordGrant_missingClientId() + { + $a = $this->returnDefault(); + $a->addGrantType(new OAuth2\Grant\Password()); + + $request = new OAuth2\Util\Request(array(), $_POST); + $a->setRequest($request); + + $v = $a->issueAccessToken(array( + 'grant_type' => 'password' + )); + } + + /** + * @expectedException OAuth2\Exception\ClientException + * @expectedExceptionCode 0 + */ + public function test_issueAccessToken_passwordGrant_missingClientPassword() + { + $a = $this->returnDefault(); + $a->addGrantType(new OAuth2\Grant\Password()); + + $request = new OAuth2\Util\Request(array(), $_POST); + $a->setRequest($request); + + $v = $a->issueAccessToken(array( + 'grant_type' => 'password', + 'client_id' => 1234 + )); + } + + /** + * @expectedException OAuth2\Exception\ClientException + * @expectedExceptionCode 8 + */ + public function test_issueAccessToken_passwordGrant_badClient() + { + $this->client->shouldReceive('getClient')->andReturn(false); + + $a = $this->returnDefault(); + $a->addGrantType(new OAuth2\Grant\Password()); + + $request = new OAuth2\Util\Request(array(), $_POST); + $a->setRequest($request); + + $v = $a->issueAccessToken(array( + 'grant_type' => 'password', + 'client_id' => 1234, + 'client_secret' => 5678 + )); + } + + /** + * @expectedException OAuth2\Exception\InvalidGrantTypeException + */ + function test_issueAccessToken_passwordGrant_invalidCallback() + { + $this->client->shouldReceive('getClient')->andReturn(array( + 'client_id' => 1234, + 'client_secret' => 5678, + 'redirect_uri' => 'http://foo/redirect', + 'name' => 'Example Client' + )); + + $this->client->shouldReceive('validateRefreshToken')->andReturn(1); + + $this->session->shouldReceive('validateAuthCode')->andReturn(1); + $this->session->shouldReceive('createSession')->andReturn(1); + $this->session->shouldReceive('deleteSession')->andReturn(null); + $this->session->shouldReceive('updateRefreshToken')->andReturn(null); + + $testCredentials = null; + + $a = $this->returnDefault(); + $pgrant = new OAuth2\Grant\Password(); + $pgrant->setVerifyCredentialsCallback($testCredentials); + $a->addGrantType($pgrant); + + $v = $a->issueAccessToken(array( + 'grant_type' => 'password', + 'client_id' => 1234, + 'client_secret' => 5678, + 'username' => 'foo', + 'password' => 'bar' + )); + } + + /** + * @expectedException OAuth2\Exception\ClientException + * @expectedExceptionCode 0 + */ + function test_issueAccessToken_passwordGrant_missingUsername() + { + $this->client->shouldReceive('getClient')->andReturn(array( + 'client_id' => 1234, + 'client_secret' => 5678, + 'redirect_uri' => 'http://foo/redirect', + 'name' => 'Example Client' + )); + + $this->client->shouldReceive('validateRefreshToken')->andReturn(1); + + $this->session->shouldReceive('validateAuthCode')->andReturn(1); + $this->session->shouldReceive('createSession')->andReturn(1); + $this->session->shouldReceive('deleteSession')->andReturn(null); + $this->session->shouldReceive('updateRefreshToken')->andReturn(null); + + $testCredentials = function($u, $p) { return false; }; + + $a = $this->returnDefault(); + $pgrant = new OAuth2\Grant\Password(); + $pgrant->setVerifyCredentialsCallback($testCredentials); + $a->addGrantType($pgrant); + + $v = $a->issueAccessToken(array( + 'grant_type' => 'password', + 'client_id' => 1234, + 'client_secret' => 5678 + )); + } + + /** + * @expectedException OAuth2\Exception\ClientException + * @expectedExceptionCode 0 + */ + function test_issueAccessToken_passwordGrant_missingPassword() + { + $this->client->shouldReceive('getClient')->andReturn(array( + 'client_id' => 1234, + 'client_secret' => 5678, + 'redirect_uri' => 'http://foo/redirect', + 'name' => 'Example Client' + )); + + $this->client->shouldReceive('validateRefreshToken')->andReturn(1); + + $this->session->shouldReceive('validateAuthCode')->andReturn(1); + $this->session->shouldReceive('createSession')->andReturn(1); + $this->session->shouldReceive('deleteSession')->andReturn(null); + $this->session->shouldReceive('updateRefreshToken')->andReturn(null); + + $testCredentials = function($u, $p) { return false; }; + + $a = $this->returnDefault(); + $pgrant = new OAuth2\Grant\Password(); + $pgrant->setVerifyCredentialsCallback($testCredentials); + $a->addGrantType($pgrant); + + $v = $a->issueAccessToken(array( + 'grant_type' => 'password', + 'client_id' => 1234, + 'client_secret' => 5678, + 'username' => 'foo' + )); + } + + /** + * @expectedException OAuth2\Exception\ClientException + * @expectedExceptionCode 0 + */ + function test_issueAccessToken_passwordGrant_badCredentials() + { + $this->client->shouldReceive('getClient')->andReturn(array( + 'client_id' => 1234, + 'client_secret' => 5678, + 'redirect_uri' => 'http://foo/redirect', + 'name' => 'Example Client' + )); + + $this->client->shouldReceive('validateRefreshToken')->andReturn(1); + + $this->session->shouldReceive('validateAuthCode')->andReturn(1); + $this->session->shouldReceive('createSession')->andReturn(1); + $this->session->shouldReceive('deleteSession')->andReturn(null); + $this->session->shouldReceive('updateRefreshToken')->andReturn(null); + + $testCredentials = function($u, $p) { return false; }; + + $a = $this->returnDefault(); + $pgrant = new OAuth2\Grant\Password(); + $pgrant->setVerifyCredentialsCallback($testCredentials); + $a->addGrantType($pgrant); + + $v = $a->issueAccessToken(array( + 'grant_type' => 'password', + 'client_id' => 1234, + 'client_secret' => 5678, + 'username' => 'foo', + 'password' => 'bar' + )); + } + + function test_issueAccessToken_passwordGrant_passedInput() + { + $this->client->shouldReceive('getClient')->andReturn(array( + 'client_id' => 1234, + 'client_secret' => 5678, + 'redirect_uri' => 'http://foo/redirect', + 'name' => 'Example Client' + )); + + $this->client->shouldReceive('validateRefreshToken')->andReturn(1); + + $this->session->shouldReceive('validateAuthCode')->andReturn(1); + $this->session->shouldReceive('createSession')->andReturn(1); + $this->session->shouldReceive('deleteSession')->andReturn(null); + $this->session->shouldReceive('updateRefreshToken')->andReturn(null); + + $testCredentials = function($u, $p) { return 1; }; + + $a = $this->returnDefault(); + $pgrant = new OAuth2\Grant\Password(); + $pgrant->setVerifyCredentialsCallback($testCredentials); + $a->addGrantType($pgrant); + + $v = $a->issueAccessToken(array( + 'grant_type' => 'password', + 'client_id' => 1234, + 'client_secret' => 5678, + 'username' => 'foo', + 'password' => 'bar' + )); + + $this->assertArrayHasKey('access_token', $v); + $this->assertArrayHasKey('token_type', $v); + $this->assertArrayHasKey('expires', $v); + $this->assertArrayHasKey('expires_in', $v); + + $this->assertEquals($a::getExpiresIn(), $v['expires_in']); + $this->assertEquals(time()+$a::getExpiresIn(), $v['expires']); + } + + function test_issueAccessToken_passwordGrant() + { + $this->client->shouldReceive('getClient')->andReturn(array( + 'client_id' => 1234, + 'client_secret' => 5678, + 'redirect_uri' => 'http://foo/redirect', + 'name' => 'Example Client' + )); + + $this->client->shouldReceive('validateRefreshToken')->andReturn(1); + + $this->session->shouldReceive('validateAuthCode')->andReturn(1); + $this->session->shouldReceive('createSession')->andReturn(1); + $this->session->shouldReceive('deleteSession')->andReturn(null); + $this->session->shouldReceive('updateRefreshToken')->andReturn(null); + + $testCredentials = function($u, $p) { return 1; }; + + $a = $this->returnDefault(); + $pgrant = new OAuth2\Grant\Password(); + $pgrant->setVerifyCredentialsCallback($testCredentials); + $a->addGrantType($pgrant); + + $_POST['grant_type'] = 'password'; + $_POST['client_id'] = 1234; + $_POST['client_secret'] = 5678; + $_POST['username'] = 'foo'; + $_POST['password'] = 'bar'; + + $request = new OAuth2\Util\Request(array(), $_POST); + $a->setRequest($request); + + $v = $a->issueAccessToken(); + + $this->assertArrayHasKey('access_token', $v); + $this->assertArrayHasKey('token_type', $v); + $this->assertArrayHasKey('expires', $v); + $this->assertArrayHasKey('expires_in', $v); + + $this->assertEquals($a::getExpiresIn(), $v['expires_in']); + $this->assertEquals(time()+$a::getExpiresIn(), $v['expires']); + } + + function test_issueAccessToken_passwordGrant_withRefreshToken() + { + $this->client->shouldReceive('getClient')->andReturn(array( + 'client_id' => 1234, + 'client_secret' => 5678, + 'redirect_uri' => 'http://foo/redirect', + 'name' => 'Example Client' + )); + + $this->client->shouldReceive('validateRefreshToken')->andReturn(1); + + $this->session->shouldReceive('validateAuthCode')->andReturn(1); + $this->session->shouldReceive('createSession')->andReturn(1); + $this->session->shouldReceive('deleteSession')->andReturn(null); + $this->session->shouldReceive('updateRefreshToken')->andReturn(null); + + $testCredentials = function($u, $p) { return 1; }; + + $a = $this->returnDefault(); + $pgrant = new OAuth2\Grant\Password(); + $pgrant->setVerifyCredentialsCallback($testCredentials); + $a->addGrantType($pgrant); + $a->addGrantType(new OAuth2\Grant\RefreshToken()); + + $_POST['grant_type'] = 'password'; + $_POST['client_id'] = 1234; + $_POST['client_secret'] = 5678; + $_POST['username'] = 'foo'; + $_POST['password'] = 'bar'; + + $request = new OAuth2\Util\Request(array(), $_POST); + $a->setRequest($request); + + $v = $a->issueAccessToken(); + + $this->assertArrayHasKey('access_token', $v); + $this->assertArrayHasKey('token_type', $v); + $this->assertArrayHasKey('expires', $v); + $this->assertArrayHasKey('expires_in', $v); + $this->assertArrayHasKey('refresh_token', $v); + + $this->assertEquals($a::getExpiresIn(), $v['expires_in']); + $this->assertEquals(time()+$a::getExpiresIn(), $v['expires']); + } + +} \ No newline at end of file diff --git a/tests/authentication/RefreshTokenTest.php b/tests/authentication/RefreshTokenTest.php new file mode 100644 index 00000000..556477b3 --- /dev/null +++ b/tests/authentication/RefreshTokenTest.php @@ -0,0 +1,233 @@ +client = M::mock('OAuth2\Storage\ClientInterface'); + $this->session = M::mock('OAuth2\Storage\SessionInterface'); + $this->scope = M::mock('OAuth2\Storage\ScopeInterface'); + } + + private function returnDefault() + { + return new OAuth2\AuthServer($this->client, $this->session, $this->scope); + } + + public function test_issueAccessToken_with_refresh_token() + { + $this->client->shouldReceive('getClient')->andReturn(array( + 'client_id' => 1234, + 'client_secret' => 5678, + 'redirect_uri' => 'http://foo/redirect', + 'name' => 'Example Client' + )); + + $this->session->shouldReceive('validateAuthCode')->andReturn(1); + $this->session->shouldReceive('updateSession')->andReturn(null); + + $a = $this->returnDefault(); + $a->addGrantType(new OAuth2\Grant\AuthCode()); + $a->addGrantType(new OAuth2\Grant\RefreshToken()); + + $_POST['grant_type'] = 'authorization_code'; + $_POST['client_id'] = 1234; + $_POST['client_secret'] = 5678; + $_POST['redirect_uri'] = 'http://foo/redirect'; + $_POST['code'] = 'foobar'; + + $request = new OAuth2\Util\Request(array(), $_POST); + $a->setRequest($request); + + $v = $a->issueAccessToken(); + + $this->assertArrayHasKey('access_token', $v); + $this->assertArrayHasKey('token_type', $v); + $this->assertArrayHasKey('expires', $v); + $this->assertArrayHasKey('expires_in', $v); + $this->assertArrayHasKey('refresh_token', $v); + + $this->assertEquals($a::getExpiresIn(), $v['expires_in']); + $this->assertEquals(time()+$a::getExpiresIn(), $v['expires']); + } + + /** + * @expectedException OAuth2\Exception\ClientException + * @expectedExceptionCode 0 + */ + public function test_issueAccessToken_refreshTokenGrant_missingClientId() + { + $a = $this->returnDefault(); + $a->addGrantType(new OAuth2\Grant\RefreshToken()); + + $request = new OAuth2\Util\Request(array(), $_POST); + $a->setRequest($request); + + $v = $a->issueAccessToken(array( + 'grant_type' => 'refresh_token' + )); + } + + /** + * @expectedException OAuth2\Exception\ClientException + * @expectedExceptionCode 0 + */ + public function test_issueAccessToken_refreshTokenGrant_missingClientSecret() + { + $a = $this->returnDefault(); + $a->addGrantType(new OAuth2\Grant\RefreshToken()); + + $request = new OAuth2\Util\Request(array(), $_POST); + $a->setRequest($request); + + $v = $a->issueAccessToken(array( + 'grant_type' => 'refresh_token', + 'client_id' => 1234 + )); + } + + /** + * @expectedException OAuth2\Exception\ClientException + * @expectedExceptionCode 8 + */ + public function test_issueAccessToken_refreshTokenGrant_badClient() + { + $this->client->shouldReceive('getClient')->andReturn(false); + + $a = $this->returnDefault(); + $a->addGrantType(new OAuth2\Grant\RefreshToken()); + + $request = new OAuth2\Util\Request(array(), $_POST); + $a->setRequest($request); + + $v = $a->issueAccessToken(array( + 'grant_type' => 'refresh_token', + 'client_id' => 1234, + 'client_secret' => 5678 + )); + } + + /** + * @expectedException OAuth2\Exception\ClientException + * @expectedExceptionCode 0 + */ + public function test_issueAccessToken_refreshTokenGrant_missingRefreshToken() + { + $this->client->shouldReceive('getClient')->andReturn(array()); + + $a = $this->returnDefault(); + $a->addGrantType(new OAuth2\Grant\RefreshToken()); + + $request = new OAuth2\Util\Request(array(), $_POST); + $a->setRequest($request); + + $v = $a->issueAccessToken(array( + 'grant_type' => 'refresh_token', + 'client_id' => 1234, + 'client_secret' => 5678, + //'refresh_token' => + )); + } + + /** + * @expectedException OAuth2\Exception\ClientException + * @expectedExceptionCode 0 + */ + public function test_issueAccessToken_refreshTokenGrant_badRefreshToken() + { + $this->client->shouldReceive('getClient')->andReturn(array()); + $this->client->shouldReceive('validateRefreshToken')->andReturn(false); + + $a = $this->returnDefault(); + $a->addGrantType(new OAuth2\Grant\RefreshToken()); + + $request = new OAuth2\Util\Request(array(), $_POST); + $a->setRequest($request); + + $v = $a->issueAccessToken(array( + 'grant_type' => 'refresh_token', + 'client_id' => 1234, + 'client_secret' => 5678, + 'refresh_token' => 'abcdef' + )); + } + + public function test_issueAccessToken_refreshTokenGrant_passedInput() + { + $this->client->shouldReceive('getClient')->andReturn(array( + 'client_id' => 1234, + 'client_secret' => 5678, + 'redirect_uri' => 'http://foo/redirect', + 'name' => 'Example Client' + )); + + $this->client->shouldReceive('validateRefreshToken')->andReturn(1); + + $this->session->shouldReceive('validateAuthCode')->andReturn(1); + $this->session->shouldReceive('updateSession')->andReturn(null); + $this->session->shouldReceive('updateRefreshToken')->andReturn(null); + + $a = $this->returnDefault(); + $a->addGrantType(new OAuth2\Grant\RefreshToken()); + + $_POST['grant_type'] = 'refresh_token'; + $_POST['client_id'] = 1234; + $_POST['client_secret'] = 5678; + $_POST['refresh_token'] = 'abcdef'; + + $request = new OAuth2\Util\Request(array(), $_POST); + $a->setRequest($request); + + $v = $a->issueAccessToken(); + + $this->assertArrayHasKey('access_token', $v); + $this->assertArrayHasKey('token_type', $v); + $this->assertArrayHasKey('expires', $v); + $this->assertArrayHasKey('expires_in', $v); + $this->assertArrayHasKey('refresh_token', $v); + + $this->assertEquals($a::getExpiresIn(), $v['expires_in']); + $this->assertEquals(time()+$a::getExpiresIn(), $v['expires']); + } + + public function test_issueAccessToken_refreshTokenGrant() + { + $this->client->shouldReceive('getClient')->andReturn(array( + 'client_id' => 1234, + 'client_secret' => 5678, + 'redirect_uri' => 'http://foo/redirect', + 'name' => 'Example Client' + )); + + $this->client->shouldReceive('validateRefreshToken')->andReturn(1); + + $this->session->shouldReceive('validateAuthCode')->andReturn(1); + $this->session->shouldReceive('updateSession')->andReturn(null); + $this->session->shouldReceive('updateRefreshToken')->andReturn(null); + + $a = $this->returnDefault(); + $a->addGrantType(new OAuth2\Grant\RefreshToken()); + + $v = $a->issueAccessToken(array( + 'grant_type' => 'refresh_token', + 'client_id' => 1234, + 'client_secret' => 5678, + 'refresh_token' => 'abcdef', + )); + + $this->assertArrayHasKey('access_token', $v); + $this->assertArrayHasKey('token_type', $v); + $this->assertArrayHasKey('expires', $v); + $this->assertArrayHasKey('expires_in', $v); + $this->assertArrayHasKey('refresh_token', $v); + + $this->assertEquals($a::getExpiresIn(), $v['expires_in']); + $this->assertEquals(time()+$a::getExpiresIn(), $v['expires']); + } +} \ No newline at end of file From 9f6bd641004cbcf0e356736c83369d049d34e93e Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Fri, 15 Feb 2013 15:05:40 +0000 Subject: [PATCH 105/113] Renamed database.sql to mysql.sql --- sql/{database.sql => mysql.sql} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename sql/{database.sql => mysql.sql} (100%) diff --git a/sql/database.sql b/sql/mysql.sql similarity index 100% rename from sql/database.sql rename to sql/mysql.sql From 92d9435bba44ee7114aaf2d0fc51e4292fc9acf4 Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Fri, 15 Feb 2013 16:29:00 +0000 Subject: [PATCH 106/113] Added method to get the exception type --- src/OAuth2/AuthServer.php | 13 ++++++++++++- tests/authentication/AuthServerTest.php | 5 +++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/OAuth2/AuthServer.php b/src/OAuth2/AuthServer.php index 69a78831..82f464fa 100644 --- a/src/OAuth2/AuthServer.php +++ b/src/OAuth2/AuthServer.php @@ -67,7 +67,7 @@ class AuthServer * Exception error codes * @var array */ - protected $exceptionCodes = array( + protected static $exceptionCodes = array( 0 => 'invalid_request', 1 => 'unauthorized_client', 2 => 'access_denied', @@ -110,6 +110,17 @@ class AuthServer return self::$exceptionMessages[$error]; } + /** + * Get an exception code + * + * @param integer $code The exception code + * @return string The exception code type + */ + public static function getExceptionType($code = 0) + { + return self::$exceptionCodes[$code]; + } + /** * Create a new OAuth2 authentication server * diff --git a/tests/authentication/AuthServerTest.php b/tests/authentication/AuthServerTest.php index a6b2b1b3..f8f3e35e 100644 --- a/tests/authentication/AuthServerTest.php +++ b/tests/authentication/AuthServerTest.php @@ -45,6 +45,11 @@ class Authentication_Server_test extends PHPUnit_Framework_TestCase $this->assertEquals($v['access_denied'], $m); } + public function test_getExceptionCode() + { + $this->assertEquals('access_denied', OAuth2\AuthServer::getExceptionType(2)); + } + public function test_hasGrantType() { $this->assertFalse(OAuth2\AuthServer::hasGrantType('test')); From 57c24953bece67fc88af8c07467b7da606eacdf5 Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Fri, 15 Feb 2013 16:30:32 +0000 Subject: [PATCH 107/113] First draft of auth server docs --- AuthServer.md | 243 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 243 insertions(+) create mode 100644 AuthServer.md diff --git a/AuthServer.md b/AuthServer.md new file mode 100644 index 00000000..a8463bba --- /dev/null +++ b/AuthServer.md @@ -0,0 +1,243 @@ +# Developing an OAuth 2.0 authentication server + +## Install the library + +The recommended way of installing the library is via [Composer](http://getcomposer.org). + +If you already have a composer.json file in your root then add `”lncd/oauth2”: “*”` in the _require_ object. Then run `composer update`. + +Otherwise create a new file in your project root called _composer.json_ add set the contents to: + +```javascript +{ + "require": { + "lncd\OAuth2": "*" + } +} +``` + +Now, assuming you have installed Composer run `composer install`. + +Ensure now that you’ve set up your project to autoload composer packages. + +## Set up the database + +To setup the database just import _sql/mysql.sql_ + +## Create your first client + +In OAuth terms a _client_ is an application (it could be a website or a mobile app) that communicates with your API. + +Insert a client into the `oauth_clients` table. It is recommended that you make the `id` and `secret` fields random alphanumeric strings - [http://randomkeygen.com/](http://randomkeygen.com/) is a useful for this. The `auto_approve` parameter should be to _1_ if you want the user to automatically approve access to the client, otherwise set it to _0_. + +If you want to use the _authorization grant_ (where a user is redirected to the auth server from the client and the back in order to “sign-in” or “connect” with the client) then in the `oauth_client_endpoints` add a redirect URI (where the user is redirected back to after signing in). You can add multiple redirect URIs for production and development. + +## Create the storage models + +In order to persist data to the database you should create classes which implement the following three interfaces: + +* `\OAuth2\Storage\ClientInterface` +* `\OAuth2\Storage\ScopeInterface` +* `\OAuth2\Storage\SessionInterface` + +## Create an _oauth_ controller + +_NOTE: This is assuming you’re using a framework that follows an MVC pattern, If you’re using individual files for each page then you create a new page for each controller route listed henceforth._ + +In your controller constuctor you should instantiate the auth server: + + public function __construct() + { + // Initiate the request handler which deals with $_GET, $_POST, etc + $request = new \OAuth2\Util\Request(); + + // Create the auth server, the three parameters passed are references to the storage models + $this->authserver = new \OAuth2\AuthServer(new ClientModel, new SessionModel, new ScopeModel); + + // Enable the authorization code grant type + $this->authserver->addGrantType(new \OAuth2\Grant\AuthCode()); + + // Set the TTL of an access token in seconds (default to 3600s / 1 hour) + $this->authserver->setExpiresIn(86400); + } + +Create your first route (for example “index” - which would resolve to _/oauth_). + + public function action_index() + { + try { + + // Tell the auth server to check the required parameters are in the query string + $params = $this->authserver->checkAuthoriseParams(); + + // Save the verified parameters to the user's session + Session::put('client_id', $params['client_id']); + Session::put('client_details', $params['client_details']); + Session::put('redirect_uri', $params['redirect_uri']); + Session::put('response_type', $params['response_type']); + Session::put('scopes', $params['scopes']); + + // Redirect the user to the sign-in route + return Redirect::to(‘oauth/signin'); + + } catch (Oauth2\Exception\ClientException $e) { + + // Throw an error here which says what the problem is with the auth params + + } catch (Exception $e) { + + // Throw an error here which has caught a non-library specific error + + } + } + +Next create a sign-in route: + + public function action_signin() + { + // Retrieve the auth params from the user's session + $params['client_id'] = Session::get('client_id'); + $params['client_details'] = Session::get('client_details'); + $params['redirect_uri'] = Session::get('redirect_uri'); + $params['response_type'] = Session::get('response_type'); + $params['scopes'] = Session::get('scopes'); + + // Check that the auth params are all present + foreach ($params as $key=>$value) { + if ($value === null) { + // Throw an error because an auth param is missing - don't continue any further + } + } + + // Process the sign-in form submission + if (Input::get('signin') !== null) { + try { + + // Get username + $u = Input::get('username'); + if ($u === null || trim($u) === '') { + throw new Exception('please enter your username.'); + } + + // Get password + $p = Input::get('password'); + if ($p === null || trim($p) === '') { + throw new Exception('please enter your password.'); + } + + // Verify the user's username and password + // Set the user's ID to a session + + } catch (Exception $e) { + $params['error_message'] = $e->getMessage(); + } + } + + // Get the user's ID from their session + $params['user_id'] = Session::get('user_id'); + + // User is signed in + if ($params['user_id'] !== null) { + + // Redirect the user to /oauth/authorise route + return Redirect::to('oauth/authorise'); + + } + + // User is not signed in, show the sign-in form + else { + return View::make('oauth.signin', $params); + } + } + +In the sign-in form HTML page you should tell the user the name of the client that their signing into. + +Once the user has signed in (if they didn’t already have an existing session) then they should be redirected the authorise route where the user explicitly gives permission for the client to act on their behalf. + + public function action_authorise() + { + // Retrieve the auth params from the user's session + $params['client_id'] = Session::get('client_id'); + $params['client_details'] = Session::get('client_details'); + $params['redirect_uri'] = Session::get('redirect_uri'); + $params['response_type'] = Session::get('response_type'); + $params['scopes'] = Session::get('scopes'); + + // Check that the auth params are all present + foreach ($params as $key=>$value) { + if ($value === null) { + // Throw an error because an auth param is missing - don't continue any further + } + } + + // Get the user ID + $params['user_id'] = Session::get('user_id'); + + // User is not signed in so redirect them to the sign-in route (/oauth/signin) + if ($params['user_id'] === null) { + return Redirect::to('signin'); + } + + // Check if the client should be automatically approved + $autoApprove = ($params['client_details']['auto_approve'] === '1') ? true : false; + + // Process the authorise request if the user's has clicked 'approve' or the client + if (Input::get('approve') !== null || $autoApprove === true) { + + // Generate an authorization code + $code = $this->authserver->newAuthoriseRequest('user', $params['user_id'], $params); + + // Redirect the user back to the client with an authorization code + return Redirect::to(\OAuth2\Util\RedirectUri::make($params['redirect_uri'], array( + 'code' => $code, + 'state' => isset($params['state']) ? $params['state'] : '' + ))); + } + + // If the user has denied the client so redirect them back without an authorization code + if (Input::get('deny') !== null) { + return Redirect::to(\OAuth2\Util\RedirectUri::make($params['redirect_uri'], array( + 'error' => $this->authserver->exceptionCodes[2], + 'error_message' => $this->authserver->errors[$this->authserver->exceptionCodes[2]], + 'state' => isset($params['state']) ? $params['state'] : '' + ))); + } + + // The client shouldn't automatically be approved and the user hasn't yet approved it so show them a form + return View::make('oauth.authorise', $params); + } + +In the authorize form the user should again be told the name of the client and also list all the scopes (permissions) it is requesting. + +The final route to create is where the client exchanges the authorization code for an access token. + + public function action_access_token() + { + try { + + // Tell the auth server to issue an access token + $response = $this->authserver->issueAccessToken(); + + } catch (\Oauth2\Exception\ClientException $e) { + + // Throw an exception because there was a problem with a the client's request + $response = array( + 'error' => $this->authserver::getExceptionType($e->getCode()), + 'error_description' => $e->getMessage() + ); + + } catch (Exception $e) { + + // Throw an error when a non-library specific exception has been thrown + $response = array( + 'error' => 'undefined_error', + 'error_description' => $e->getMessage() + ); + } + + header('Content-type: application/json'); + echo json_encode($response); + } + header('Content-type: application/json'); + echo json_encode($response); + } \ No newline at end of file From ff37850feabfdf06a73f05e82ed48299876d9587 Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Fri, 15 Feb 2013 16:33:18 +0000 Subject: [PATCH 108/113] Pretty print github-style codeblocks --- AuthServer.md | 330 ++++++++++++++++++++++++++------------------------ 1 file changed, 170 insertions(+), 160 deletions(-) diff --git a/AuthServer.md b/AuthServer.md index a8463bba..55534d95 100644 --- a/AuthServer.md +++ b/AuthServer.md @@ -46,198 +46,208 @@ _NOTE: This is assuming you’re using a framework that follows an MVC pattern, In your controller constuctor you should instantiate the auth server: - public function __construct() - { - // Initiate the request handler which deals with $_GET, $_POST, etc - $request = new \OAuth2\Util\Request(); - - // Create the auth server, the three parameters passed are references to the storage models - $this->authserver = new \OAuth2\AuthServer(new ClientModel, new SessionModel, new ScopeModel); - - // Enable the authorization code grant type - $this->authserver->addGrantType(new \OAuth2\Grant\AuthCode()); - - // Set the TTL of an access token in seconds (default to 3600s / 1 hour) - $this->authserver->setExpiresIn(86400); - } +```php +public function __construct() +{ + // Initiate the request handler which deals with $_GET, $_POST, etc + $request = new \OAuth2\Util\Request(); + + // Create the auth server, the three parameters passed are references to the storage models + $this->authserver = new \OAuth2\AuthServer(new ClientModel, new SessionModel, new ScopeModel); + + // Enable the authorization code grant type + $this->authserver->addGrantType(new \OAuth2\Grant\AuthCode()); + + // Set the TTL of an access token in seconds (default to 3600s / 1 hour) + $this->authserver->setExpiresIn(86400); +} +``` Create your first route (for example “index” - which would resolve to _/oauth_). - public function action_index() - { - try { +```php +public function action_index() +{ + try { - // Tell the auth server to check the required parameters are in the query string - $params = $this->authserver->checkAuthoriseParams(); + // Tell the auth server to check the required parameters are in the query string + $params = $this->authserver->checkAuthoriseParams(); - // Save the verified parameters to the user's session - Session::put('client_id', $params['client_id']); - Session::put('client_details', $params['client_details']); - Session::put('redirect_uri', $params['redirect_uri']); - Session::put('response_type', $params['response_type']); - Session::put('scopes', $params['scopes']); + // Save the verified parameters to the user's session + Session::put('client_id', $params['client_id']); + Session::put('client_details', $params['client_details']); + Session::put('redirect_uri', $params['redirect_uri']); + Session::put('response_type', $params['response_type']); + Session::put('scopes', $params['scopes']); - // Redirect the user to the sign-in route - return Redirect::to(‘oauth/signin'); + // Redirect the user to the sign-in route + return Redirect::to(‘oauth/signin'); - } catch (Oauth2\Exception\ClientException $e) { + } catch (Oauth2\Exception\ClientException $e) { - // Throw an error here which says what the problem is with the auth params - - } catch (Exception $e) { - - // Throw an error here which has caught a non-library specific error + // Throw an error here which says what the problem is with the auth params + + } catch (Exception $e) { + + // Throw an error here which has caught a non-library specific error - } } +} +``` Next create a sign-in route: - public function action_signin() - { - // Retrieve the auth params from the user's session - $params['client_id'] = Session::get('client_id'); - $params['client_details'] = Session::get('client_details'); - $params['redirect_uri'] = Session::get('redirect_uri'); - $params['response_type'] = Session::get('response_type'); - $params['scopes'] = Session::get('scopes'); +```php +public function action_signin() +{ + // Retrieve the auth params from the user's session + $params['client_id'] = Session::get('client_id'); + $params['client_details'] = Session::get('client_details'); + $params['redirect_uri'] = Session::get('redirect_uri'); + $params['response_type'] = Session::get('response_type'); + $params['scopes'] = Session::get('scopes'); - // Check that the auth params are all present - foreach ($params as $key=>$value) { - if ($value === null) { - // Throw an error because an auth param is missing - don't continue any further - } - } - - // Process the sign-in form submission - if (Input::get('signin') !== null) { - try { - - // Get username - $u = Input::get('username'); - if ($u === null || trim($u) === '') { - throw new Exception('please enter your username.'); - } - - // Get password - $p = Input::get('password'); - if ($p === null || trim($p) === '') { - throw new Exception('please enter your password.'); - } - - // Verify the user's username and password - // Set the user's ID to a session - - } catch (Exception $e) { - $params['error_message'] = $e->getMessage(); - } - } - - // Get the user's ID from their session - $params['user_id'] = Session::get('user_id'); - - // User is signed in - if ($params['user_id'] !== null) { - - // Redirect the user to /oauth/authorise route - return Redirect::to('oauth/authorise'); - - } - - // User is not signed in, show the sign-in form - else { - return View::make('oauth.signin', $params); + // Check that the auth params are all present + foreach ($params as $key=>$value) { + if ($value === null) { + // Throw an error because an auth param is missing - don't continue any further } } + + // Process the sign-in form submission + if (Input::get('signin') !== null) { + try { + + // Get username + $u = Input::get('username'); + if ($u === null || trim($u) === '') { + throw new Exception('please enter your username.'); + } + + // Get password + $p = Input::get('password'); + if ($p === null || trim($p) === '') { + throw new Exception('please enter your password.'); + } + + // Verify the user's username and password + // Set the user's ID to a session + + } catch (Exception $e) { + $params['error_message'] = $e->getMessage(); + } + } + + // Get the user's ID from their session + $params['user_id'] = Session::get('user_id'); + + // User is signed in + if ($params['user_id'] !== null) { + + // Redirect the user to /oauth/authorise route + return Redirect::to('oauth/authorise'); + + } + + // User is not signed in, show the sign-in form + else { + return View::make('oauth.signin', $params); + } +} +``` In the sign-in form HTML page you should tell the user the name of the client that their signing into. Once the user has signed in (if they didn’t already have an existing session) then they should be redirected the authorise route where the user explicitly gives permission for the client to act on their behalf. - public function action_authorise() - { - // Retrieve the auth params from the user's session - $params['client_id'] = Session::get('client_id'); - $params['client_details'] = Session::get('client_details'); - $params['redirect_uri'] = Session::get('redirect_uri'); - $params['response_type'] = Session::get('response_type'); - $params['scopes'] = Session::get('scopes'); +```php +public function action_authorise() +{ + // Retrieve the auth params from the user's session + $params['client_id'] = Session::get('client_id'); + $params['client_details'] = Session::get('client_details'); + $params['redirect_uri'] = Session::get('redirect_uri'); + $params['response_type'] = Session::get('response_type'); + $params['scopes'] = Session::get('scopes'); - // Check that the auth params are all present - foreach ($params as $key=>$value) { - if ($value === null) { - // Throw an error because an auth param is missing - don't continue any further - } + // Check that the auth params are all present + foreach ($params as $key=>$value) { + if ($value === null) { + // Throw an error because an auth param is missing - don't continue any further } - - // Get the user ID - $params['user_id'] = Session::get('user_id'); - - // User is not signed in so redirect them to the sign-in route (/oauth/signin) - if ($params['user_id'] === null) { - return Redirect::to('signin'); - } - - // Check if the client should be automatically approved - $autoApprove = ($params['client_details']['auto_approve'] === '1') ? true : false; - - // Process the authorise request if the user's has clicked 'approve' or the client - if (Input::get('approve') !== null || $autoApprove === true) { - - // Generate an authorization code - $code = $this->authserver->newAuthoriseRequest('user', $params['user_id'], $params); - - // Redirect the user back to the client with an authorization code - return Redirect::to(\OAuth2\Util\RedirectUri::make($params['redirect_uri'], array( - 'code' => $code, - 'state' => isset($params['state']) ? $params['state'] : '' - ))); - } - - // If the user has denied the client so redirect them back without an authorization code - if (Input::get('deny') !== null) { - return Redirect::to(\OAuth2\Util\RedirectUri::make($params['redirect_uri'], array( - 'error' => $this->authserver->exceptionCodes[2], - 'error_message' => $this->authserver->errors[$this->authserver->exceptionCodes[2]], - 'state' => isset($params['state']) ? $params['state'] : '' - ))); - } - - // The client shouldn't automatically be approved and the user hasn't yet approved it so show them a form - return View::make('oauth.authorise', $params); } + + // Get the user ID + $params['user_id'] = Session::get('user_id'); + + // User is not signed in so redirect them to the sign-in route (/oauth/signin) + if ($params['user_id'] === null) { + return Redirect::to('signin'); + } + + // Check if the client should be automatically approved + $autoApprove = ($params['client_details']['auto_approve'] === '1') ? true : false; + + // Process the authorise request if the user's has clicked 'approve' or the client + if (Input::get('approve') !== null || $autoApprove === true) { + + // Generate an authorization code + $code = $this->authserver->newAuthoriseRequest('user', $params['user_id'], $params); + + // Redirect the user back to the client with an authorization code + return Redirect::to(\OAuth2\Util\RedirectUri::make($params['redirect_uri'], array( + 'code' => $code, + 'state' => isset($params['state']) ? $params['state'] : '' + ))); + } + + // If the user has denied the client so redirect them back without an authorization code + if (Input::get('deny') !== null) { + return Redirect::to(\OAuth2\Util\RedirectUri::make($params['redirect_uri'], array( + 'error' => $this->authserver->exceptionCodes[2], + 'error_message' => $this->authserver->errors[$this->authserver->exceptionCodes[2]], + 'state' => isset($params['state']) ? $params['state'] : '' + ))); + } + + // The client shouldn't automatically be approved and the user hasn't yet approved it so show them a form + return View::make('oauth.authorise', $params); +} +``` In the authorize form the user should again be told the name of the client and also list all the scopes (permissions) it is requesting. The final route to create is where the client exchanges the authorization code for an access token. - public function action_access_token() - { - try { +```php +public function action_access_token() +{ + try { - // Tell the auth server to issue an access token - $response = $this->authserver->issueAccessToken(); + // Tell the auth server to issue an access token + $response = $this->authserver->issueAccessToken(); - } catch (\Oauth2\Exception\ClientException $e) { + } catch (\Oauth2\Exception\ClientException $e) { - // Throw an exception because there was a problem with a the client's request - $response = array( - 'error' => $this->authserver::getExceptionType($e->getCode()), - 'error_description' => $e->getMessage() - ); + // Throw an exception because there was a problem with a the client's request + $response = array( + 'error' => $this->authserver::getExceptionType($e->getCode()), + 'error_description' => $e->getMessage() + ); - } catch (Exception $e) { + } catch (Exception $e) { - // Throw an error when a non-library specific exception has been thrown - $response = array( - 'error' => 'undefined_error', - 'error_description' => $e->getMessage() - ); - } - - header('Content-type: application/json'); - echo json_encode($response); + // Throw an error when a non-library specific exception has been thrown + $response = array( + 'error' => 'undefined_error', + 'error_description' => $e->getMessage() + ); } - header('Content-type: application/json'); - echo json_encode($response); - } \ No newline at end of file + + header('Content-type: application/json'); + echo json_encode($response); +} + header('Content-type: application/json'); + echo json_encode($response); +} +``` \ No newline at end of file From 645fc7210e60255da86da8d97e2ca6442dca8e62 Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Fri, 15 Feb 2013 16:35:28 +0000 Subject: [PATCH 109/113] Removed sillyness --- AuthServer.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/AuthServer.md b/AuthServer.md index 55534d95..fff9fbd9 100644 --- a/AuthServer.md +++ b/AuthServer.md @@ -247,7 +247,4 @@ public function action_access_token() header('Content-type: application/json'); echo json_encode($response); } - header('Content-type: application/json'); - echo json_encode($response); -} ``` \ No newline at end of file From 333ce37c974c62994f6258556f540714d75303c0 Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Fri, 15 Feb 2013 16:56:54 +0000 Subject: [PATCH 110/113] Removed authserver.md - going to be in docs instead --- AuthServer.md | 250 -------------------------------------------------- 1 file changed, 250 deletions(-) delete mode 100644 AuthServer.md diff --git a/AuthServer.md b/AuthServer.md deleted file mode 100644 index fff9fbd9..00000000 --- a/AuthServer.md +++ /dev/null @@ -1,250 +0,0 @@ -# Developing an OAuth 2.0 authentication server - -## Install the library - -The recommended way of installing the library is via [Composer](http://getcomposer.org). - -If you already have a composer.json file in your root then add `”lncd/oauth2”: “*”` in the _require_ object. Then run `composer update`. - -Otherwise create a new file in your project root called _composer.json_ add set the contents to: - -```javascript -{ - "require": { - "lncd\OAuth2": "*" - } -} -``` - -Now, assuming you have installed Composer run `composer install`. - -Ensure now that you’ve set up your project to autoload composer packages. - -## Set up the database - -To setup the database just import _sql/mysql.sql_ - -## Create your first client - -In OAuth terms a _client_ is an application (it could be a website or a mobile app) that communicates with your API. - -Insert a client into the `oauth_clients` table. It is recommended that you make the `id` and `secret` fields random alphanumeric strings - [http://randomkeygen.com/](http://randomkeygen.com/) is a useful for this. The `auto_approve` parameter should be to _1_ if you want the user to automatically approve access to the client, otherwise set it to _0_. - -If you want to use the _authorization grant_ (where a user is redirected to the auth server from the client and the back in order to “sign-in” or “connect” with the client) then in the `oauth_client_endpoints` add a redirect URI (where the user is redirected back to after signing in). You can add multiple redirect URIs for production and development. - -## Create the storage models - -In order to persist data to the database you should create classes which implement the following three interfaces: - -* `\OAuth2\Storage\ClientInterface` -* `\OAuth2\Storage\ScopeInterface` -* `\OAuth2\Storage\SessionInterface` - -## Create an _oauth_ controller - -_NOTE: This is assuming you’re using a framework that follows an MVC pattern, If you’re using individual files for each page then you create a new page for each controller route listed henceforth._ - -In your controller constuctor you should instantiate the auth server: - -```php -public function __construct() -{ - // Initiate the request handler which deals with $_GET, $_POST, etc - $request = new \OAuth2\Util\Request(); - - // Create the auth server, the three parameters passed are references to the storage models - $this->authserver = new \OAuth2\AuthServer(new ClientModel, new SessionModel, new ScopeModel); - - // Enable the authorization code grant type - $this->authserver->addGrantType(new \OAuth2\Grant\AuthCode()); - - // Set the TTL of an access token in seconds (default to 3600s / 1 hour) - $this->authserver->setExpiresIn(86400); -} -``` - -Create your first route (for example “index” - which would resolve to _/oauth_). - -```php -public function action_index() -{ - try { - - // Tell the auth server to check the required parameters are in the query string - $params = $this->authserver->checkAuthoriseParams(); - - // Save the verified parameters to the user's session - Session::put('client_id', $params['client_id']); - Session::put('client_details', $params['client_details']); - Session::put('redirect_uri', $params['redirect_uri']); - Session::put('response_type', $params['response_type']); - Session::put('scopes', $params['scopes']); - - // Redirect the user to the sign-in route - return Redirect::to(‘oauth/signin'); - - } catch (Oauth2\Exception\ClientException $e) { - - // Throw an error here which says what the problem is with the auth params - - } catch (Exception $e) { - - // Throw an error here which has caught a non-library specific error - - } -} -``` - -Next create a sign-in route: - -```php -public function action_signin() -{ - // Retrieve the auth params from the user's session - $params['client_id'] = Session::get('client_id'); - $params['client_details'] = Session::get('client_details'); - $params['redirect_uri'] = Session::get('redirect_uri'); - $params['response_type'] = Session::get('response_type'); - $params['scopes'] = Session::get('scopes'); - - // Check that the auth params are all present - foreach ($params as $key=>$value) { - if ($value === null) { - // Throw an error because an auth param is missing - don't continue any further - } - } - - // Process the sign-in form submission - if (Input::get('signin') !== null) { - try { - - // Get username - $u = Input::get('username'); - if ($u === null || trim($u) === '') { - throw new Exception('please enter your username.'); - } - - // Get password - $p = Input::get('password'); - if ($p === null || trim($p) === '') { - throw new Exception('please enter your password.'); - } - - // Verify the user's username and password - // Set the user's ID to a session - - } catch (Exception $e) { - $params['error_message'] = $e->getMessage(); - } - } - - // Get the user's ID from their session - $params['user_id'] = Session::get('user_id'); - - // User is signed in - if ($params['user_id'] !== null) { - - // Redirect the user to /oauth/authorise route - return Redirect::to('oauth/authorise'); - - } - - // User is not signed in, show the sign-in form - else { - return View::make('oauth.signin', $params); - } -} -``` - -In the sign-in form HTML page you should tell the user the name of the client that their signing into. - -Once the user has signed in (if they didn’t already have an existing session) then they should be redirected the authorise route where the user explicitly gives permission for the client to act on their behalf. - -```php -public function action_authorise() -{ - // Retrieve the auth params from the user's session - $params['client_id'] = Session::get('client_id'); - $params['client_details'] = Session::get('client_details'); - $params['redirect_uri'] = Session::get('redirect_uri'); - $params['response_type'] = Session::get('response_type'); - $params['scopes'] = Session::get('scopes'); - - // Check that the auth params are all present - foreach ($params as $key=>$value) { - if ($value === null) { - // Throw an error because an auth param is missing - don't continue any further - } - } - - // Get the user ID - $params['user_id'] = Session::get('user_id'); - - // User is not signed in so redirect them to the sign-in route (/oauth/signin) - if ($params['user_id'] === null) { - return Redirect::to('signin'); - } - - // Check if the client should be automatically approved - $autoApprove = ($params['client_details']['auto_approve'] === '1') ? true : false; - - // Process the authorise request if the user's has clicked 'approve' or the client - if (Input::get('approve') !== null || $autoApprove === true) { - - // Generate an authorization code - $code = $this->authserver->newAuthoriseRequest('user', $params['user_id'], $params); - - // Redirect the user back to the client with an authorization code - return Redirect::to(\OAuth2\Util\RedirectUri::make($params['redirect_uri'], array( - 'code' => $code, - 'state' => isset($params['state']) ? $params['state'] : '' - ))); - } - - // If the user has denied the client so redirect them back without an authorization code - if (Input::get('deny') !== null) { - return Redirect::to(\OAuth2\Util\RedirectUri::make($params['redirect_uri'], array( - 'error' => $this->authserver->exceptionCodes[2], - 'error_message' => $this->authserver->errors[$this->authserver->exceptionCodes[2]], - 'state' => isset($params['state']) ? $params['state'] : '' - ))); - } - - // The client shouldn't automatically be approved and the user hasn't yet approved it so show them a form - return View::make('oauth.authorise', $params); -} -``` - -In the authorize form the user should again be told the name of the client and also list all the scopes (permissions) it is requesting. - -The final route to create is where the client exchanges the authorization code for an access token. - -```php -public function action_access_token() -{ - try { - - // Tell the auth server to issue an access token - $response = $this->authserver->issueAccessToken(); - - } catch (\Oauth2\Exception\ClientException $e) { - - // Throw an exception because there was a problem with a the client's request - $response = array( - 'error' => $this->authserver::getExceptionType($e->getCode()), - 'error_description' => $e->getMessage() - ); - - } catch (Exception $e) { - - // Throw an error when a non-library specific exception has been thrown - $response = array( - 'error' => 'undefined_error', - 'error_description' => $e->getMessage() - ); - } - - header('Content-type: application/json'); - echo json_encode($response); -} -``` \ No newline at end of file From f42f45e42e21bec5fa906a9501d99c63101fc51b Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Fri, 15 Feb 2013 17:08:21 +0000 Subject: [PATCH 111/113] Updated README --- README.md | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 06e193a5..d65bcaf3 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # PHP OAuth Framework -The goal of this project is to develop a standards compliant [OAuth 2](http://tools.ietf.org/wg/oauth/draft-ietf-oauth-v2/) authentication server, resource server and client library with support for a major OAuth 2 providers. +The goal of this project is to develop a standards compliant [OAuth 2](http://tools.ietf.org/wg/oauth/draft-ietf-oauth-v2/) authentication server and resource server. ## Package Installation @@ -14,28 +14,25 @@ The framework is provided as a Composer package which can be installed by adding } ``` -## Package Integration +--- -Check out the [wiki](https://github.com/lncd/OAuth2/wiki) +The library features 100% unit test code coverage. To run the tests yourself run `phpunit -c build/phpunit.xml`. ## Current Features ### Authentication Server -The authentication server is a flexible class that supports the following grants: +The authentication server is a flexible class and following core specification grants are implemented: -* authentication code -* refresh token -* client credentials -* password (user credentials) +* authentication code ([section 4.1](http://tools.ietf.org/html/rfc6749#section-4.1)) +* refresh token ([section 6](http://tools.ietf.org/html/rfc6749#section-6)) +* client credentials ([section 2.3.1](http://tools.ietf.org/html/rfc6749#section-2.3.1)) +* password (user credentials) ([section 4.3](http://tools.ietf.org/html/rfc6749#section-4.3)) ### Resource Server The resource server allows you to secure your API endpoints by checking for a valid OAuth access token in the request and ensuring the token has the correct permission to access resources. - - - ## Future Goals ### Authentication Server @@ -43,10 +40,13 @@ The resource server allows you to secure your API endpoints by checking for a va * Support for [JSON web tokens](http://tools.ietf.org/wg/oauth/draft-ietf-oauth-json-web-token/). * Support for [SAML assertions](http://tools.ietf.org/wg/oauth/draft-ietf-oauth-saml2-bearer/). -### Client support - -* Merge in https://github.com/philsturgeon/codeigniter-oauth2 - --- -This code will be developed as part of the [Linkey](http://linkey.blogs.lincoln.ac.uk) project which has been funded by [JISC](http://jisc.ac.uk) under the Access and Identity Management programme. \ No newline at end of file +This code will be developed as part of the [Linkey](http://linkey.blogs.lincoln.ac.uk) project which has been funded by [JISC](http://jisc.ac.uk) under the Access and Identity Management programme. + +This code was principally developed by [Alex Bilbie](http://alexbilbie.com/) ([Twitter](https://twitter.com/alexbilbie)|[Github](https://github.com/alexbilbie)). + +Valuable contribtions have been made by the following: + +* [Dan Horrigan](http://dandoescode.com) ([Twitter](https://twitter.com/dandoescode)|[Github](https://github.com/dandoescode)) +* [Nick Jackson](http://nickjackson.me) ([Twitter](https://twitter.com/jacksonj04)|[Github](https://github.com/jacksonj04)) \ No newline at end of file From 6a81bcbefc5ce69ca1e1a34903f51f88369ff865 Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Fri, 15 Feb 2013 17:08:27 +0000 Subject: [PATCH 112/113] Updated composer.json --- composer.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 83328f1c..5ba67484 100644 --- a/composer.json +++ b/composer.json @@ -1,7 +1,7 @@ { "name": "lncd/oauth2", "description": "OAuth 2.0 Framework", - "version": "0.4.1", + "version": "1.0.0", "homepage": "https://github.com/lncd/OAuth2", "license": "MIT", "require": { @@ -23,7 +23,8 @@ "server", "authorization", "authentication", - "resource" + "resource", + "api" ], "authors": [ { From 4c46dd222e4f6a36d6bdd025b7203fa974bf11bc Mon Sep 17 00:00:00 2001 From: Alex Bilbie Date: Fri, 15 Feb 2013 17:08:41 +0000 Subject: [PATCH 113/113] Added changelog --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000..4cceea32 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,5 @@ +# Changelog + +## 1.0.0 (released 2012-02-15) + +* First release \ No newline at end of file