From d68233e7ed2878ae21a842b55829936599905bb7 Mon Sep 17 00:00:00 2001 From: Luca Santarella Date: Wed, 29 Jun 2016 12:21:02 -0400 Subject: [PATCH 01/19] Added all Phalcon models and the storage controller --- .../Phalcon/Models/OauthAccessTokens.php | 97 +++ .../Models/OauthAuthorizationCodes.php | 82 +++ .../Storage/Phalcon/Models/OauthClients.php | 92 +++ .../Storage/Phalcon/Models/OauthJti.php | 70 ++ .../Storage/Phalcon/Models/OauthJwt.php | 71 ++ .../Phalcon/Models/OauthPublicKeys.php | 77 ++ .../Phalcon/Models/OauthRefreshTokens.php | 79 ++ .../Storage/Phalcon/Models/OauthScopes.php | 52 ++ .../Storage/Phalcon/Models/OauthUsers.php | 135 ++++ src/OAuth2/Storage/Phalcon/Phalcon.php | 676 ++++++++++++++++++ 10 files changed, 1431 insertions(+) create mode 100644 src/OAuth2/Storage/Phalcon/Models/OauthAccessTokens.php create mode 100644 src/OAuth2/Storage/Phalcon/Models/OauthAuthorizationCodes.php create mode 100644 src/OAuth2/Storage/Phalcon/Models/OauthClients.php create mode 100644 src/OAuth2/Storage/Phalcon/Models/OauthJti.php create mode 100644 src/OAuth2/Storage/Phalcon/Models/OauthJwt.php create mode 100644 src/OAuth2/Storage/Phalcon/Models/OauthPublicKeys.php create mode 100644 src/OAuth2/Storage/Phalcon/Models/OauthRefreshTokens.php create mode 100644 src/OAuth2/Storage/Phalcon/Models/OauthScopes.php create mode 100644 src/OAuth2/Storage/Phalcon/Models/OauthUsers.php create mode 100644 src/OAuth2/Storage/Phalcon/Phalcon.php diff --git a/src/OAuth2/Storage/Phalcon/Models/OauthAccessTokens.php b/src/OAuth2/Storage/Phalcon/Models/OauthAccessTokens.php new file mode 100644 index 000000000..f790ecd65 --- /dev/null +++ b/src/OAuth2/Storage/Phalcon/Models/OauthAccessTokens.php @@ -0,0 +1,97 @@ +setSource("'oauth__access_tokens'"); + $this->belongsTo('user_id', 'OAuth2\Storage\Models\OauthUsers', 'username', array("alias" => "User")); + $this->belongsTo('client_id', 'OAuth2\Storage\Models\OauthClients', 'client_id', array("alias" => "Client")); + } + + /** + * Returns table name mapped in the model. + * + * @return string + */ + public function getSource() + { + return 'oauth__access_tokens'; + } + + /** + * @param mixed $parameters + * @return \OAuth2\Storage\Models\OauthUsers + */ + public function getUser($parameters = null) + { + return $this->getRelated('User', $parameters); + } + + /** + * @param mixed $parameters + * @return \OAuth2\Storage\Models\OauthClients + */ + public function getClient($parameters = null) + { + return $this->getRelated('Client', $parameters); + } + +} diff --git a/src/OAuth2/Storage/Phalcon/Models/OauthAuthorizationCodes.php b/src/OAuth2/Storage/Phalcon/Models/OauthAuthorizationCodes.php new file mode 100644 index 000000000..b81f86131 --- /dev/null +++ b/src/OAuth2/Storage/Phalcon/Models/OauthAuthorizationCodes.php @@ -0,0 +1,82 @@ +setSource("'oauth__clients'"); + $this->belongsTo('user_id', 'OAuth2\Storage\Models\OauthUsers', 'username', array("alias" => "User")); + } + + /** + * Returns table name mapped in the model. + * + * @return string + */ + public function getSource() + { + return 'oauth__clients'; + } + + /** + * Allows to query a set of records that match the specified conditions + * + * @param mixed $parameters + * @return OauthClients[] + */ + public static function find($parameters = null) + { + return parent::find($parameters); + } + + /** + * Allows to query the first record that match the specified conditions + * + * @param mixed $parameters + * @return OauthClients + */ + public static function findFirst($parameters = null) + { + return parent::findFirst($parameters); + } + + /** + * @param mixed $parameters + * @return OauthUsers + */ + public function getUser($parameters = null){ + return $this->getRelated('User', $parameters); + } +} diff --git a/src/OAuth2/Storage/Phalcon/Models/OauthJti.php b/src/OAuth2/Storage/Phalcon/Models/OauthJti.php new file mode 100644 index 000000000..58699eef0 --- /dev/null +++ b/src/OAuth2/Storage/Phalcon/Models/OauthJti.php @@ -0,0 +1,70 @@ +setSource("'oauth__jwt'"); + $this->belongsTo('client_id', 'OAuth2\Storage\Models\OauthClients', 'client_id', array("alias" => "Client")); + } + + /** + * Returns table name mapped in the model. + * + * @return string + */ + public function getSource() + { + return 'oauth__jwt'; + } + + public function getClient($parameters = null) + { + return $this->getRelated('Client', $parameters); + } +} diff --git a/src/OAuth2/Storage/Phalcon/Models/OauthPublicKeys.php b/src/OAuth2/Storage/Phalcon/Models/OauthPublicKeys.php new file mode 100644 index 000000000..4a86faf1e --- /dev/null +++ b/src/OAuth2/Storage/Phalcon/Models/OauthPublicKeys.php @@ -0,0 +1,77 @@ +setSource("'oauth__public_keys'"); + $this->belongsTo('client_id', 'OAuth2\Storage\Models\OauthClients', 'client_id', array("alias" => "Client")); + } + + /** + * Returns table name mapped in the model. + * + * @return string + */ + public function getSource() + { + return 'oauth__public_keys'; + } + + public function getClient($parameters = null) + { + return $this->getRelated('Client', $parameters); + } +} diff --git a/src/OAuth2/Storage/Phalcon/Models/OauthRefreshTokens.php b/src/OAuth2/Storage/Phalcon/Models/OauthRefreshTokens.php new file mode 100644 index 000000000..e0d382b74 --- /dev/null +++ b/src/OAuth2/Storage/Phalcon/Models/OauthRefreshTokens.php @@ -0,0 +1,79 @@ +setSource("'oauth__refresh_tokens'"); + $this->belongsTo('user_id', 'OAuth2\Storage\Models\OauthUsers', 'username'); + $this->belongsTo('client_id', 'OAuth2\Storage\Models\OauthClients', 'client_id'); + } + + /** + * Returns table name mapped in the model. + * + * @return string + */ + public function getSource() + { + return 'oauth__refresh_tokens'; + } + +} diff --git a/src/OAuth2/Storage/Phalcon/Models/OauthScopes.php b/src/OAuth2/Storage/Phalcon/Models/OauthScopes.php new file mode 100644 index 000000000..5ceff932c --- /dev/null +++ b/src/OAuth2/Storage/Phalcon/Models/OauthScopes.php @@ -0,0 +1,52 @@ +keepSnapshots(true); + $this->setSource("'oauth__users'"); + $this->hasMany('username', 'OAuth2\Storage\Models\OauthAccessTokens', 'user_id', array("alias" => "AccessTokens")); + $this->hasMany('username', 'OAuth2\Storage\Models\OauthRefreshTokens', 'user_id', array("alias" => "RefreshTokens")); + } + + /** + * Validations and business logic + * + * @return boolean + */ + public function validation() + { + $this->validate( + new Email( + array( + 'field' => 'email', + 'required' => true, + ) + ) + ); + + if ($this->validationHasFailed() == true) { + return false; + } + + return true; + } + + /** + * Returns table name mapped in the model. + * + * @return string + */ + public function getSource() + { + return 'oauth__users'; + } + + /** + * @param mixed $parameters + * @return \OAuth2\Storage\Models\OauthAccessTokens[] + */ + public function getAccessTokens($parameters = null) + { + return $this->getRelated('AccessTokens', $parameters); + } + + /** + * @param mixed $parameters + * @return \OAuth2\Storage\Models\OauthRefreshTokens[] + */ + public function getRefreshTokens($parameters = null) + { + return $this->getRelated('RefreshTokens', $parameters); + } +} \ No newline at end of file diff --git a/src/OAuth2/Storage/Phalcon/Phalcon.php b/src/OAuth2/Storage/Phalcon/Phalcon.php new file mode 100644 index 000000000..729ebc90e --- /dev/null +++ b/src/OAuth2/Storage/Phalcon/Phalcon.php @@ -0,0 +1,676 @@ + + */ +class Phalcon implements + AuthorizationCodeInterface, + AccessTokenInterface, + ClientCredentialsInterface, + UserCredentialsInterface, + RefreshTokenInterface, + JwtBearerInterface, + ScopeInterface, + PublicKeyInterface, + UserClaimsInterface, + OpenIDAuthorizationCodeInterface +{ + protected $db; + protected $config; + + /** + * Phalcon constructor. + * @param \Phalcon\DiInterface $di Dependency Injector from the Phalcon Application, this is necessary for Model Lookups + * @param array $config Config to append to the current config + */ + public function __construct($di, $config = array()) + { + $this->di = $di; + $this->config = array_merge(array( + 'client_table' => 'oauth__clients', + 'access_token_table' => 'oauth__access_tokens', + 'refresh_token_table' => 'oauth__refresh_tokens', + 'code_table' => 'oauth__authorization_codes', + 'user_table' => 'oauth__users', + 'jwt_table' => 'oauth__jwt', + 'jti_table' => 'oauth__jti', + 'scope_table' => 'oauth__scopes', + 'public_key_table' => 'oauth__public_keys', + ), $config); + } + + /** + * @param $client_id + * @param null $client_secret + * @return bool + */ + public function checkClientCredentials($client_id, $client_secret = null) + { + $clients = Models\OauthClients::findFirst( + array( + "conditions" => "client_id = ?1 AND client_secret = ?2", + "bind" => array(1 => $client_id, 2 => $client_secret), + "limit" => 1 + ) + ); + + return $clients != false; + } + + /** + * @param $client_id + * @return bool + */ + public function isPublicClient($client_id) + { + $clients = Models\OauthClients::findFirst( + array( + "conditions" => "client_id = ?1", + "bind" => array(1 => $client_id), + "limit" => 1 + ) + ); + + return empty($clients['client_secret']); + } + + /** + * @param $client_id + * @param null $client_secret + * @param null $redirect_uri + * @param null $grant_types + * @param null $scope + * @param null $user_id + * @return mixed + */ + public function setClientDetails($client_id, $client_secret = null, $redirect_uri = null, $grant_types = null, $scope = null, $user_id = null) + { + $client = new Models\OauthClients(); + $client->client_id = $client_id; + + // Update the fields only if they are set + isset($client_secret) ?: $client->client_secret = $client_secret; + isset($redirect_uri) ?: $client->redirect_uri = $redirect_uri; + isset($grant_types) ?: $client->grant_types = $grant_types; + isset($scope) ?: $client->scope = $scope; + isset($user_id) ?: $client->user_id = $user_id; + + return $client->save(); + } + + public function checkRestrictedGrantType($client_id, $grant_type) + { + $details = $this->getClientDetails($client_id); + + if (isset($details['grant_types'])) { + $grant_types = explode(' ', $details['grant_types']); + return in_array($grant_type, (array)$grant_types); + } + + // if grant_types are not defined, then none are restricted + return true; + } + + /** + * @param $client_id + * @return array + */ + public function getClientDetails($client_id) + { + $clients = Models\OauthClients::findFirst( + array( + "conditions" => "client_id = ?1", + "bind" => array(1 => $client_id), + "limit" => 1 + ) + ); + + return $clients->toArray(); + } + + /* OAuth2\Storage\AccessTokenInterface */ + + public function getAccessToken($access_token) + { + $token = Models\OauthAccessTokens::findFirst( + array( + "conditions" => "access_token = ?1", + "bind" => array(1 => $access_token), + "limit" => 1 + ) + ); + if ($token->count() == 1) { + $token['expires'] = strtotime($token['expires']); + } + + return $token; + } + + public function setAccessToken($access_token, $client_id, $user_id, $expires, $scope = null) + { + // convert expires to datestring + $expires = date('Y-m-d H:i:s', $expires); + + $token = new Models\OauthAccessTokens(); + $token->access_token = $access_token; + + // Update the fields only if they are set + $token->client_id = $client_id; + $token->client_ip = $_SERVER['REMOTE_ADDR']; + $token->client_useragent = $_SERVER['HTTP_USER_AGENT']; + $token->user_id = $user_id; + $token->expires = $expires; + isset($scope) ?: $token->scope = $scope; + + return $token->save(); + } + + public function unsetAccessToken($access_token) + { + $token = Models\OauthAccessTokens::findFirst( + array( + "conditions" => "access_token = ?1", + "bind" => array(1 => $access_token), + "limit" => 1 + ) + ); + return $token->delete(); + } + + /* OAuth2\Storage\AuthorizationCodeInterface */ + public function getAuthorizationCode($code) + { + $code = Models\OauthAuthorizationCodes::findFirst( + array( + "conditions" => "authorization_code = ?1", + "bind" => array(1 => $code), + "limit" => 1 + ) + ); + if ($code->count() == 1) { + $code['expires'] = strtotime($code['expires']); + } + return $code; + } + + public function setAuthorizationCode($code, $client_id, $user_id, $redirect_uri, $expires, $scope = null, $id_token = null) + { + // Convert expires to datestring + $expires = date('Y-m-d H:i:s', $expires); + + $authCode = new Models\OauthAuthorizationCodes(); + $authCode->authorization_code = $code; + $authCode->client_id = $client_id; + $authCode->user_id = $user_id; + $authCode->redirect_uri = $redirect_uri; + $authCode->expires = $expires; + + // Update the fields only if they are set + isset($scope) ?: $authCode->scope = $scope; + isset($id_token) ?: $authCode->id_token = $id_token; + + return $authCode->save(); + } + + public function expireAuthorizationCode($code) + { + $code = Models\OauthAuthorizationCodes::findFirst( + array( + "conditions" => "authorization_code = ?1", + "bind" => array(1 => $code), + "limit" => 1 + ) + ); + + return $code->delete(); + } + + /* OAuth2\Storage\UserCredentialsInterface */ + public function checkUserCredentials($username, $password) + { + if ($user = $this->getUser($username)) { + return $this->checkPassword($user, $password); + } + return false; + } + + public function getUser($username) + { + $user = Models\OauthUsers::findFirst( + array( + "conditions" => "username = ?1", + "bind" => array(1 => $username), + "limit" => 1 + ) + ); + + if ($user == false) { + return false; + } + + return array_merge(array('user_id' => $username), $user->toArray()); + } + + /* UserClaimsInterface */ + + protected function checkPassword($user, $password) + { + return $user['password'] == $this->hashPassword($password); + } + + protected function hashPassword($password) + { + return sha1($password); + } + + /* OAuth2\Storage\RefreshTokenInterface */ + + public function getUserClaims($user_id, $claims) + { + if (!$userDetails = $this->getUserDetails($user_id)) { + return false; + } + + $claims = explode(' ', trim($claims)); + $userClaims = array(); + + // for each requested claim, if the user has the claim, set it in the response + $validClaims = explode(' ', self::VALID_CLAIMS); + foreach ($validClaims as $validClaim) { + if (in_array($validClaim, $claims)) { + if ($validClaim == 'address') { + // address is an object with subfields + $userClaims['address'] = $this->getUserClaim($validClaim, $userDetails['address'] ?: $userDetails); + } else { + $userClaims = array_merge($userClaims, $this->getUserClaim($validClaim, $userDetails)); + } + } + } + + return $userClaims; + } + + public function getUserDetails($username) + { + return $this->getUser($username); + } + + protected function getUserClaim($claim, $userDetails) + { + $userClaims = array(); + $claimValuesString = constant(sprintf('self::%s_CLAIM_VALUES', strtoupper($claim))); + $claimValues = explode(' ', $claimValuesString); + + foreach ($claimValues as $value) { + $userClaims[$value] = isset($userDetails[$value]) ? $userDetails[$value] : null; + } + + return $userClaims; + } + + // plaintext passwords are bad! Override this for your application + + public function getRefreshToken($refresh_token) + { + $token = Models\OauthRefreshTokens::findFirst( + array( + "conditions" => "refresh_token = ?1", + "bind" => array(1 => $refresh_token), + "limit" => 1 + ) + ); + + if ($token != false) { + // convert expires to epoch time + $token->expires = strtotime($token->expires); + } + + return $token->toArray(); + } + + // use a secure hashing algorithm when storing passwords. Override this for your application + + public function setRefreshToken($refresh_token, $client_id, $user_id, $expires, $scope = null) + { + // convert expires to datestring + $expires = date('Y-m-d H:i:s', $expires); + + $token = new Models\OauthRefreshTokens(); + $token->refresh_token = $refresh_token; + $token->client_id = $client_id; + $token->user_id = $user_id; + $token->expires = $expires; + $token->client_ip = $_SERVER['REMOTE_ADDR']; + $token->client_useragent = $_SERVER['HTTP_USER_AGENT']; + isset($scope) ?: $token->scope = $scope; + + return $token->save(); + } + + public function unsetRefreshToken($refresh_token) + { + $token = Models\OauthRefreshTokens::findFirst( + array( + "conditions" => "refresh_token = ?1", + "bind" => array(1 => $refresh_token), + "limit" => 1 + ) + ); + + return $token->delete(); + } + + public function setUser($username, $password, $firstName = null, $lastName = null) + { + // do not store in plaintext + $password = $this->hashPassword($password); + + $user = Models\OauthUsers::findFirst( + array( + "conditions" => "username = ?1", + "bind" => array(1 => $username), + "limit" => 1 + ) + ); + + $user->password = $password; + + // Update values only if set + isset($firstName) ?: $user->first_name = $firstName; + isset($lastName) ?: $user->first_name = $lastName; + + return $user->save(); + } + + + /* JWTBearerInterface */ + public function getClientKey($client_id, $subject) + { + + $clientKey = Models\OauthJwt::findFirst( + array( + "conditions" => "client_id = ?1 AND subject = ?2", + "bind" => array(1 => $client_id, 2 => $subject), + "limit" => 1 + ) + ); + + return $clientKey->count() == 1 ? $clientKey->client_id : false; + } + + public function getClientScope($client_id) + { + if (!$clientDetails = $this->getClientDetails($client_id)) { + return false; + } + + if (isset($clientDetails['scope'])) { + return $clientDetails['scope']; + } + + return null; + } + + /** + * Check if the provided scope exists. + * + * @param $scope + * A space-separated string of scopes. + * + * @return boolean + * TRUE if it exists, FALSE otherwise. + */ + public function scopeExists($scope) + { + $scopeRow = Models\OauthScopes::findFirst( + array( + "conditions" => "scope = ?1", + "bind" => array(1 => $scope), + "limit" => 1 + ) + ); + + return $scopeRow == 1; + } + + /** + * The default scope to use in the event the client + * does not request one. By returning "false", a + * request_error is returned by the server to force a + * scope request by the client. By returning "null", + * opt out of requiring scopes + * + * @param $client_id + * An optional client id that can be used to return customized default scopes. + * + * @return + * string representation of default scope, null if + * scopes are not defined, or false to force scope + * request by the client + * + * ex: + * 'default' + * ex: + * null + */ + public function getDefaultScope($client_id = null) + { + $scopes = Models\OauthScopes::find( + array( + "conditions" => "is_default = ?1", + "bind" => array(1 => true) + ) + ); + + if (count($scopes) >= 1) { + $defaultScope = array_map(function ($row) { + return $row->scope; + }, $scopes); + + return implode(' ', $defaultScope); + } + + return null; + } + + public function getJti($client_id, $subject, $audience, $expires, $jti) + { + + $result = Models\OauthJti::findFirst( + array( + "conditions" => "client_id = :client_id: AND subject = :subject: AND audience = :audience: AND expires = :expires: AND jti = :jti:", + "bind" => array( + "client_id" => $client_id, + "subject" => $subject, + "audience" => $audience, + "expires" => $expires, + "jti" => $jti + ), + "limit" => 1 + ) + ); + + if ($result->count() == 1) { + $result = $result->toArray(); + return array( + 'issuer' => $result['issuer'], + 'subject' => $result['subject'], + 'audience' => $result['audience'], + 'expires' => $result['expires'], + 'jti' => $result['jti'], + ); + } + + return null; + } + + public function setJti($client_id, $subject, $audience, $expires, $jti) + { + $jtiModel = new Models\OauthJti(); + $jtiModel->issuer = $client_id; + $jtiModel->subject = $subject; + $jtiModel->audience = $audience; + $jtiModel->expires = $expires; + $jtiModel->jti = $jti; + + return $jtiModel->save(); + } + + /* PublicKeyInterface */ + public function getPublicKey($client_id = null) + { + $publicKey = Models\OauthPublicKeys::findFirst( + array( + "conditions" => "client_id = ?1", + "bind" => array(1 => $client_id), + "limit" => 1 + ) + ); + + if ($array = $publicKey->toArray()) + return $array['public_key']; + else + return false; + } + + public function getPrivateKey($client_id = null) + { + $publicKey = Models\OauthPublicKeys::findFirst( + array( + "conditions" => "client_id = ?1", + "bind" => array(1 => $client_id), + "limit" => 1 + ) + ); + + if ($array = $publicKey->toArray()) + return $array['private_key']; + else + return false; + } + + public function getEncryptionAlgorithm($client_id = null) + { + $publicKey = Models\OauthPublicKeys::findFirst( + array( + "conditions" => "client_id = ?1", + "bind" => array(1 => $client_id), + "limit" => 1 + ) + ); + + if ($array = $publicKey->toArray()) + return $array['encryption_algorithm']; + else + return 'RS256'; + } + + /** + * DDL to create OAuth2 database and tables for PDO/Phalcon storage + * + * @see https://github.com/dsquier/oauth2-server-php-mysql + */ + public function getBuildSql($dbName = 'oauth2_server_php') + { + $sql = " + CREATE TABLE {$this->config['client_table']} ( + `client_id` varchar(80) NOT NULL, + `client_secret` varchar(80) DEFAULT NULL, + `redirect_uri` varchar(2000) DEFAULT NULL, + `grant_types` varchar(80) DEFAULT NULL, + `scope` varchar(4000) DEFAULT NULL, + `user_id` varchar(80) DEFAULT NULL, + PRIMARY KEY (client_id) + ); + CREATE TABLE {$this->config['access_token_table']} ( + `access_token` varchar(40) NOT NULL, + `valid` tinyint(1) NOT NULL DEFAULT '1', + `client_ip` varchar(155) NOT NULL, + `client_useragent` text NOT NULL, + `client_id` varchar(80) NOT NULL, + `user_id` varchar(80) DEFAULT NULL, + `expires` timestamp NOT NULL, + `scope` varchar(4000) DEFAULT NULL + PRIMARY KEY (access_token) + ); + + CREATE TABLE {$this->config['code_table']} ( + `authorization_code` varchar(40) NOT NULL, + `client_id` varchar(80) NOT NULL, + `user_id` varchar(80) DEFAULT NULL, + `redirect_uri` varchar(2000) DEFAULT NULL, + `expires` timestamp NOT NULL, + `scope` varchar(4000) DEFAULT NULL, + `id_token` varchar(1000) DEFAULT NULL, + PRIMARY KEY (authorization_code) + ); + + CREATE TABLE {$this->config['refresh_token_table']} ( + `refresh_token` varchar(40) NOT NULL, + `valid` tinyint(1) NOT NULL DEFAULT '1', + `client_id` varchar(80) NOT NULL, + `user_id` varchar(80) DEFAULT NULL, + `client_ip` varchar(155) NOT NULL, + `client_useragent` text NOT NULL, + `expires` timestamp NOT NULL, + `scope` varchar(4000) DEFAULT NULL, + PRIMARY KEY (refresh_token) + ); + + CREATE TABLE {$this->config['user_table']} ( + `id` bigint(20) NOT NULL AUTO_INCREMENT, + `status` tinyint(2) NOT NULL DEFAULT '0', + `username` varchar(80) NOT NULL DEFAULT '', + `password` varchar(80) DEFAULT NULL, + `first_name` varchar(80) DEFAULT NULL, + `last_name` varchar(80) DEFAULT NULL, + `email` varchar(80) DEFAULT NULL, + `email_verified` tinyint(1) DEFAULT NULL, + `scope` varchar(4000) DEFAULT NULL + ); + + CREATE TABLE {$this->config['scope_table']} ( + `scope` varchar(80) NOT NULL, + `is_default` tinyint(1) DEFAULT NULL, + PRIMARY KEY (scope) + ); + + CREATE TABLE {$this->config['jwt_table']} ( + `client_id` varchar(80) NOT NULL, + `subject` varchar(80) DEFAULT NULL, + `public_key` varchar(2000) NOT NULL + ); + + CREATE TABLE {$this->config['jti_table']} ( + `issuer` varchar(80) NOT NULL, + `subject` varchar(80) DEFAULT NULL, + `audience` varchar(80) DEFAULT NULL, + `expires` timestamp NOT NULL, + `jti` varchar(2000) NOT NULL + ); + + CREATE TABLE {$this->config['public_key_table']} ( + `client_id` varchar(80) DEFAULT NULL, + `public_key` varchar(2000) DEFAULT NULL, + `private_key` varchar(2000) DEFAULT NULL, + `encryption_algorithm` varchar(100) DEFAULT 'RS256' + ); + "; + + return $sql; + } + + +} From 074d36650081edb23d8482835f9e818244f28acf Mon Sep 17 00:00:00 2001 From: Luca Santarella Date: Wed, 29 Jun 2016 13:10:19 -0400 Subject: [PATCH 02/19] Updated Oauth logic to be compliant with the standard --- src/OAuth2/Storage/Phalcon/Phalcon.php | 334 +++++++++++++------------ 1 file changed, 169 insertions(+), 165 deletions(-) diff --git a/src/OAuth2/Storage/Phalcon/Phalcon.php b/src/OAuth2/Storage/Phalcon/Phalcon.php index 729ebc90e..980973685 100644 --- a/src/OAuth2/Storage/Phalcon/Phalcon.php +++ b/src/OAuth2/Storage/Phalcon/Phalcon.php @@ -58,15 +58,15 @@ public function __construct($di, $config = array()) */ public function checkClientCredentials($client_id, $client_secret = null) { - $clients = Models\OauthClients::findFirst( + $client = Models\OauthClients::findFirst( array( - "conditions" => "client_id = ?1 AND client_secret = ?2", - "bind" => array(1 => $client_id, 2 => $client_secret), + "conditions" => "client_id = ?1", + "bind" => array(1 => $client_id), "limit" => 1 ) ); - return $clients != false; + return $client != false && $client->client_secret == $client_secret; } /** @@ -83,7 +83,24 @@ public function isPublicClient($client_id) ) ); - return empty($clients['client_secret']); + return empty($clients->client_secret); + } + + /** + * @param $client_id + * @return array + */ + public function getClientDetails($client_id) + { + $clients = Models\OauthClients::findFirst( + array( + "conditions" => "client_id = ?1", + "bind" => array(1 => $client_id), + "limit" => 1 + ) + ); + + return $clients->toArray(); } /** @@ -100,12 +117,11 @@ public function setClientDetails($client_id, $client_secret = null, $redirect_ur $client = new Models\OauthClients(); $client->client_id = $client_id; - // Update the fields only if they are set - isset($client_secret) ?: $client->client_secret = $client_secret; - isset($redirect_uri) ?: $client->redirect_uri = $redirect_uri; - isset($grant_types) ?: $client->grant_types = $grant_types; - isset($scope) ?: $client->scope = $scope; - isset($user_id) ?: $client->user_id = $user_id; + $client->client_secret = $client_secret; + $client->redirect_uri = $redirect_uri; + $client->grant_types = $grant_types; + $client->scope = $scope; + $client->user_id = $user_id; return $client->save(); } @@ -123,23 +139,6 @@ public function checkRestrictedGrantType($client_id, $grant_type) return true; } - /** - * @param $client_id - * @return array - */ - public function getClientDetails($client_id) - { - $clients = Models\OauthClients::findFirst( - array( - "conditions" => "client_id = ?1", - "bind" => array(1 => $client_id), - "limit" => 1 - ) - ); - - return $clients->toArray(); - } - /* OAuth2\Storage\AccessTokenInterface */ public function getAccessToken($access_token) @@ -151,11 +150,15 @@ public function getAccessToken($access_token) "limit" => 1 ) ); - if ($token->count() == 1) { - $token['expires'] = strtotime($token['expires']); - } - return $token; + if ($token != false) { + $tokenArray = $token->toArray(); + $tokenArray['expires'] = strtotime($token->expires); + return $tokenArray; + } else { + // If token == false, then return false + return false; + } } public function setAccessToken($access_token, $client_id, $user_id, $expires, $scope = null) @@ -199,31 +202,67 @@ public function getAuthorizationCode($code) "limit" => 1 ) ); - if ($code->count() == 1) { - $code['expires'] = strtotime($code['expires']); + if ($code != false) { + $codeArray = $code->toArray(); + $codeArray['expires'] = strtotime($code->expires); + return $codeArray; + } else { + // If code == false, then return false + return false; } - return $code; } public function setAuthorizationCode($code, $client_id, $user_id, $redirect_uri, $expires, $scope = null, $id_token = null) { + // Convert expires to datestring $expires = date('Y-m-d H:i:s', $expires); - $authCode = new Models\OauthAuthorizationCodes(); + // if it exists, update it. + $authCode = $this->getAuthorizationCode($code); + if ($authCode == false) + $authCode = new Models\OauthAuthorizationCodes(); + $authCode->authorization_code = $code; $authCode->client_id = $client_id; $authCode->user_id = $user_id; $authCode->redirect_uri = $redirect_uri; $authCode->expires = $expires; - // Update the fields only if they are set - isset($scope) ?: $authCode->scope = $scope; - isset($id_token) ?: $authCode->id_token = $id_token; + $authCode->scope = $scope; + $authCode->id_token = $id_token; return $authCode->save(); } + /** + * @deprecated No longer used. + * @see setAuthorizationCode. + */ + public function setAuthorizationCodeWithIdToken($code, $client_id, $user_id, $redirect_uri, $expires, $scope = null, $id_token = null) + { + + // Convert expires to datestring + $expires = date('Y-m-d H:i:s', $expires); + + // if it exists, update it. + $authCode = $this->getAuthorizationCode($code); + if ($authCode == false) + $authCode = new Models\OauthAuthorizationCodes(); + + $authCode->authorization_code = $code; + $authCode->client_id = $client_id; + $authCode->user_id = $user_id; + $authCode->redirect_uri = $redirect_uri; + $authCode->expires = $expires; + $authCode->id_token = $id_token; + + $authCode->scope = $scope; + + return $authCode->save(); + } + + public function expireAuthorizationCode($code) { $code = Models\OauthAuthorizationCodes::findFirst( @@ -246,37 +285,12 @@ public function checkUserCredentials($username, $password) return false; } - public function getUser($username) + public function getUserDetails($username) { - $user = Models\OauthUsers::findFirst( - array( - "conditions" => "username = ?1", - "bind" => array(1 => $username), - "limit" => 1 - ) - ); - - if ($user == false) { - return false; - } - - return array_merge(array('user_id' => $username), $user->toArray()); + return $this->getUser($username); } /* UserClaimsInterface */ - - protected function checkPassword($user, $password) - { - return $user['password'] == $this->hashPassword($password); - } - - protected function hashPassword($password) - { - return sha1($password); - } - - /* OAuth2\Storage\RefreshTokenInterface */ - public function getUserClaims($user_id, $claims) { if (!$userDetails = $this->getUserDetails($user_id)) { @@ -302,11 +316,6 @@ public function getUserClaims($user_id, $claims) return $userClaims; } - public function getUserDetails($username) - { - return $this->getUser($username); - } - protected function getUserClaim($claim, $userDetails) { $userClaims = array(); @@ -320,8 +329,6 @@ protected function getUserClaim($claim, $userDetails) return $userClaims; } - // plaintext passwords are bad! Override this for your application - public function getRefreshToken($refresh_token) { $token = Models\OauthRefreshTokens::findFirst( @@ -333,11 +340,13 @@ public function getRefreshToken($refresh_token) ); if ($token != false) { - // convert expires to epoch time - $token->expires = strtotime($token->expires); + $tokenArray = $token->toArray(); + $tokenArray['expires'] = strtotime($token->expires); + return $tokenArray; + } else { + // If token == false, then return false + return false; } - - return $token->toArray(); } // use a secure hashing algorithm when storing passwords. Override this for your application @@ -354,7 +363,7 @@ public function setRefreshToken($refresh_token, $client_id, $user_id, $expires, $token->expires = $expires; $token->client_ip = $_SERVER['REMOTE_ADDR']; $token->client_useragent = $_SERVER['HTTP_USER_AGENT']; - isset($scope) ?: $token->scope = $scope; + $token->scope = $scope; return $token->save(); } @@ -372,99 +381,71 @@ public function unsetRefreshToken($refresh_token) return $token->delete(); } - public function setUser($username, $password, $firstName = null, $lastName = null) + protected function checkPassword($user, $password) { - // do not store in plaintext - $password = $this->hashPassword($password); - - $user = Models\OauthUsers::findFirst( - array( - "conditions" => "username = ?1", - "bind" => array(1 => $username), - "limit" => 1 - ) - ); - - $user->password = $password; - - // Update values only if set - isset($firstName) ?: $user->first_name = $firstName; - isset($lastName) ?: $user->first_name = $lastName; - - return $user->save(); + return $user['password'] == $this->hashPassword($password); } - - /* JWTBearerInterface */ - public function getClientKey($client_id, $subject) + protected function hashPassword($password) { + return sha1($password); + } - $clientKey = Models\OauthJwt::findFirst( + public function getUser($username) + { + $user = Models\OauthUsers::findFirst( array( - "conditions" => "client_id = ?1 AND subject = ?2", - "bind" => array(1 => $client_id, 2 => $subject), + "conditions" => "username = ?1", + "bind" => array(1 => $username), "limit" => 1 ) ); - return $clientKey->count() == 1 ? $clientKey->client_id : false; + if ($user == false) + return false; + else + return array_merge(array('user_id' => $username), $user->toArray()); } - public function getClientScope($client_id) + public function setUser($username, $password, $firstName = null, $lastName = null) { - if (!$clientDetails = $this->getClientDetails($client_id)) { - return false; - } + // do not store in plaintext + $password = $this->hashPassword($password); - if (isset($clientDetails['scope'])) { - return $clientDetails['scope']; + // if it exists, update it. + $user = $this->getUser($username); + if ($user == false) { + $user = Models\OauthUsers::findFirst( + array( + "conditions" => "username = ?1", + "bind" => array(1 => $username), + "limit" => 1 + ) + ); + $user->username = $username; } + $user->password = $password; + $user->first_name = $firstName; + $user->first_name = $lastName; - return null; + return $user->save(); } - /** - * Check if the provided scope exists. - * - * @param $scope - * A space-separated string of scopes. - * - * @return boolean - * TRUE if it exists, FALSE otherwise. - */ public function scopeExists($scope) { - $scopeRow = Models\OauthScopes::findFirst( + $scope = explode(' ', $scope); + $whereIn = implode(',', array_fill(0, count($scope), '?')); + $result = Models\OauthScopes::count( array( - "conditions" => "scope = ?1", - "bind" => array(1 => $scope), + "conditions" => "scope IN(?1)", + "bind" => array(1 => $whereIn), "limit" => 1 ) ); - return $scopeRow == 1; + return $result == count($scope); } - /** - * The default scope to use in the event the client - * does not request one. By returning "false", a - * request_error is returned by the server to force a - * scope request by the client. By returning "null", - * opt out of requiring scopes - * - * @param $client_id - * An optional client id that can be used to return customized default scopes. - * - * @return - * string representation of default scope, null if - * scopes are not defined, or false to force scope - * request by the client - * - * ex: - * 'default' - * ex: - * null - */ public function getDefaultScope($client_id = null) { $scopes = Models\OauthScopes::find( @@ -485,35 +466,58 @@ public function getDefaultScope($client_id = null) return null; } + /* JWTBearerInterface */ + public function getClientKey($client_id, $subject) + { + + $clientKey = Models\OauthJwt::findFirst( + array( + "conditions" => "client_id = ?1 AND subject = ?2", + "bind" => array(1 => $client_id, 2 => $subject), + "limit" => 1 + ) + ); + + if ($clientKey != false) + return $clientKey->public_key; + else + return false; + } + + public function getClientScope($client_id) + { + if (!$clientDetails = $this->getClientDetails($client_id)) { + return false; + } + + if (isset($clientDetails['scope'])) { + return $clientDetails['scope']; + } + + return null; + } + public function getJti($client_id, $subject, $audience, $expires, $jti) { $result = Models\OauthJti::findFirst( array( "conditions" => "client_id = :client_id: AND subject = :subject: AND audience = :audience: AND expires = :expires: AND jti = :jti:", - "bind" => array( + "bind" => [ "client_id" => $client_id, "subject" => $subject, "audience" => $audience, "expires" => $expires, "jti" => $jti - ), + ], "limit" => 1 ) ); - if ($result->count() == 1) { - $result = $result->toArray(); - return array( - 'issuer' => $result['issuer'], - 'subject' => $result['subject'], - 'audience' => $result['audience'], - 'expires' => $result['expires'], - 'jti' => $result['jti'], - ); - } - - return null; + if ($result != false) + return $result->toArray(['issuer','subject','audience','expires','jti']); + else + return null; } public function setJti($client_id, $subject, $audience, $expires, $jti) @@ -533,14 +537,14 @@ public function getPublicKey($client_id = null) { $publicKey = Models\OauthPublicKeys::findFirst( array( - "conditions" => "client_id = ?1", + "conditions" => "client_id = ?1 OR client_id IS NULL", "bind" => array(1 => $client_id), "limit" => 1 ) ); - if ($array = $publicKey->toArray()) - return $array['public_key']; + if ($publicKey != false) + return $publicKey-> public_key; else return false; } @@ -555,8 +559,8 @@ public function getPrivateKey($client_id = null) ) ); - if ($array = $publicKey->toArray()) - return $array['private_key']; + if ($publicKey != false) + return $publicKey->private_key; else return false; } @@ -571,8 +575,8 @@ public function getEncryptionAlgorithm($client_id = null) ) ); - if ($array = $publicKey->toArray()) - return $array['encryption_algorithm']; + if ($publicKey != false) + return $publicKey->encryption_algorithm; else return 'RS256'; } From eedce8fc62e86eb3622d1e4b788470d7319d4128 Mon Sep 17 00:00:00 2001 From: Luca Santarella Date: Wed, 29 Jun 2016 14:33:34 -0400 Subject: [PATCH 03/19] Updated namespaces --- .../Phalcon/Models/OauthAccessTokens.php | 2 +- .../Phalcon/Models/OauthAuthorizationCodes.php | 2 +- .../Storage/Phalcon/Models/OauthClients.php | 2 +- src/OAuth2/Storage/Phalcon/Models/OauthJti.php | 2 +- src/OAuth2/Storage/Phalcon/Models/OauthJwt.php | 2 +- .../Storage/Phalcon/Models/OauthPublicKeys.php | 2 +- .../Phalcon/Models/OauthRefreshTokens.php | 2 +- .../Storage/Phalcon/Models/OauthScopes.php | 2 +- .../Storage/Phalcon/Models/OauthUsers.php | 2 +- src/OAuth2/Storage/Phalcon/Phalcon.php | 18 ++++++++++++------ 10 files changed, 21 insertions(+), 15 deletions(-) diff --git a/src/OAuth2/Storage/Phalcon/Models/OauthAccessTokens.php b/src/OAuth2/Storage/Phalcon/Models/OauthAccessTokens.php index f790ecd65..6550bd376 100644 --- a/src/OAuth2/Storage/Phalcon/Models/OauthAccessTokens.php +++ b/src/OAuth2/Storage/Phalcon/Models/OauthAccessTokens.php @@ -1,6 +1,6 @@ toArray(['issuer','subject','audience','expires','jti']); + return $result->toArray(['issuer', 'subject', 'audience', 'expires', 'jti']); else return null; } @@ -544,7 +550,7 @@ public function getPublicKey($client_id = null) ); if ($publicKey != false) - return $publicKey-> public_key; + return $publicKey->public_key; else return false; } From 04f183eae8a7761960623e0652173f436cd744c3 Mon Sep 17 00:00:00 2001 From: Luca Santarella Date: Wed, 29 Jun 2016 21:54:14 -0400 Subject: [PATCH 04/19] Cleaned up code to be consistent and pretty --- .../Phalcon/Models/OauthAccessTokens.php | 2 +- .../Models/OauthAuthorizationCodes.php | 2 +- .../Storage/Phalcon/Models/OauthClients.php | 44 ++++++++++--------- .../Storage/Phalcon/Models/OauthJti.php | 2 +- .../Storage/Phalcon/Models/OauthJwt.php | 3 +- .../Phalcon/Models/OauthPublicKeys.php | 3 +- .../Phalcon/Models/OauthRefreshTokens.php | 2 +- .../Storage/Phalcon/Models/OauthScopes.php | 2 +- .../Storage/Phalcon/Models/OauthUsers.php | 1 + src/OAuth2/Storage/Phalcon/Phalcon.php | 39 ++++------------ 10 files changed, 42 insertions(+), 58 deletions(-) diff --git a/src/OAuth2/Storage/Phalcon/Models/OauthAccessTokens.php b/src/OAuth2/Storage/Phalcon/Models/OauthAccessTokens.php index 6550bd376..502af8106 100644 --- a/src/OAuth2/Storage/Phalcon/Models/OauthAccessTokens.php +++ b/src/OAuth2/Storage/Phalcon/Models/OauthAccessTokens.php @@ -94,4 +94,4 @@ public function getClient($parameters = null) return $this->getRelated('Client', $parameters); } -} +} \ No newline at end of file diff --git a/src/OAuth2/Storage/Phalcon/Models/OauthAuthorizationCodes.php b/src/OAuth2/Storage/Phalcon/Models/OauthAuthorizationCodes.php index d7028d17d..1d7e5001e 100644 --- a/src/OAuth2/Storage/Phalcon/Models/OauthAuthorizationCodes.php +++ b/src/OAuth2/Storage/Phalcon/Models/OauthAuthorizationCodes.php @@ -79,4 +79,4 @@ public static function findFirst($parameters = null) return parent::findFirst($parameters); } -} +} \ No newline at end of file diff --git a/src/OAuth2/Storage/Phalcon/Models/OauthClients.php b/src/OAuth2/Storage/Phalcon/Models/OauthClients.php index a4a733009..35c660202 100644 --- a/src/OAuth2/Storage/Phalcon/Models/OauthClients.php +++ b/src/OAuth2/Storage/Phalcon/Models/OauthClients.php @@ -41,25 +41,6 @@ class OauthClients extends \Phalcon\Mvc\Model */ public $user_id; - /** - * Initialize method for model. - */ - public function initialize() - { - $this->setSource("'oauth__clients'"); - $this->belongsTo('user_id', 'OAuth2\Storage\Models\OauthUsers', 'username', array("alias" => "User")); - } - - /** - * Returns table name mapped in the model. - * - * @return string - */ - public function getSource() - { - return 'oauth__clients'; - } - /** * Allows to query a set of records that match the specified conditions * @@ -82,11 +63,32 @@ public static function findFirst($parameters = null) return parent::findFirst($parameters); } + /** + * Initialize method for model. + */ + public function initialize() + { + $this->setSource("'oauth__clients'"); + $this->belongsTo('user_id', 'OAuth2\Storage\Models\OauthUsers', 'username', array("alias" => "User")); + } + + /** + * Returns table name mapped in the model. + * + * @return string + */ + public function getSource() + { + return 'oauth__clients'; + } + /** * @param mixed $parameters * @return OauthUsers */ - public function getUser($parameters = null){ + public function getUser($parameters = null) + { return $this->getRelated('User', $parameters); } -} + +} \ No newline at end of file diff --git a/src/OAuth2/Storage/Phalcon/Models/OauthJti.php b/src/OAuth2/Storage/Phalcon/Models/OauthJti.php index fcc61be2a..cbd5a1c90 100644 --- a/src/OAuth2/Storage/Phalcon/Models/OauthJti.php +++ b/src/OAuth2/Storage/Phalcon/Models/OauthJti.php @@ -67,4 +67,4 @@ public static function findFirst($parameters = null) return parent::findFirst($parameters); } -} +} \ No newline at end of file diff --git a/src/OAuth2/Storage/Phalcon/Models/OauthJwt.php b/src/OAuth2/Storage/Phalcon/Models/OauthJwt.php index 0bef0b976..06d731f81 100644 --- a/src/OAuth2/Storage/Phalcon/Models/OauthJwt.php +++ b/src/OAuth2/Storage/Phalcon/Models/OauthJwt.php @@ -68,4 +68,5 @@ public function getClient($parameters = null) { return $this->getRelated('Client', $parameters); } -} + +} \ No newline at end of file diff --git a/src/OAuth2/Storage/Phalcon/Models/OauthPublicKeys.php b/src/OAuth2/Storage/Phalcon/Models/OauthPublicKeys.php index bf0b7541e..06c41a0a1 100644 --- a/src/OAuth2/Storage/Phalcon/Models/OauthPublicKeys.php +++ b/src/OAuth2/Storage/Phalcon/Models/OauthPublicKeys.php @@ -74,4 +74,5 @@ public function getClient($parameters = null) { return $this->getRelated('Client', $parameters); } -} + +} \ No newline at end of file diff --git a/src/OAuth2/Storage/Phalcon/Models/OauthRefreshTokens.php b/src/OAuth2/Storage/Phalcon/Models/OauthRefreshTokens.php index cfbaf633a..0961eb7dc 100644 --- a/src/OAuth2/Storage/Phalcon/Models/OauthRefreshTokens.php +++ b/src/OAuth2/Storage/Phalcon/Models/OauthRefreshTokens.php @@ -76,4 +76,4 @@ public function getSource() return 'oauth__refresh_tokens'; } -} +} \ No newline at end of file diff --git a/src/OAuth2/Storage/Phalcon/Models/OauthScopes.php b/src/OAuth2/Storage/Phalcon/Models/OauthScopes.php index 6a142e31d..32187decb 100644 --- a/src/OAuth2/Storage/Phalcon/Models/OauthScopes.php +++ b/src/OAuth2/Storage/Phalcon/Models/OauthScopes.php @@ -49,4 +49,4 @@ public static function findFirst($parameters = null) return parent::findFirst($parameters); } -} +} \ No newline at end of file diff --git a/src/OAuth2/Storage/Phalcon/Models/OauthUsers.php b/src/OAuth2/Storage/Phalcon/Models/OauthUsers.php index 10b5e34ec..f1ac91c9e 100644 --- a/src/OAuth2/Storage/Phalcon/Models/OauthUsers.php +++ b/src/OAuth2/Storage/Phalcon/Models/OauthUsers.php @@ -132,4 +132,5 @@ public function getRefreshTokens($parameters = null) { return $this->getRelated('RefreshTokens', $parameters); } + } \ No newline at end of file diff --git a/src/OAuth2/Storage/Phalcon/Phalcon.php b/src/OAuth2/Storage/Phalcon/Phalcon.php index 29470a046..13ecf2391 100644 --- a/src/OAuth2/Storage/Phalcon/Phalcon.php +++ b/src/OAuth2/Storage/Phalcon/Phalcon.php @@ -57,11 +57,7 @@ public function __construct($di, $config = array()) ), $config); } - /** - * @param $client_id - * @param null $client_secret - * @return bool - */ + /* OAuth2\Storage\ClientCredentialsInterface */ public function checkClientCredentials($client_id, $client_secret = null) { $client = Models\OauthClients::findFirst( @@ -75,10 +71,6 @@ public function checkClientCredentials($client_id, $client_secret = null) return $client != false && $client->client_secret == $client_secret; } - /** - * @param $client_id - * @return bool - */ public function isPublicClient($client_id) { $clients = Models\OauthClients::findFirst( @@ -92,10 +84,6 @@ public function isPublicClient($client_id) return empty($clients->client_secret); } - /** - * @param $client_id - * @return array - */ public function getClientDetails($client_id) { $clients = Models\OauthClients::findFirst( @@ -109,15 +97,6 @@ public function getClientDetails($client_id) return $clients->toArray(); } - /** - * @param $client_id - * @param null $client_secret - * @param null $redirect_uri - * @param null $grant_types - * @param null $scope - * @param null $user_id - * @return mixed - */ public function setClientDetails($client_id, $client_secret = null, $redirect_uri = null, $grant_types = null, $scope = null, $user_id = null) { $client = new Models\OauthClients(); @@ -146,7 +125,6 @@ public function checkRestrictedGrantType($client_id, $grant_type) } /* OAuth2\Storage\AccessTokenInterface */ - public function getAccessToken($access_token) { $token = Models\OauthAccessTokens::findFirst( @@ -296,7 +274,7 @@ public function getUserDetails($username) return $this->getUser($username); } - /* UserClaimsInterface */ + /* OAuth2\Storage\UserClaimsInterface */ public function getUserClaims($user_id, $claims) { if (!$userDetails = $this->getUserDetails($user_id)) { @@ -335,6 +313,7 @@ protected function getUserClaim($claim, $userDetails) return $userClaims; } + /* OAuth2\Storage\RefreshTokenInterface */ public function getRefreshToken($refresh_token) { $token = Models\OauthRefreshTokens::findFirst( @@ -356,7 +335,6 @@ public function getRefreshToken($refresh_token) } // use a secure hashing algorithm when storing passwords. Override this for your application - public function setRefreshToken($refresh_token, $client_id, $user_id, $expires, $scope = null) { // convert expires to datestring @@ -387,6 +365,7 @@ public function unsetRefreshToken($refresh_token) return $token->delete(); } + /* OAuth2\Storage\UserCredentialsInterface */ protected function checkPassword($user, $password) { return $user['password'] == $this->hashPassword($password); @@ -437,6 +416,7 @@ public function setUser($username, $password, $firstName = null, $lastName = nul return $user->save(); } + /* OAuth2\Storage\ScopeInterface */ public function scopeExists($scope) { $scope = explode(' ', $scope); @@ -472,7 +452,7 @@ public function getDefaultScope($client_id = null) return null; } - /* JWTBearerInterface */ + /* OAuth2\Storage\JWTBearerInterface */ public function getClientKey($client_id, $subject) { @@ -538,7 +518,7 @@ public function setJti($client_id, $subject, $audience, $expires, $jti) return $jtiModel->save(); } - /* PublicKeyInterface */ + /* OAuth2\Storage\PublicKeyInterface */ public function getPublicKey($client_id = null) { $publicKey = Models\OauthPublicKeys::findFirst( @@ -588,7 +568,7 @@ public function getEncryptionAlgorithm($client_id = null) } /** - * DDL to create OAuth2 database and tables for PDO/Phalcon storage + * SQL to create OAuth2 tables for PDO/Phalcon storage * * @see https://github.com/dsquier/oauth2-server-php-mysql */ @@ -682,5 +662,4 @@ public function getBuildSql($dbName = 'oauth2_server_php') return $sql; } - -} +} \ No newline at end of file From a0a289eb868dde2c3d0dd20f939af0fce787bd88 Mon Sep 17 00:00:00 2001 From: Luca Santarella Date: Wed, 29 Jun 2016 22:12:24 -0400 Subject: [PATCH 05/19] Added PRIMARY KEY to the Build SQL --- src/OAuth2/Storage/Phalcon/Phalcon.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/OAuth2/Storage/Phalcon/Phalcon.php b/src/OAuth2/Storage/Phalcon/Phalcon.php index 13ecf2391..9124459cb 100644 --- a/src/OAuth2/Storage/Phalcon/Phalcon.php +++ b/src/OAuth2/Storage/Phalcon/Phalcon.php @@ -628,7 +628,8 @@ public function getBuildSql($dbName = 'oauth2_server_php') `last_name` varchar(80) DEFAULT NULL, `email` varchar(80) DEFAULT NULL, `email_verified` tinyint(1) DEFAULT NULL, - `scope` varchar(4000) DEFAULT NULL + `scope` varchar(4000) DEFAULT NULL, + PRIMARY KEY `id` ); CREATE TABLE {$this->config['scope_table']} ( From 2173560f1b152f73c70ba11bd7afe9ce47bcbd7d Mon Sep 17 00:00:00 2001 From: Luca Santarella Date: Wed, 29 Jun 2016 22:13:43 -0400 Subject: [PATCH 06/19] Fixed syntax error --- src/OAuth2/Storage/Phalcon/Phalcon.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/OAuth2/Storage/Phalcon/Phalcon.php b/src/OAuth2/Storage/Phalcon/Phalcon.php index 9124459cb..c9c401cb2 100644 --- a/src/OAuth2/Storage/Phalcon/Phalcon.php +++ b/src/OAuth2/Storage/Phalcon/Phalcon.php @@ -629,7 +629,7 @@ public function getBuildSql($dbName = 'oauth2_server_php') `email` varchar(80) DEFAULT NULL, `email_verified` tinyint(1) DEFAULT NULL, `scope` varchar(4000) DEFAULT NULL, - PRIMARY KEY `id` + PRIMARY KEY (`id`) ); CREATE TABLE {$this->config['scope_table']} ( From ced15f395d8fb3cd1f9fa0430526abb18a5d6add Mon Sep 17 00:00:00 2001 From: Luca Santarella Date: Wed, 29 Jun 2016 22:15:02 -0400 Subject: [PATCH 07/19] Reformatted for consistency --- src/OAuth2/Storage/Phalcon/Phalcon.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/OAuth2/Storage/Phalcon/Phalcon.php b/src/OAuth2/Storage/Phalcon/Phalcon.php index c9c401cb2..2a5141ef8 100644 --- a/src/OAuth2/Storage/Phalcon/Phalcon.php +++ b/src/OAuth2/Storage/Phalcon/Phalcon.php @@ -584,6 +584,7 @@ public function getBuildSql($dbName = 'oauth2_server_php') `user_id` varchar(80) DEFAULT NULL, PRIMARY KEY (client_id) ); + CREATE TABLE {$this->config['access_token_table']} ( `access_token` varchar(40) NOT NULL, `valid` tinyint(1) NOT NULL DEFAULT '1', @@ -629,7 +630,7 @@ public function getBuildSql($dbName = 'oauth2_server_php') `email` varchar(80) DEFAULT NULL, `email_verified` tinyint(1) DEFAULT NULL, `scope` varchar(4000) DEFAULT NULL, - PRIMARY KEY (`id`) + PRIMARY KEY (id) ); CREATE TABLE {$this->config['scope_table']} ( From 835b318c66e3d7465cf4f1dc9f6381717383ff3f Mon Sep 17 00:00:00 2001 From: Luca Santarella Date: Thu, 30 Jun 2016 09:46:44 -0400 Subject: [PATCH 08/19] Fixed namespace problem --- src/OAuth2/Storage/Phalcon/Models/OauthAccessTokens.php | 8 ++++---- src/OAuth2/Storage/Phalcon/Models/OauthClients.php | 2 +- src/OAuth2/Storage/Phalcon/Models/OauthJwt.php | 2 +- src/OAuth2/Storage/Phalcon/Models/OauthPublicKeys.php | 2 +- src/OAuth2/Storage/Phalcon/Models/OauthRefreshTokens.php | 4 ++-- src/OAuth2/Storage/Phalcon/Models/OauthUsers.php | 8 ++++---- 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/OAuth2/Storage/Phalcon/Models/OauthAccessTokens.php b/src/OAuth2/Storage/Phalcon/Models/OauthAccessTokens.php index 502af8106..f4c162a91 100644 --- a/src/OAuth2/Storage/Phalcon/Models/OauthAccessTokens.php +++ b/src/OAuth2/Storage/Phalcon/Models/OauthAccessTokens.php @@ -62,8 +62,8 @@ public static function findFirst($parameters = null) public function initialize() { $this->setSource("'oauth__access_tokens'"); - $this->belongsTo('user_id', 'OAuth2\Storage\Models\OauthUsers', 'username', array("alias" => "User")); - $this->belongsTo('client_id', 'OAuth2\Storage\Models\OauthClients', 'client_id', array("alias" => "Client")); + $this->belongsTo('user_id', 'OAuth2\Storage\Phalcon\Models\OauthUsers', 'username', array("alias" => "User")); + $this->belongsTo('client_id', 'OAuth2\Storage\Phalcon\Models\OauthClients', 'client_id', array("alias" => "Client")); } /** @@ -78,7 +78,7 @@ public function getSource() /** * @param mixed $parameters - * @return \OAuth2\Storage\Models\OauthUsers + * @return \OAuth2\Storage\Phalcon\Models\OauthUsers */ public function getUser($parameters = null) { @@ -87,7 +87,7 @@ public function getUser($parameters = null) /** * @param mixed $parameters - * @return \OAuth2\Storage\Models\OauthClients + * @return \OAuth2\Storage\Phalcon\Models\OauthClients */ public function getClient($parameters = null) { diff --git a/src/OAuth2/Storage/Phalcon/Models/OauthClients.php b/src/OAuth2/Storage/Phalcon/Models/OauthClients.php index 35c660202..a7a7c7b57 100644 --- a/src/OAuth2/Storage/Phalcon/Models/OauthClients.php +++ b/src/OAuth2/Storage/Phalcon/Models/OauthClients.php @@ -69,7 +69,7 @@ public static function findFirst($parameters = null) public function initialize() { $this->setSource("'oauth__clients'"); - $this->belongsTo('user_id', 'OAuth2\Storage\Models\OauthUsers', 'username', array("alias" => "User")); + $this->belongsTo('user_id', 'OAuth2\Storage\Phalcon\Models\OauthUsers', 'username', array("alias" => "User")); } /** diff --git a/src/OAuth2/Storage/Phalcon/Models/OauthJwt.php b/src/OAuth2/Storage/Phalcon/Models/OauthJwt.php index 06d731f81..bebd42691 100644 --- a/src/OAuth2/Storage/Phalcon/Models/OauthJwt.php +++ b/src/OAuth2/Storage/Phalcon/Models/OauthJwt.php @@ -51,7 +51,7 @@ public static function findFirst($parameters = null) public function initialize() { $this->setSource("'oauth__jwt'"); - $this->belongsTo('client_id', 'OAuth2\Storage\Models\OauthClients', 'client_id', array("alias" => "Client")); + $this->belongsTo('client_id', 'OAuth2\Storage\Phalcon\Models\OauthClients', 'client_id', array("alias" => "Client")); } /** diff --git a/src/OAuth2/Storage/Phalcon/Models/OauthPublicKeys.php b/src/OAuth2/Storage/Phalcon/Models/OauthPublicKeys.php index 06c41a0a1..f954dd3da 100644 --- a/src/OAuth2/Storage/Phalcon/Models/OauthPublicKeys.php +++ b/src/OAuth2/Storage/Phalcon/Models/OauthPublicKeys.php @@ -57,7 +57,7 @@ public static function findFirst($parameters = null) public function initialize() { $this->setSource("'oauth__public_keys'"); - $this->belongsTo('client_id', 'OAuth2\Storage\Models\OauthClients', 'client_id', array("alias" => "Client")); + $this->belongsTo('client_id', 'OAuth2\Storage\Phalcon\Models\OauthClients', 'client_id', array("alias" => "Client")); } /** diff --git a/src/OAuth2/Storage/Phalcon/Models/OauthRefreshTokens.php b/src/OAuth2/Storage/Phalcon/Models/OauthRefreshTokens.php index 0961eb7dc..c3046f6e8 100644 --- a/src/OAuth2/Storage/Phalcon/Models/OauthRefreshTokens.php +++ b/src/OAuth2/Storage/Phalcon/Models/OauthRefreshTokens.php @@ -62,8 +62,8 @@ public static function findFirst($parameters = null) public function initialize() { $this->setSource("'oauth__refresh_tokens'"); - $this->belongsTo('user_id', 'OAuth2\Storage\Models\OauthUsers', 'username'); - $this->belongsTo('client_id', 'OAuth2\Storage\Models\OauthClients', 'client_id'); + $this->belongsTo('user_id', 'OAuth2\Storage\Phalcon\Models\OauthUsers', 'username'); + $this->belongsTo('client_id', 'OAuth2\Storage\Phalcon\Models\OauthClients', 'client_id'); } /** diff --git a/src/OAuth2/Storage/Phalcon/Models/OauthUsers.php b/src/OAuth2/Storage/Phalcon/Models/OauthUsers.php index f1ac91c9e..f3846ad86 100644 --- a/src/OAuth2/Storage/Phalcon/Models/OauthUsers.php +++ b/src/OAuth2/Storage/Phalcon/Models/OauthUsers.php @@ -78,8 +78,8 @@ public function initialize() { $this->keepSnapshots(true); $this->setSource("'oauth__users'"); - $this->hasMany('username', 'OAuth2\Storage\Models\OauthAccessTokens', 'user_id', array("alias" => "AccessTokens")); - $this->hasMany('username', 'OAuth2\Storage\Models\OauthRefreshTokens', 'user_id', array("alias" => "RefreshTokens")); + $this->hasMany('username', 'OAuth2\Storage\Phalcon\Models\OauthAccessTokens', 'user_id', array("alias" => "AccessTokens")); + $this->hasMany('username', 'OAuth2\Storage\Phalcon\Models\OauthRefreshTokens', 'user_id', array("alias" => "RefreshTokens")); } /** @@ -117,7 +117,7 @@ public function getSource() /** * @param mixed $parameters - * @return \OAuth2\Storage\Models\OauthAccessTokens[] + * @return \OAuth2\Storage\Phalcon\Models\OauthAccessTokens[] */ public function getAccessTokens($parameters = null) { @@ -126,7 +126,7 @@ public function getAccessTokens($parameters = null) /** * @param mixed $parameters - * @return \OAuth2\Storage\Models\OauthRefreshTokens[] + * @return \OAuth2\Storage\Phalcon\Models\OauthRefreshTokens[] */ public function getRefreshTokens($parameters = null) { From cf3a1577def5f2515cf4ddfd76df263633ad7518 Mon Sep 17 00:00:00 2001 From: Luca Santarella Date: Fri, 1 Jul 2016 14:12:20 -0400 Subject: [PATCH 09/19] Changed table names to conform to the PDO class table names --- src/OAuth2/Storage/Phalcon/Phalcon.php | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/OAuth2/Storage/Phalcon/Phalcon.php b/src/OAuth2/Storage/Phalcon/Phalcon.php index 2a5141ef8..0b449be10 100644 --- a/src/OAuth2/Storage/Phalcon/Phalcon.php +++ b/src/OAuth2/Storage/Phalcon/Phalcon.php @@ -45,15 +45,15 @@ public function __construct($di, $config = array()) { $this->di = $di; $this->config = array_merge(array( - 'client_table' => 'oauth__clients', - 'access_token_table' => 'oauth__access_tokens', - 'refresh_token_table' => 'oauth__refresh_tokens', - 'code_table' => 'oauth__authorization_codes', - 'user_table' => 'oauth__users', - 'jwt_table' => 'oauth__jwt', - 'jti_table' => 'oauth__jti', - 'scope_table' => 'oauth__scopes', - 'public_key_table' => 'oauth__public_keys', + 'client_table' => 'oauth_clients', + 'access_token_table' => 'oauth_access_tokens', + 'refresh_token_table' => 'oauth_refresh_tokens', + 'code_table' => 'oauth_authorization_codes', + 'user_table' => 'oauth_users', + 'jwt_table' => 'oauth_jwt', + 'jti_table' => 'oauth_jti', + 'scope_table' => 'oauth_scopes', + 'public_key_table' => 'oauth_public_keys', ), $config); } From 4d77748c185cf0b6c2ee667a3d607302b81eae72 Mon Sep 17 00:00:00 2001 From: Luca Santarella Date: Fri, 1 Jul 2016 14:12:49 -0400 Subject: [PATCH 10/19] Added base Phalcon test --- test/OAuth2/Storage/PhalconTest.php | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 test/OAuth2/Storage/PhalconTest.php diff --git a/test/OAuth2/Storage/PhalconTest.php b/test/OAuth2/Storage/PhalconTest.php new file mode 100644 index 000000000..5ee4c29ae --- /dev/null +++ b/test/OAuth2/Storage/PhalconTest.php @@ -0,0 +1,15 @@ + Date: Fri, 1 Jul 2016 17:52:03 -0400 Subject: [PATCH 11/19] Phalcon travis ci config (#1) * Added Travis CI installer for Phalcon * Travis CI config for phalcon * Refactored to the corresponding directory for the Phalcon classes * Added phalcon autoload tests * Test test * Get client details test * Init DB for phalcon test * Refactored di connection * More tests * Disabled throwing an exception * Setup methods * Fixed table names * Finalize tests --- .travis.yml | 8 +- composer.json | 3 +- .../Phalcon/Models/OauthAccessTokens.php | 4 +- .../Models/OauthAuthorizationCodes.php | 2 +- .../Storage/Phalcon/Models/OauthClients.php | 4 +- .../Storage/Phalcon/Models/OauthJti.php | 2 +- .../Storage/Phalcon/Models/OauthJwt.php | 4 +- .../Phalcon/Models/OauthPublicKeys.php | 4 +- .../Phalcon/Models/OauthRefreshTokens.php | 4 +- .../Storage/Phalcon/Models/OauthScopes.php | 2 +- .../Storage/Phalcon/Models/OauthUsers.php | 4 +- src/OAuth2/Storage/Phalcon/Phalcon.php | 3 + test/OAuth2/AutoloadTest.php | 2 + test/OAuth2/Storage/Phalcon/PhalconTest.php | 101 ++++++++++++++++++ test/OAuth2/Storage/PhalconTest.php | 15 --- 15 files changed, 130 insertions(+), 32 deletions(-) create mode 100644 test/OAuth2/Storage/Phalcon/PhalconTest.php delete mode 100644 test/OAuth2/Storage/PhalconTest.php diff --git a/.travis.yml b/.travis.yml index dd4aae4a6..f80b7928f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,6 +4,7 @@ cache: directories: - $HOME/.composer/cache - vendor + - $HOME/cphalcon php: - 5.3 - 5.4 @@ -20,11 +21,16 @@ services: - mongodb - redis-server - cassandra +- mysql +- memcached before_install: -- phpenv config-rm xdebug.ini || return 0 + - composer install --prefer-source --no-interaction + - vendor/bin/install-phalcon.sh + - phpenv config-rm xdebug.ini || return 0 install: - composer install --no-interaction before_script: +- php -m - psql -c 'create database oauth2_server_php;' -U postgres after_script: - php test/cleanup.php diff --git a/composer.json b/composer.json index b1f28c707..5b8f3ced2 100644 --- a/composer.json +++ b/composer.json @@ -28,6 +28,7 @@ "aws/aws-sdk-php": "~2.8", "firebase/php-jwt": "~2.2", "predis/predis": "dev-master", - "thobbs/phpcassa": "dev-master" + "thobbs/phpcassa": "dev-master", + "techpivot/phalcon-ci-installer": "~1.0" } } diff --git a/src/OAuth2/Storage/Phalcon/Models/OauthAccessTokens.php b/src/OAuth2/Storage/Phalcon/Models/OauthAccessTokens.php index f4c162a91..03162a24e 100644 --- a/src/OAuth2/Storage/Phalcon/Models/OauthAccessTokens.php +++ b/src/OAuth2/Storage/Phalcon/Models/OauthAccessTokens.php @@ -61,7 +61,7 @@ public static function findFirst($parameters = null) */ public function initialize() { - $this->setSource("'oauth__access_tokens'"); + $this->setSource("'oauth_access_tokens'"); $this->belongsTo('user_id', 'OAuth2\Storage\Phalcon\Models\OauthUsers', 'username', array("alias" => "User")); $this->belongsTo('client_id', 'OAuth2\Storage\Phalcon\Models\OauthClients', 'client_id', array("alias" => "Client")); } @@ -73,7 +73,7 @@ public function initialize() */ public function getSource() { - return 'oauth__access_tokens'; + return 'oauth_access_tokens'; } /** diff --git a/src/OAuth2/Storage/Phalcon/Models/OauthAuthorizationCodes.php b/src/OAuth2/Storage/Phalcon/Models/OauthAuthorizationCodes.php index 1d7e5001e..da4c1903e 100644 --- a/src/OAuth2/Storage/Phalcon/Models/OauthAuthorizationCodes.php +++ b/src/OAuth2/Storage/Phalcon/Models/OauthAuthorizationCodes.php @@ -54,7 +54,7 @@ class OauthAuthorizationCodes extends \Phalcon\Mvc\Model */ public function getSource() { - return 'oauth__authorization_codes'; + return 'oauth_authorization_codes'; } /** diff --git a/src/OAuth2/Storage/Phalcon/Models/OauthClients.php b/src/OAuth2/Storage/Phalcon/Models/OauthClients.php index a7a7c7b57..3e81b1dc6 100644 --- a/src/OAuth2/Storage/Phalcon/Models/OauthClients.php +++ b/src/OAuth2/Storage/Phalcon/Models/OauthClients.php @@ -68,7 +68,7 @@ public static function findFirst($parameters = null) */ public function initialize() { - $this->setSource("'oauth__clients'"); + $this->setSource("'oauth_clients'"); $this->belongsTo('user_id', 'OAuth2\Storage\Phalcon\Models\OauthUsers', 'username', array("alias" => "User")); } @@ -79,7 +79,7 @@ public function initialize() */ public function getSource() { - return 'oauth__clients'; + return 'oauth_clients'; } /** diff --git a/src/OAuth2/Storage/Phalcon/Models/OauthJti.php b/src/OAuth2/Storage/Phalcon/Models/OauthJti.php index cbd5a1c90..9c3378710 100644 --- a/src/OAuth2/Storage/Phalcon/Models/OauthJti.php +++ b/src/OAuth2/Storage/Phalcon/Models/OauthJti.php @@ -42,7 +42,7 @@ class OauthJti extends \Phalcon\Mvc\Model */ public function getSource() { - return 'oauth__jti'; + return 'oauth_jti'; } /** diff --git a/src/OAuth2/Storage/Phalcon/Models/OauthJwt.php b/src/OAuth2/Storage/Phalcon/Models/OauthJwt.php index bebd42691..9c85795af 100644 --- a/src/OAuth2/Storage/Phalcon/Models/OauthJwt.php +++ b/src/OAuth2/Storage/Phalcon/Models/OauthJwt.php @@ -50,7 +50,7 @@ public static function findFirst($parameters = null) */ public function initialize() { - $this->setSource("'oauth__jwt'"); + $this->setSource("'oauth_jwt'"); $this->belongsTo('client_id', 'OAuth2\Storage\Phalcon\Models\OauthClients', 'client_id', array("alias" => "Client")); } @@ -61,7 +61,7 @@ public function initialize() */ public function getSource() { - return 'oauth__jwt'; + return 'oauth_jwt'; } public function getClient($parameters = null) diff --git a/src/OAuth2/Storage/Phalcon/Models/OauthPublicKeys.php b/src/OAuth2/Storage/Phalcon/Models/OauthPublicKeys.php index f954dd3da..95e4361c7 100644 --- a/src/OAuth2/Storage/Phalcon/Models/OauthPublicKeys.php +++ b/src/OAuth2/Storage/Phalcon/Models/OauthPublicKeys.php @@ -56,7 +56,7 @@ public static function findFirst($parameters = null) */ public function initialize() { - $this->setSource("'oauth__public_keys'"); + $this->setSource("'oauth_public_keys'"); $this->belongsTo('client_id', 'OAuth2\Storage\Phalcon\Models\OauthClients', 'client_id', array("alias" => "Client")); } @@ -67,7 +67,7 @@ public function initialize() */ public function getSource() { - return 'oauth__public_keys'; + return 'oauth_public_keys'; } public function getClient($parameters = null) diff --git a/src/OAuth2/Storage/Phalcon/Models/OauthRefreshTokens.php b/src/OAuth2/Storage/Phalcon/Models/OauthRefreshTokens.php index c3046f6e8..ef201b5b5 100644 --- a/src/OAuth2/Storage/Phalcon/Models/OauthRefreshTokens.php +++ b/src/OAuth2/Storage/Phalcon/Models/OauthRefreshTokens.php @@ -61,7 +61,7 @@ public static function findFirst($parameters = null) */ public function initialize() { - $this->setSource("'oauth__refresh_tokens'"); + $this->setSource("'oauth_refresh_tokens'"); $this->belongsTo('user_id', 'OAuth2\Storage\Phalcon\Models\OauthUsers', 'username'); $this->belongsTo('client_id', 'OAuth2\Storage\Phalcon\Models\OauthClients', 'client_id'); } @@ -73,7 +73,7 @@ public function initialize() */ public function getSource() { - return 'oauth__refresh_tokens'; + return 'oauth_refresh_tokens'; } } \ No newline at end of file diff --git a/src/OAuth2/Storage/Phalcon/Models/OauthScopes.php b/src/OAuth2/Storage/Phalcon/Models/OauthScopes.php index 32187decb..721766596 100644 --- a/src/OAuth2/Storage/Phalcon/Models/OauthScopes.php +++ b/src/OAuth2/Storage/Phalcon/Models/OauthScopes.php @@ -24,7 +24,7 @@ class OauthScopes extends \Phalcon\Mvc\Model */ public function getSource() { - return 'oauth__scopes'; + return 'oauth_scopes'; } /** diff --git a/src/OAuth2/Storage/Phalcon/Models/OauthUsers.php b/src/OAuth2/Storage/Phalcon/Models/OauthUsers.php index f3846ad86..aed45d13b 100644 --- a/src/OAuth2/Storage/Phalcon/Models/OauthUsers.php +++ b/src/OAuth2/Storage/Phalcon/Models/OauthUsers.php @@ -77,7 +77,7 @@ public static function findFirst($parameters = null) public function initialize() { $this->keepSnapshots(true); - $this->setSource("'oauth__users'"); + $this->setSource("'oauth_users'"); $this->hasMany('username', 'OAuth2\Storage\Phalcon\Models\OauthAccessTokens', 'user_id', array("alias" => "AccessTokens")); $this->hasMany('username', 'OAuth2\Storage\Phalcon\Models\OauthRefreshTokens', 'user_id', array("alias" => "RefreshTokens")); } @@ -112,7 +112,7 @@ public function validation() */ public function getSource() { - return 'oauth__users'; + return 'oauth_users'; } /** diff --git a/src/OAuth2/Storage/Phalcon/Phalcon.php b/src/OAuth2/Storage/Phalcon/Phalcon.php index 0b449be10..6436293ba 100644 --- a/src/OAuth2/Storage/Phalcon/Phalcon.php +++ b/src/OAuth2/Storage/Phalcon/Phalcon.php @@ -43,6 +43,9 @@ class Phalcon implements */ public function __construct($di, $config = array()) { + if(!isset($di['db'])) + throw new \InvalidArgumentException('Dependency injector must contain a valid database connection'); + $this->di = $di; $this->config = array_merge(array( 'client_table' => 'oauth_clients', diff --git a/test/OAuth2/AutoloadTest.php b/test/OAuth2/AutoloadTest.php index 5901bdc42..baba16b8d 100644 --- a/test/OAuth2/AutoloadTest.php +++ b/test/OAuth2/AutoloadTest.php @@ -12,5 +12,7 @@ public function testClassesExist() $this->assertTrue(class_exists('OAuth2\Response')); $this->assertTrue(class_exists('OAuth2\GrantType\UserCredentials')); $this->assertTrue(interface_exists('OAuth2\Storage\AccessTokenInterface')); + $this->assertTrue(class_exists('OAuth2\Storage\Phalcon\Phalcon')); + $this->assertTrue(class_exists('OAuth2\Storage\Phalcon\Models\OauthUsers')); } } diff --git a/test/OAuth2/Storage/Phalcon/PhalconTest.php b/test/OAuth2/Storage/Phalcon/PhalconTest.php new file mode 100644 index 000000000..a12237652 --- /dev/null +++ b/test/OAuth2/Storage/Phalcon/PhalconTest.php @@ -0,0 +1,101 @@ +checkExtension('phalcon'); + // Reset the DI container + Di::reset(); + // Instantiate a new DI container + $di = new Di(); + // Set the URL + $di->set( + 'url', + function () { + $url = new Url(); + $url->setBaseUri('/'); + return $url; + } + ); + + $di->set( + 'escaper', + function () { + return new Escaper(); + } + ); + + $di->set('db', function() { + return new Mysql(array( + "host" => "localhost", + "username" => "root", + "password" => "", + "dbname" => "oauth2_server_php", + )); + }); + + $di->set( + 'modelsManager', + function () { + return new Manager(); + } + ); + + $di->set( + 'modelsMetadata', + function () { + return new Memory(); + } + ); + + $this->di = $di; + } + + public function checkExtension($extension) + { + $message = function ($ext) { + sprintf('Warning: %s extension is not loaded', $ext); + }; + if (is_array($extension)) { + foreach ($extension as $ext) { + if (!extension_loaded($ext)) { + $this->markTestSkipped($message($ext)); + break; + } + } + } elseif (!extension_loaded($extension)) { + $this->markTestSkipped($message($extension)); + } + } + + public function testPhalconDataStorage(){ + $this->setUp(); + $storage = new Phalcon($this->di); + $this->assertNotNull($storage->getClientDetails('oauth_test_client')); + } + +} \ No newline at end of file diff --git a/test/OAuth2/Storage/PhalconTest.php b/test/OAuth2/Storage/PhalconTest.php deleted file mode 100644 index 5ee4c29ae..000000000 --- a/test/OAuth2/Storage/PhalconTest.php +++ /dev/null @@ -1,15 +0,0 @@ - Date: Tue, 5 Jul 2016 12:23:20 -0400 Subject: [PATCH 12/19] Revert "Phalcon travis ci config (#1)" This reverts commit f18eb4752641a8ed219fbac04098296db12528b5. --- .travis.yml | 8 +- composer.json | 3 +- .../Phalcon/Models/OauthAccessTokens.php | 4 +- .../Models/OauthAuthorizationCodes.php | 2 +- .../Storage/Phalcon/Models/OauthClients.php | 4 +- .../Storage/Phalcon/Models/OauthJti.php | 2 +- .../Storage/Phalcon/Models/OauthJwt.php | 4 +- .../Phalcon/Models/OauthPublicKeys.php | 4 +- .../Phalcon/Models/OauthRefreshTokens.php | 4 +- .../Storage/Phalcon/Models/OauthScopes.php | 2 +- .../Storage/Phalcon/Models/OauthUsers.php | 4 +- src/OAuth2/Storage/Phalcon/Phalcon.php | 3 - test/OAuth2/AutoloadTest.php | 2 - test/OAuth2/Storage/Phalcon/PhalconTest.php | 101 ------------------ test/OAuth2/Storage/PhalconTest.php | 15 +++ 15 files changed, 32 insertions(+), 130 deletions(-) delete mode 100644 test/OAuth2/Storage/Phalcon/PhalconTest.php create mode 100644 test/OAuth2/Storage/PhalconTest.php diff --git a/.travis.yml b/.travis.yml index f80b7928f..dd4aae4a6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,7 +4,6 @@ cache: directories: - $HOME/.composer/cache - vendor - - $HOME/cphalcon php: - 5.3 - 5.4 @@ -21,16 +20,11 @@ services: - mongodb - redis-server - cassandra -- mysql -- memcached before_install: - - composer install --prefer-source --no-interaction - - vendor/bin/install-phalcon.sh - - phpenv config-rm xdebug.ini || return 0 +- phpenv config-rm xdebug.ini || return 0 install: - composer install --no-interaction before_script: -- php -m - psql -c 'create database oauth2_server_php;' -U postgres after_script: - php test/cleanup.php diff --git a/composer.json b/composer.json index 5b8f3ced2..b1f28c707 100644 --- a/composer.json +++ b/composer.json @@ -28,7 +28,6 @@ "aws/aws-sdk-php": "~2.8", "firebase/php-jwt": "~2.2", "predis/predis": "dev-master", - "thobbs/phpcassa": "dev-master", - "techpivot/phalcon-ci-installer": "~1.0" + "thobbs/phpcassa": "dev-master" } } diff --git a/src/OAuth2/Storage/Phalcon/Models/OauthAccessTokens.php b/src/OAuth2/Storage/Phalcon/Models/OauthAccessTokens.php index 03162a24e..f4c162a91 100644 --- a/src/OAuth2/Storage/Phalcon/Models/OauthAccessTokens.php +++ b/src/OAuth2/Storage/Phalcon/Models/OauthAccessTokens.php @@ -61,7 +61,7 @@ public static function findFirst($parameters = null) */ public function initialize() { - $this->setSource("'oauth_access_tokens'"); + $this->setSource("'oauth__access_tokens'"); $this->belongsTo('user_id', 'OAuth2\Storage\Phalcon\Models\OauthUsers', 'username', array("alias" => "User")); $this->belongsTo('client_id', 'OAuth2\Storage\Phalcon\Models\OauthClients', 'client_id', array("alias" => "Client")); } @@ -73,7 +73,7 @@ public function initialize() */ public function getSource() { - return 'oauth_access_tokens'; + return 'oauth__access_tokens'; } /** diff --git a/src/OAuth2/Storage/Phalcon/Models/OauthAuthorizationCodes.php b/src/OAuth2/Storage/Phalcon/Models/OauthAuthorizationCodes.php index da4c1903e..1d7e5001e 100644 --- a/src/OAuth2/Storage/Phalcon/Models/OauthAuthorizationCodes.php +++ b/src/OAuth2/Storage/Phalcon/Models/OauthAuthorizationCodes.php @@ -54,7 +54,7 @@ class OauthAuthorizationCodes extends \Phalcon\Mvc\Model */ public function getSource() { - return 'oauth_authorization_codes'; + return 'oauth__authorization_codes'; } /** diff --git a/src/OAuth2/Storage/Phalcon/Models/OauthClients.php b/src/OAuth2/Storage/Phalcon/Models/OauthClients.php index 3e81b1dc6..a7a7c7b57 100644 --- a/src/OAuth2/Storage/Phalcon/Models/OauthClients.php +++ b/src/OAuth2/Storage/Phalcon/Models/OauthClients.php @@ -68,7 +68,7 @@ public static function findFirst($parameters = null) */ public function initialize() { - $this->setSource("'oauth_clients'"); + $this->setSource("'oauth__clients'"); $this->belongsTo('user_id', 'OAuth2\Storage\Phalcon\Models\OauthUsers', 'username', array("alias" => "User")); } @@ -79,7 +79,7 @@ public function initialize() */ public function getSource() { - return 'oauth_clients'; + return 'oauth__clients'; } /** diff --git a/src/OAuth2/Storage/Phalcon/Models/OauthJti.php b/src/OAuth2/Storage/Phalcon/Models/OauthJti.php index 9c3378710..cbd5a1c90 100644 --- a/src/OAuth2/Storage/Phalcon/Models/OauthJti.php +++ b/src/OAuth2/Storage/Phalcon/Models/OauthJti.php @@ -42,7 +42,7 @@ class OauthJti extends \Phalcon\Mvc\Model */ public function getSource() { - return 'oauth_jti'; + return 'oauth__jti'; } /** diff --git a/src/OAuth2/Storage/Phalcon/Models/OauthJwt.php b/src/OAuth2/Storage/Phalcon/Models/OauthJwt.php index 9c85795af..bebd42691 100644 --- a/src/OAuth2/Storage/Phalcon/Models/OauthJwt.php +++ b/src/OAuth2/Storage/Phalcon/Models/OauthJwt.php @@ -50,7 +50,7 @@ public static function findFirst($parameters = null) */ public function initialize() { - $this->setSource("'oauth_jwt'"); + $this->setSource("'oauth__jwt'"); $this->belongsTo('client_id', 'OAuth2\Storage\Phalcon\Models\OauthClients', 'client_id', array("alias" => "Client")); } @@ -61,7 +61,7 @@ public function initialize() */ public function getSource() { - return 'oauth_jwt'; + return 'oauth__jwt'; } public function getClient($parameters = null) diff --git a/src/OAuth2/Storage/Phalcon/Models/OauthPublicKeys.php b/src/OAuth2/Storage/Phalcon/Models/OauthPublicKeys.php index 95e4361c7..f954dd3da 100644 --- a/src/OAuth2/Storage/Phalcon/Models/OauthPublicKeys.php +++ b/src/OAuth2/Storage/Phalcon/Models/OauthPublicKeys.php @@ -56,7 +56,7 @@ public static function findFirst($parameters = null) */ public function initialize() { - $this->setSource("'oauth_public_keys'"); + $this->setSource("'oauth__public_keys'"); $this->belongsTo('client_id', 'OAuth2\Storage\Phalcon\Models\OauthClients', 'client_id', array("alias" => "Client")); } @@ -67,7 +67,7 @@ public function initialize() */ public function getSource() { - return 'oauth_public_keys'; + return 'oauth__public_keys'; } public function getClient($parameters = null) diff --git a/src/OAuth2/Storage/Phalcon/Models/OauthRefreshTokens.php b/src/OAuth2/Storage/Phalcon/Models/OauthRefreshTokens.php index ef201b5b5..c3046f6e8 100644 --- a/src/OAuth2/Storage/Phalcon/Models/OauthRefreshTokens.php +++ b/src/OAuth2/Storage/Phalcon/Models/OauthRefreshTokens.php @@ -61,7 +61,7 @@ public static function findFirst($parameters = null) */ public function initialize() { - $this->setSource("'oauth_refresh_tokens'"); + $this->setSource("'oauth__refresh_tokens'"); $this->belongsTo('user_id', 'OAuth2\Storage\Phalcon\Models\OauthUsers', 'username'); $this->belongsTo('client_id', 'OAuth2\Storage\Phalcon\Models\OauthClients', 'client_id'); } @@ -73,7 +73,7 @@ public function initialize() */ public function getSource() { - return 'oauth_refresh_tokens'; + return 'oauth__refresh_tokens'; } } \ No newline at end of file diff --git a/src/OAuth2/Storage/Phalcon/Models/OauthScopes.php b/src/OAuth2/Storage/Phalcon/Models/OauthScopes.php index 721766596..32187decb 100644 --- a/src/OAuth2/Storage/Phalcon/Models/OauthScopes.php +++ b/src/OAuth2/Storage/Phalcon/Models/OauthScopes.php @@ -24,7 +24,7 @@ class OauthScopes extends \Phalcon\Mvc\Model */ public function getSource() { - return 'oauth_scopes'; + return 'oauth__scopes'; } /** diff --git a/src/OAuth2/Storage/Phalcon/Models/OauthUsers.php b/src/OAuth2/Storage/Phalcon/Models/OauthUsers.php index aed45d13b..f3846ad86 100644 --- a/src/OAuth2/Storage/Phalcon/Models/OauthUsers.php +++ b/src/OAuth2/Storage/Phalcon/Models/OauthUsers.php @@ -77,7 +77,7 @@ public static function findFirst($parameters = null) public function initialize() { $this->keepSnapshots(true); - $this->setSource("'oauth_users'"); + $this->setSource("'oauth__users'"); $this->hasMany('username', 'OAuth2\Storage\Phalcon\Models\OauthAccessTokens', 'user_id', array("alias" => "AccessTokens")); $this->hasMany('username', 'OAuth2\Storage\Phalcon\Models\OauthRefreshTokens', 'user_id', array("alias" => "RefreshTokens")); } @@ -112,7 +112,7 @@ public function validation() */ public function getSource() { - return 'oauth_users'; + return 'oauth__users'; } /** diff --git a/src/OAuth2/Storage/Phalcon/Phalcon.php b/src/OAuth2/Storage/Phalcon/Phalcon.php index 6436293ba..0b449be10 100644 --- a/src/OAuth2/Storage/Phalcon/Phalcon.php +++ b/src/OAuth2/Storage/Phalcon/Phalcon.php @@ -43,9 +43,6 @@ class Phalcon implements */ public function __construct($di, $config = array()) { - if(!isset($di['db'])) - throw new \InvalidArgumentException('Dependency injector must contain a valid database connection'); - $this->di = $di; $this->config = array_merge(array( 'client_table' => 'oauth_clients', diff --git a/test/OAuth2/AutoloadTest.php b/test/OAuth2/AutoloadTest.php index baba16b8d..5901bdc42 100644 --- a/test/OAuth2/AutoloadTest.php +++ b/test/OAuth2/AutoloadTest.php @@ -12,7 +12,5 @@ public function testClassesExist() $this->assertTrue(class_exists('OAuth2\Response')); $this->assertTrue(class_exists('OAuth2\GrantType\UserCredentials')); $this->assertTrue(interface_exists('OAuth2\Storage\AccessTokenInterface')); - $this->assertTrue(class_exists('OAuth2\Storage\Phalcon\Phalcon')); - $this->assertTrue(class_exists('OAuth2\Storage\Phalcon\Models\OauthUsers')); } } diff --git a/test/OAuth2/Storage/Phalcon/PhalconTest.php b/test/OAuth2/Storage/Phalcon/PhalconTest.php deleted file mode 100644 index a12237652..000000000 --- a/test/OAuth2/Storage/Phalcon/PhalconTest.php +++ /dev/null @@ -1,101 +0,0 @@ -checkExtension('phalcon'); - // Reset the DI container - Di::reset(); - // Instantiate a new DI container - $di = new Di(); - // Set the URL - $di->set( - 'url', - function () { - $url = new Url(); - $url->setBaseUri('/'); - return $url; - } - ); - - $di->set( - 'escaper', - function () { - return new Escaper(); - } - ); - - $di->set('db', function() { - return new Mysql(array( - "host" => "localhost", - "username" => "root", - "password" => "", - "dbname" => "oauth2_server_php", - )); - }); - - $di->set( - 'modelsManager', - function () { - return new Manager(); - } - ); - - $di->set( - 'modelsMetadata', - function () { - return new Memory(); - } - ); - - $this->di = $di; - } - - public function checkExtension($extension) - { - $message = function ($ext) { - sprintf('Warning: %s extension is not loaded', $ext); - }; - if (is_array($extension)) { - foreach ($extension as $ext) { - if (!extension_loaded($ext)) { - $this->markTestSkipped($message($ext)); - break; - } - } - } elseif (!extension_loaded($extension)) { - $this->markTestSkipped($message($extension)); - } - } - - public function testPhalconDataStorage(){ - $this->setUp(); - $storage = new Phalcon($this->di); - $this->assertNotNull($storage->getClientDetails('oauth_test_client')); - } - -} \ No newline at end of file diff --git a/test/OAuth2/Storage/PhalconTest.php b/test/OAuth2/Storage/PhalconTest.php new file mode 100644 index 000000000..5ee4c29ae --- /dev/null +++ b/test/OAuth2/Storage/PhalconTest.php @@ -0,0 +1,15 @@ + Date: Tue, 5 Jul 2016 12:23:45 -0400 Subject: [PATCH 13/19] Phalcon travis ci config (#2) * Added Travis CI installer for Phalcon * Travis CI config for phalcon * Refactored to the corresponding directory for the Phalcon classes * Added phalcon autoload tests * Test test * Get client details test * Init DB for phalcon test * Refactored di connection * More tests * Disabled throwing an exception * Setup methods * Fixed table names * Finalize tests * Min php version set to 5.3.21 * Removed manually setting the phalcon version * Php 5.3.29 for Phalcon Zephir * Added dev packages * using sudo * Installing 2.0.x of phalcon * Removed PHP7 and HHVM from config * Using dynamic table names for the library * Using getShared instead of getRaw * Fixed recursion depth * Using get instead of getShared * Using function * Using special config class * Added special phalcon conf class * Using containerbased infrastructure * Fixed not sending the class in the di * Moved the conf class back to the Phalcon main class --- .travis.yml | 10 +- composer.json | 3 +- .../Phalcon/Models/OauthAccessTokens.php | 6 +- .../Models/OauthAuthorizationCodes.php | 4 +- .../Storage/Phalcon/Models/OauthClients.php | 6 +- .../Storage/Phalcon/Models/OauthJti.php | 4 +- .../Storage/Phalcon/Models/OauthJwt.php | 8 +- .../Phalcon/Models/OauthPublicKeys.php | 7 +- .../Phalcon/Models/OauthRefreshTokens.php | 7 +- .../Storage/Phalcon/Models/OauthScopes.php | 4 +- .../Storage/Phalcon/Models/OauthUsers.php | 7 +- src/OAuth2/Storage/Phalcon/Phalcon.php | 245 +++++++++++++++++- test/OAuth2/AutoloadTest.php | 2 + test/OAuth2/Storage/Phalcon/PhalconTest.php | 99 +++++++ test/OAuth2/Storage/PhalconTest.php | 15 -- 15 files changed, 378 insertions(+), 49 deletions(-) create mode 100644 test/OAuth2/Storage/Phalcon/PhalconTest.php delete mode 100644 test/OAuth2/Storage/PhalconTest.php diff --git a/.travis.yml b/.travis.yml index dd4aae4a6..1d463fe44 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,13 +4,12 @@ cache: directories: - $HOME/.composer/cache - vendor + - $HOME/cphalcon php: - 5.3 - 5.4 - 5.5 - 5.6 -- 7 -- hhvm env: global: - SKIP_MONGO_TESTS=1 @@ -20,11 +19,16 @@ services: - mongodb - redis-server - cassandra +- mysql +- memcached before_install: -- phpenv config-rm xdebug.ini || return 0 + - composer install --prefer-source --no-interaction + - vendor/bin/install-phalcon.sh 2.0.x + - phpenv config-rm xdebug.ini || return 0 install: - composer install --no-interaction before_script: +- php -m - psql -c 'create database oauth2_server_php;' -U postgres after_script: - php test/cleanup.php diff --git a/composer.json b/composer.json index b1f28c707..5b8f3ced2 100644 --- a/composer.json +++ b/composer.json @@ -28,6 +28,7 @@ "aws/aws-sdk-php": "~2.8", "firebase/php-jwt": "~2.2", "predis/predis": "dev-master", - "thobbs/phpcassa": "dev-master" + "thobbs/phpcassa": "dev-master", + "techpivot/phalcon-ci-installer": "~1.0" } } diff --git a/src/OAuth2/Storage/Phalcon/Models/OauthAccessTokens.php b/src/OAuth2/Storage/Phalcon/Models/OauthAccessTokens.php index f4c162a91..bb5c79f4a 100644 --- a/src/OAuth2/Storage/Phalcon/Models/OauthAccessTokens.php +++ b/src/OAuth2/Storage/Phalcon/Models/OauthAccessTokens.php @@ -2,6 +2,8 @@ namespace OAuth2\Storage\Phalcon\Models; +use OAuth2\Storage\Phalcon\Phalcon; + class OauthAccessTokens extends \Phalcon\Mvc\Model { /** @@ -61,7 +63,7 @@ public static function findFirst($parameters = null) */ public function initialize() { - $this->setSource("'oauth__access_tokens'"); + $this->setSource("'" . $this->getDI()->get(Phalcon::KEY_PHALCON_CONFIG_ARRAY)->getAccessTokenTable() . "'"); $this->belongsTo('user_id', 'OAuth2\Storage\Phalcon\Models\OauthUsers', 'username', array("alias" => "User")); $this->belongsTo('client_id', 'OAuth2\Storage\Phalcon\Models\OauthClients', 'client_id', array("alias" => "Client")); } @@ -73,7 +75,7 @@ public function initialize() */ public function getSource() { - return 'oauth__access_tokens'; + return $this->getDI()->get(Phalcon::KEY_PHALCON_CONFIG_ARRAY)->getAccessTokenTable(); } /** diff --git a/src/OAuth2/Storage/Phalcon/Models/OauthAuthorizationCodes.php b/src/OAuth2/Storage/Phalcon/Models/OauthAuthorizationCodes.php index 1d7e5001e..e2e3fef89 100644 --- a/src/OAuth2/Storage/Phalcon/Models/OauthAuthorizationCodes.php +++ b/src/OAuth2/Storage/Phalcon/Models/OauthAuthorizationCodes.php @@ -2,6 +2,8 @@ namespace OAuth2\Storage\Phalcon\Models; +use OAuth2\Storage\Phalcon\Phalcon; + class OauthAuthorizationCodes extends \Phalcon\Mvc\Model { @@ -54,7 +56,7 @@ class OauthAuthorizationCodes extends \Phalcon\Mvc\Model */ public function getSource() { - return 'oauth__authorization_codes'; + return $this->getDI()->get(Phalcon::KEY_PHALCON_CONFIG_ARRAY)->getCodeTable(); } /** diff --git a/src/OAuth2/Storage/Phalcon/Models/OauthClients.php b/src/OAuth2/Storage/Phalcon/Models/OauthClients.php index a7a7c7b57..86a8f6645 100644 --- a/src/OAuth2/Storage/Phalcon/Models/OauthClients.php +++ b/src/OAuth2/Storage/Phalcon/Models/OauthClients.php @@ -2,6 +2,8 @@ namespace OAuth2\Storage\Phalcon\Models; +use OAuth2\Storage\Phalcon\Phalcon; + class OauthClients extends \Phalcon\Mvc\Model { @@ -68,7 +70,7 @@ public static function findFirst($parameters = null) */ public function initialize() { - $this->setSource("'oauth__clients'"); + $this->setSource("'" . $this->getDI()->get(Phalcon::KEY_PHALCON_CONFIG_ARRAY)->getClientTable() . "'"); $this->belongsTo('user_id', 'OAuth2\Storage\Phalcon\Models\OauthUsers', 'username', array("alias" => "User")); } @@ -79,7 +81,7 @@ public function initialize() */ public function getSource() { - return 'oauth__clients'; + return $this->getDI()->get(Phalcon::KEY_PHALCON_CONFIG_ARRAY)->getClientTable(); } /** diff --git a/src/OAuth2/Storage/Phalcon/Models/OauthJti.php b/src/OAuth2/Storage/Phalcon/Models/OauthJti.php index cbd5a1c90..5461c39d6 100644 --- a/src/OAuth2/Storage/Phalcon/Models/OauthJti.php +++ b/src/OAuth2/Storage/Phalcon/Models/OauthJti.php @@ -2,6 +2,8 @@ namespace OAuth2\Storage\Phalcon\Models; +use OAuth2\Storage\Phalcon\Phalcon; + class OauthJti extends \Phalcon\Mvc\Model { @@ -42,7 +44,7 @@ class OauthJti extends \Phalcon\Mvc\Model */ public function getSource() { - return 'oauth__jti'; + return $this->getDI()->get(Phalcon::KEY_PHALCON_CONFIG_ARRAY)->getJtiTable(); } /** diff --git a/src/OAuth2/Storage/Phalcon/Models/OauthJwt.php b/src/OAuth2/Storage/Phalcon/Models/OauthJwt.php index bebd42691..5faed3d2b 100644 --- a/src/OAuth2/Storage/Phalcon/Models/OauthJwt.php +++ b/src/OAuth2/Storage/Phalcon/Models/OauthJwt.php @@ -2,6 +2,8 @@ namespace OAuth2\Storage\Phalcon\Models; +use OAuth2\Storage\Phalcon\Phalcon; + class OauthJwt extends \Phalcon\Mvc\Model { @@ -50,7 +52,7 @@ public static function findFirst($parameters = null) */ public function initialize() { - $this->setSource("'oauth__jwt'"); + $this->setSource("'" . $this->getDI()->get(Phalcon::KEY_PHALCON_CONFIG_ARRAY)->getJwtTable() . "'"); $this->belongsTo('client_id', 'OAuth2\Storage\Phalcon\Models\OauthClients', 'client_id', array("alias" => "Client")); } @@ -61,9 +63,9 @@ public function initialize() */ public function getSource() { - return 'oauth__jwt'; + return $this->getDI()->get(Phalcon::KEY_PHALCON_CONFIG_ARRAY)->getJwtTable(); } - + public function getClient($parameters = null) { return $this->getRelated('Client', $parameters); diff --git a/src/OAuth2/Storage/Phalcon/Models/OauthPublicKeys.php b/src/OAuth2/Storage/Phalcon/Models/OauthPublicKeys.php index f954dd3da..bb2a14326 100644 --- a/src/OAuth2/Storage/Phalcon/Models/OauthPublicKeys.php +++ b/src/OAuth2/Storage/Phalcon/Models/OauthPublicKeys.php @@ -2,6 +2,8 @@ namespace OAuth2\Storage\Phalcon\Models; +use OAuth2\Storage\Phalcon\Phalcon; + class OauthPublicKeys extends \Phalcon\Mvc\Model { @@ -56,7 +58,7 @@ public static function findFirst($parameters = null) */ public function initialize() { - $this->setSource("'oauth__public_keys'"); + $this->setSource("'" . $this->getDI()->get(Phalcon::KEY_PHALCON_CONFIG_ARRAY)->getPublicKeyTable() . "'"); $this->belongsTo('client_id', 'OAuth2\Storage\Phalcon\Models\OauthClients', 'client_id', array("alias" => "Client")); } @@ -67,9 +69,10 @@ public function initialize() */ public function getSource() { - return 'oauth__public_keys'; + return $this->getDI()->get(Phalcon::KEY_PHALCON_CONFIG_ARRAY)->getPublicKeyTable(); } + public function getClient($parameters = null) { return $this->getRelated('Client', $parameters); diff --git a/src/OAuth2/Storage/Phalcon/Models/OauthRefreshTokens.php b/src/OAuth2/Storage/Phalcon/Models/OauthRefreshTokens.php index c3046f6e8..8d77e5da8 100644 --- a/src/OAuth2/Storage/Phalcon/Models/OauthRefreshTokens.php +++ b/src/OAuth2/Storage/Phalcon/Models/OauthRefreshTokens.php @@ -2,6 +2,8 @@ namespace OAuth2\Storage\Phalcon\Models; +use OAuth2\Storage\Phalcon\Phalcon; + class OauthRefreshTokens extends \Phalcon\Mvc\Model { /** @@ -61,7 +63,7 @@ public static function findFirst($parameters = null) */ public function initialize() { - $this->setSource("'oauth__refresh_tokens'"); + $this->setSource("'" . $this->getDI()->get(Phalcon::KEY_PHALCON_CONFIG_ARRAY)->getRefreshTokenTable() . "'"); $this->belongsTo('user_id', 'OAuth2\Storage\Phalcon\Models\OauthUsers', 'username'); $this->belongsTo('client_id', 'OAuth2\Storage\Phalcon\Models\OauthClients', 'client_id'); } @@ -73,7 +75,6 @@ public function initialize() */ public function getSource() { - return 'oauth__refresh_tokens'; + return $this->getDI()->get(Phalcon::KEY_PHALCON_CONFIG_ARRAY)->getRefreshTokenTable(); } - } \ No newline at end of file diff --git a/src/OAuth2/Storage/Phalcon/Models/OauthScopes.php b/src/OAuth2/Storage/Phalcon/Models/OauthScopes.php index 32187decb..a66f93e35 100644 --- a/src/OAuth2/Storage/Phalcon/Models/OauthScopes.php +++ b/src/OAuth2/Storage/Phalcon/Models/OauthScopes.php @@ -2,6 +2,8 @@ namespace OAuth2\Storage\Phalcon\Models; +use OAuth2\Storage\Phalcon\Phalcon; + class OauthScopes extends \Phalcon\Mvc\Model { @@ -24,7 +26,7 @@ class OauthScopes extends \Phalcon\Mvc\Model */ public function getSource() { - return 'oauth__scopes'; + return $this->getDI()->get(Phalcon::KEY_PHALCON_CONFIG_ARRAY)->getScopeTable(); } /** diff --git a/src/OAuth2/Storage/Phalcon/Models/OauthUsers.php b/src/OAuth2/Storage/Phalcon/Models/OauthUsers.php index f3846ad86..cdf9b12fb 100644 --- a/src/OAuth2/Storage/Phalcon/Models/OauthUsers.php +++ b/src/OAuth2/Storage/Phalcon/Models/OauthUsers.php @@ -2,6 +2,7 @@ namespace OAuth2\Storage\Phalcon\Models; +use OAuth2\Storage\Phalcon\Phalcon; use Phalcon\Mvc\Model\Validator\Email as Email; class OauthUsers extends \Phalcon\Mvc\Model @@ -77,7 +78,7 @@ public static function findFirst($parameters = null) public function initialize() { $this->keepSnapshots(true); - $this->setSource("'oauth__users'"); + $this->setSource("'" . $this->getDI()->get(Phalcon::KEY_PHALCON_CONFIG_ARRAY)->getUserTable() . "'"); $this->hasMany('username', 'OAuth2\Storage\Phalcon\Models\OauthAccessTokens', 'user_id', array("alias" => "AccessTokens")); $this->hasMany('username', 'OAuth2\Storage\Phalcon\Models\OauthRefreshTokens', 'user_id', array("alias" => "RefreshTokens")); } @@ -112,7 +113,7 @@ public function validation() */ public function getSource() { - return 'oauth__users'; + return $this->getDI()->get(Phalcon::KEY_PHALCON_CONFIG_ARRAY)->getUserTable(); } /** @@ -132,5 +133,5 @@ public function getRefreshTokens($parameters = null) { return $this->getRelated('RefreshTokens', $parameters); } - + } \ No newline at end of file diff --git a/src/OAuth2/Storage/Phalcon/Phalcon.php b/src/OAuth2/Storage/Phalcon/Phalcon.php index 0b449be10..105ef4185 100644 --- a/src/OAuth2/Storage/Phalcon/Phalcon.php +++ b/src/OAuth2/Storage/Phalcon/Phalcon.php @@ -33,7 +33,9 @@ class Phalcon implements UserClaimsInterface, OpenIDAuthorizationCodeInterface { + const KEY_PHALCON_CONFIG_ARRAY = 'oauth2_storage_phalcon_config'; protected $db; + protected $di; protected $config; /** @@ -43,8 +45,10 @@ class Phalcon implements */ public function __construct($di, $config = array()) { - $this->di = $di; - $this->config = array_merge(array( + if (!isset($di['db'])) + throw new \InvalidArgumentException('Dependency injector must contain a valid database connection'); + + $phalconConf = new PhalconConf(array_merge(array( 'client_table' => 'oauth_clients', 'access_token_table' => 'oauth_access_tokens', 'refresh_token_table' => 'oauth_refresh_tokens', @@ -54,7 +58,24 @@ public function __construct($di, $config = array()) 'jti_table' => 'oauth_jti', 'scope_table' => 'oauth_scopes', 'public_key_table' => 'oauth_public_keys', - ), $config); + ), $config)); + + $di->set(self::KEY_PHALCON_CONFIG_ARRAY, $phalconConf); + + $manager = $di->get('modelsManager'); + $manager->setDi($di); + $di->set('modelsManager', $manager); + + $this->config = $phalconConf; + $this->di = $di; + } + + /** + * @return \Phalcon\DiInterface + */ + public function getDi() + { + return $this->di; } /* OAuth2\Storage\ClientCredentialsInterface */ @@ -575,7 +596,7 @@ public function getEncryptionAlgorithm($client_id = null) public function getBuildSql($dbName = 'oauth2_server_php') { $sql = " - CREATE TABLE {$this->config['client_table']} ( + CREATE TABLE {$this->config->getClientTable()} ( `client_id` varchar(80) NOT NULL, `client_secret` varchar(80) DEFAULT NULL, `redirect_uri` varchar(2000) DEFAULT NULL, @@ -585,7 +606,7 @@ public function getBuildSql($dbName = 'oauth2_server_php') PRIMARY KEY (client_id) ); - CREATE TABLE {$this->config['access_token_table']} ( + CREATE TABLE {$this->config->getAccessTokenTable()} ( `access_token` varchar(40) NOT NULL, `valid` tinyint(1) NOT NULL DEFAULT '1', `client_ip` varchar(155) NOT NULL, @@ -597,7 +618,7 @@ public function getBuildSql($dbName = 'oauth2_server_php') PRIMARY KEY (access_token) ); - CREATE TABLE {$this->config['code_table']} ( + CREATE TABLE {$this->config->getCodeTable()} ( `authorization_code` varchar(40) NOT NULL, `client_id` varchar(80) NOT NULL, `user_id` varchar(80) DEFAULT NULL, @@ -608,7 +629,7 @@ public function getBuildSql($dbName = 'oauth2_server_php') PRIMARY KEY (authorization_code) ); - CREATE TABLE {$this->config['refresh_token_table']} ( + CREATE TABLE {$this->config->getRefreshTokenTable()} ( `refresh_token` varchar(40) NOT NULL, `valid` tinyint(1) NOT NULL DEFAULT '1', `client_id` varchar(80) NOT NULL, @@ -620,7 +641,7 @@ public function getBuildSql($dbName = 'oauth2_server_php') PRIMARY KEY (refresh_token) ); - CREATE TABLE {$this->config['user_table']} ( + CREATE TABLE {$this->config->getUserTable()} ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `status` tinyint(2) NOT NULL DEFAULT '0', `username` varchar(80) NOT NULL DEFAULT '', @@ -633,19 +654,19 @@ public function getBuildSql($dbName = 'oauth2_server_php') PRIMARY KEY (id) ); - CREATE TABLE {$this->config['scope_table']} ( + CREATE TABLE {$this->config->getScopeTable()} ( `scope` varchar(80) NOT NULL, `is_default` tinyint(1) DEFAULT NULL, PRIMARY KEY (scope) ); - CREATE TABLE {$this->config['jwt_table']} ( + CREATE TABLE {$this->config->getJwtTable()} ( `client_id` varchar(80) NOT NULL, `subject` varchar(80) DEFAULT NULL, `public_key` varchar(2000) NOT NULL ); - CREATE TABLE {$this->config['jti_table']} ( + CREATE TABLE {$this->config->getJtiTable()} ( `issuer` varchar(80) NOT NULL, `subject` varchar(80) DEFAULT NULL, `audience` varchar(80) DEFAULT NULL, @@ -653,7 +674,7 @@ public function getBuildSql($dbName = 'oauth2_server_php') `jti` varchar(2000) NOT NULL ); - CREATE TABLE {$this->config['public_key_table']} ( + CREATE TABLE {$this->config->getPublicKeyTable()} ( `client_id` varchar(80) DEFAULT NULL, `public_key` varchar(2000) DEFAULT NULL, `private_key` varchar(2000) DEFAULT NULL, @@ -664,4 +685,204 @@ public function getBuildSql($dbName = 'oauth2_server_php') return $sql; } +} + + +/** + * Class PhalconConf + * @package OAuth2\Storage\Phalcon + * + * This config class is used purely internally for communication + * between the model files and the main Phalcon storage class + * for setting table names dynamically. + */ +class PhalconConf +{ + private $client_table; + private $access_token_table; + private $refresh_token_table; + private $code_table; + private $user_table; + private $jwt_table; + private $jti_table; + private $scope_table; + private $public_key_table; + + /** + * PhalconConf constructor. + * @param array $config + * @throws \UnexpectedValueException + */ + public function __construct($config) + { + if ( + isset($config['client_table']) && + isset($config['access_token_table']) && + isset($config['refresh_token_table']) && + isset($config['code_table']) && + isset($config['user_table']) && + isset($config['jwt_table']) && + isset($config['jti_table']) && + isset($config['scope_table']) && + isset($config['public_key_table']) + ) { + $this->setClientTable($config['client_table']); + $this->setAccessTokenTable($config['access_token_table']); + $this->setRefreshTokenTable($config['refresh_token_table']); + $this->setCodeTable($config['code_table']); + $this->setUserTable($config['user_table']); + $this->setJwtTable($config['jwt_table']); + $this->setJtiTable($config['jti_table']); + $this->setScopeTable($config['scope_table']); + $this->setPublicKeyTable($config['public_key_table']); + } else { + throw new \UnexpectedValueException('Config array must contain all keys!'); + } + } + + + /** + * @return mixed + */ + public function getClientTable() + { + return $this->client_table; + } + + /** + * @param mixed $client_table + */ + public function setClientTable($client_table) + { + $this->client_table = $client_table; + } + + /** + * @return mixed + */ + public function getAccessTokenTable() + { + return $this->access_token_table; + } + + /** + * @param mixed $access_token_table + */ + public function setAccessTokenTable($access_token_table) + { + $this->access_token_table = $access_token_table; + } + + /** + * @return mixed + */ + public function getRefreshTokenTable() + { + return $this->refresh_token_table; + } + + /** + * @param mixed $refresh_token_table + */ + public function setRefreshTokenTable($refresh_token_table) + { + $this->refresh_token_table = $refresh_token_table; + } + + /** + * @return mixed + */ + public function getCodeTable() + { + return $this->code_table; + } + + /** + * @param mixed $code_table + */ + public function setCodeTable($code_table) + { + $this->code_table = $code_table; + } + + /** + * @return mixed + */ + public function getUserTable() + { + return $this->user_table; + } + + /** + * @param mixed $user_table + */ + public function setUserTable($user_table) + { + $this->user_table = $user_table; + } + + /** + * @return mixed + */ + public function getJwtTable() + { + return $this->jwt_table; + } + + /** + * @param mixed $jwt_table + */ + public function setJwtTable($jwt_table) + { + $this->jwt_table = $jwt_table; + } + + /** + * @return mixed + */ + public function getJtiTable() + { + return $this->jti_table; + } + + /** + * @param mixed $jti_table + */ + public function setJtiTable($jti_table) + { + $this->jti_table = $jti_table; + } + + /** + * @return mixed + */ + public function getScopeTable() + { + return $this->scope_table; + } + + /** + * @param mixed $scope_table + */ + public function setScopeTable($scope_table) + { + $this->scope_table = $scope_table; + } + + /** + * @return mixed + */ + public function getPublicKeyTable() + { + return $this->public_key_table; + } + + /** + * @param mixed $public_key_table + */ + public function setPublicKeyTable($public_key_table) + { + $this->public_key_table = $public_key_table; + } + } \ No newline at end of file diff --git a/test/OAuth2/AutoloadTest.php b/test/OAuth2/AutoloadTest.php index 5901bdc42..baba16b8d 100644 --- a/test/OAuth2/AutoloadTest.php +++ b/test/OAuth2/AutoloadTest.php @@ -12,5 +12,7 @@ public function testClassesExist() $this->assertTrue(class_exists('OAuth2\Response')); $this->assertTrue(class_exists('OAuth2\GrantType\UserCredentials')); $this->assertTrue(interface_exists('OAuth2\Storage\AccessTokenInterface')); + $this->assertTrue(class_exists('OAuth2\Storage\Phalcon\Phalcon')); + $this->assertTrue(class_exists('OAuth2\Storage\Phalcon\Models\OauthUsers')); } } diff --git a/test/OAuth2/Storage/Phalcon/PhalconTest.php b/test/OAuth2/Storage/Phalcon/PhalconTest.php new file mode 100644 index 000000000..479209679 --- /dev/null +++ b/test/OAuth2/Storage/Phalcon/PhalconTest.php @@ -0,0 +1,99 @@ +checkExtension('phalcon'); + // Reset the DI container + Di::reset(); + + // Instantiate a new DI container (this would automatically be created in a normal Phalcon install) + $di = new Di(); + $di->set( + 'url', + function () { + $url = new Url(); + $url->setBaseUri('/'); + return $url; + } + ); + + $di->set( + 'escaper', + function () { + return new Escaper(); + } + ); + + $di->set('db', function() { + return new Mysql(array( + "host" => "localhost", + "username" => "root", + "password" => "", + "dbname" => "oauth2_server_php", + )); + }); + + $di->set( + 'modelsManager', + function () { + return new Manager(); + } + ); + + $di->set( + 'modelsMetadata', + function () { + return new Memory(); + } + ); + + $this->di = $di; + } + + public function checkExtension($extension) + { + $message = function ($ext) { + sprintf('Warning: %s extension is not loaded', $ext); + }; + if (is_array($extension)) { + foreach ($extension as $ext) { + if (!extension_loaded($ext)) { + $this->markTestSkipped($message($ext)); + break; + } + } + } elseif (!extension_loaded($extension)) { + $this->markTestSkipped($message($extension)); + } + } + + public function testPhalconDataStorage(){ + $this->setUp(); + $storage = new Phalcon($this->di); + $this->assertNotNull($storage->getClientDetails('oauth_test_client')); + } + +} \ No newline at end of file diff --git a/test/OAuth2/Storage/PhalconTest.php b/test/OAuth2/Storage/PhalconTest.php deleted file mode 100644 index 5ee4c29ae..000000000 --- a/test/OAuth2/Storage/PhalconTest.php +++ /dev/null @@ -1,15 +0,0 @@ - Date: Wed, 6 Jul 2016 16:33:59 -0400 Subject: [PATCH 14/19] Using function instead of class object (#3) * Using array instead of class * Removed unused PhalconConf class --- .../Phalcon/Models/OauthAccessTokens.php | 4 +- .../Models/OauthAuthorizationCodes.php | 2 +- .../Storage/Phalcon/Models/OauthClients.php | 4 +- .../Storage/Phalcon/Models/OauthJti.php | 2 +- .../Storage/Phalcon/Models/OauthJwt.php | 4 +- .../Phalcon/Models/OauthPublicKeys.php | 4 +- .../Phalcon/Models/OauthRefreshTokens.php | 4 +- .../Storage/Phalcon/Models/OauthScopes.php | 2 +- .../Storage/Phalcon/Models/OauthUsers.php | 4 +- src/OAuth2/Storage/Phalcon/Phalcon.php | 358 ++++-------------- 10 files changed, 98 insertions(+), 290 deletions(-) diff --git a/src/OAuth2/Storage/Phalcon/Models/OauthAccessTokens.php b/src/OAuth2/Storage/Phalcon/Models/OauthAccessTokens.php index bb5c79f4a..8baae1851 100644 --- a/src/OAuth2/Storage/Phalcon/Models/OauthAccessTokens.php +++ b/src/OAuth2/Storage/Phalcon/Models/OauthAccessTokens.php @@ -63,7 +63,7 @@ public static function findFirst($parameters = null) */ public function initialize() { - $this->setSource("'" . $this->getDI()->get(Phalcon::KEY_PHALCON_CONFIG_ARRAY)->getAccessTokenTable() . "'"); + $this->setSource("'" . $this->getDI()->get(Phalcon::KEY_PHALCON_CONFIG_ARRAY)['access_token_table'] . "'"); $this->belongsTo('user_id', 'OAuth2\Storage\Phalcon\Models\OauthUsers', 'username', array("alias" => "User")); $this->belongsTo('client_id', 'OAuth2\Storage\Phalcon\Models\OauthClients', 'client_id', array("alias" => "Client")); } @@ -75,7 +75,7 @@ public function initialize() */ public function getSource() { - return $this->getDI()->get(Phalcon::KEY_PHALCON_CONFIG_ARRAY)->getAccessTokenTable(); + return $this->getDI()->get(Phalcon::KEY_PHALCON_CONFIG_ARRAY)['access_token_table']; } /** diff --git a/src/OAuth2/Storage/Phalcon/Models/OauthAuthorizationCodes.php b/src/OAuth2/Storage/Phalcon/Models/OauthAuthorizationCodes.php index e2e3fef89..85a10dfca 100644 --- a/src/OAuth2/Storage/Phalcon/Models/OauthAuthorizationCodes.php +++ b/src/OAuth2/Storage/Phalcon/Models/OauthAuthorizationCodes.php @@ -56,7 +56,7 @@ class OauthAuthorizationCodes extends \Phalcon\Mvc\Model */ public function getSource() { - return $this->getDI()->get(Phalcon::KEY_PHALCON_CONFIG_ARRAY)->getCodeTable(); + return $this->getDI()->get(Phalcon::KEY_PHALCON_CONFIG_ARRAY)['code_table']; } /** diff --git a/src/OAuth2/Storage/Phalcon/Models/OauthClients.php b/src/OAuth2/Storage/Phalcon/Models/OauthClients.php index 86a8f6645..8dbacc283 100644 --- a/src/OAuth2/Storage/Phalcon/Models/OauthClients.php +++ b/src/OAuth2/Storage/Phalcon/Models/OauthClients.php @@ -70,7 +70,7 @@ public static function findFirst($parameters = null) */ public function initialize() { - $this->setSource("'" . $this->getDI()->get(Phalcon::KEY_PHALCON_CONFIG_ARRAY)->getClientTable() . "'"); + $this->setSource("'" . $this->getDI()->get(Phalcon::KEY_PHALCON_CONFIG_ARRAY)['client_table'] . "'"); $this->belongsTo('user_id', 'OAuth2\Storage\Phalcon\Models\OauthUsers', 'username', array("alias" => "User")); } @@ -81,7 +81,7 @@ public function initialize() */ public function getSource() { - return $this->getDI()->get(Phalcon::KEY_PHALCON_CONFIG_ARRAY)->getClientTable(); + return $this->getDI()->get(Phalcon::KEY_PHALCON_CONFIG_ARRAY)['client_table']; } /** diff --git a/src/OAuth2/Storage/Phalcon/Models/OauthJti.php b/src/OAuth2/Storage/Phalcon/Models/OauthJti.php index 5461c39d6..5735ff420 100644 --- a/src/OAuth2/Storage/Phalcon/Models/OauthJti.php +++ b/src/OAuth2/Storage/Phalcon/Models/OauthJti.php @@ -44,7 +44,7 @@ class OauthJti extends \Phalcon\Mvc\Model */ public function getSource() { - return $this->getDI()->get(Phalcon::KEY_PHALCON_CONFIG_ARRAY)->getJtiTable(); + return $this->getDI()->get(Phalcon::KEY_PHALCON_CONFIG_ARRAY)['jti_table']; } /** diff --git a/src/OAuth2/Storage/Phalcon/Models/OauthJwt.php b/src/OAuth2/Storage/Phalcon/Models/OauthJwt.php index 5faed3d2b..0331edeb8 100644 --- a/src/OAuth2/Storage/Phalcon/Models/OauthJwt.php +++ b/src/OAuth2/Storage/Phalcon/Models/OauthJwt.php @@ -52,7 +52,7 @@ public static function findFirst($parameters = null) */ public function initialize() { - $this->setSource("'" . $this->getDI()->get(Phalcon::KEY_PHALCON_CONFIG_ARRAY)->getJwtTable() . "'"); + $this->setSource("'" . $this->getDI()->get(Phalcon::KEY_PHALCON_CONFIG_ARRAY)['jwt_table'] . "'"); $this->belongsTo('client_id', 'OAuth2\Storage\Phalcon\Models\OauthClients', 'client_id', array("alias" => "Client")); } @@ -63,7 +63,7 @@ public function initialize() */ public function getSource() { - return $this->getDI()->get(Phalcon::KEY_PHALCON_CONFIG_ARRAY)->getJwtTable(); + return $this->getDI()->get(Phalcon::KEY_PHALCON_CONFIG_ARRAY)['jwt_table']; } public function getClient($parameters = null) diff --git a/src/OAuth2/Storage/Phalcon/Models/OauthPublicKeys.php b/src/OAuth2/Storage/Phalcon/Models/OauthPublicKeys.php index bb2a14326..3152fca11 100644 --- a/src/OAuth2/Storage/Phalcon/Models/OauthPublicKeys.php +++ b/src/OAuth2/Storage/Phalcon/Models/OauthPublicKeys.php @@ -58,7 +58,7 @@ public static function findFirst($parameters = null) */ public function initialize() { - $this->setSource("'" . $this->getDI()->get(Phalcon::KEY_PHALCON_CONFIG_ARRAY)->getPublicKeyTable() . "'"); + $this->setSource("'" . $this->getDI()->get(Phalcon::KEY_PHALCON_CONFIG_ARRAY)['public_key_table'] . "'"); $this->belongsTo('client_id', 'OAuth2\Storage\Phalcon\Models\OauthClients', 'client_id', array("alias" => "Client")); } @@ -69,7 +69,7 @@ public function initialize() */ public function getSource() { - return $this->getDI()->get(Phalcon::KEY_PHALCON_CONFIG_ARRAY)->getPublicKeyTable(); + return $this->getDI()->get(Phalcon::KEY_PHALCON_CONFIG_ARRAY)['public_key_table']; } diff --git a/src/OAuth2/Storage/Phalcon/Models/OauthRefreshTokens.php b/src/OAuth2/Storage/Phalcon/Models/OauthRefreshTokens.php index 8d77e5da8..ded6a100e 100644 --- a/src/OAuth2/Storage/Phalcon/Models/OauthRefreshTokens.php +++ b/src/OAuth2/Storage/Phalcon/Models/OauthRefreshTokens.php @@ -63,7 +63,7 @@ public static function findFirst($parameters = null) */ public function initialize() { - $this->setSource("'" . $this->getDI()->get(Phalcon::KEY_PHALCON_CONFIG_ARRAY)->getRefreshTokenTable() . "'"); + $this->setSource("'" . $this->getDI()->get(Phalcon::KEY_PHALCON_CONFIG_ARRAY)['refresh_token_table'] . "'"); $this->belongsTo('user_id', 'OAuth2\Storage\Phalcon\Models\OauthUsers', 'username'); $this->belongsTo('client_id', 'OAuth2\Storage\Phalcon\Models\OauthClients', 'client_id'); } @@ -75,6 +75,6 @@ public function initialize() */ public function getSource() { - return $this->getDI()->get(Phalcon::KEY_PHALCON_CONFIG_ARRAY)->getRefreshTokenTable(); + return $this->getDI()->get(Phalcon::KEY_PHALCON_CONFIG_ARRAY)['refresh_token_table']; } } \ No newline at end of file diff --git a/src/OAuth2/Storage/Phalcon/Models/OauthScopes.php b/src/OAuth2/Storage/Phalcon/Models/OauthScopes.php index a66f93e35..4c73468e6 100644 --- a/src/OAuth2/Storage/Phalcon/Models/OauthScopes.php +++ b/src/OAuth2/Storage/Phalcon/Models/OauthScopes.php @@ -26,7 +26,7 @@ class OauthScopes extends \Phalcon\Mvc\Model */ public function getSource() { - return $this->getDI()->get(Phalcon::KEY_PHALCON_CONFIG_ARRAY)->getScopeTable(); + return $this->getDI()->get(Phalcon::KEY_PHALCON_CONFIG_ARRAY)['scope_table']; } /** diff --git a/src/OAuth2/Storage/Phalcon/Models/OauthUsers.php b/src/OAuth2/Storage/Phalcon/Models/OauthUsers.php index cdf9b12fb..000ee0625 100644 --- a/src/OAuth2/Storage/Phalcon/Models/OauthUsers.php +++ b/src/OAuth2/Storage/Phalcon/Models/OauthUsers.php @@ -78,7 +78,7 @@ public static function findFirst($parameters = null) public function initialize() { $this->keepSnapshots(true); - $this->setSource("'" . $this->getDI()->get(Phalcon::KEY_PHALCON_CONFIG_ARRAY)->getUserTable() . "'"); + $this->setSource("'" . $this->getDI()->get(Phalcon::KEY_PHALCON_CONFIG_ARRAY)['user_table'] . "'"); $this->hasMany('username', 'OAuth2\Storage\Phalcon\Models\OauthAccessTokens', 'user_id', array("alias" => "AccessTokens")); $this->hasMany('username', 'OAuth2\Storage\Phalcon\Models\OauthRefreshTokens', 'user_id', array("alias" => "RefreshTokens")); } @@ -113,7 +113,7 @@ public function validation() */ public function getSource() { - return $this->getDI()->get(Phalcon::KEY_PHALCON_CONFIG_ARRAY)->getUserTable(); + return $this->getDI()->get(Phalcon::KEY_PHALCON_CONFIG_ARRAY)['user_table']; } /** diff --git a/src/OAuth2/Storage/Phalcon/Phalcon.php b/src/OAuth2/Storage/Phalcon/Phalcon.php index 105ef4185..a1d48d433 100644 --- a/src/OAuth2/Storage/Phalcon/Phalcon.php +++ b/src/OAuth2/Storage/Phalcon/Phalcon.php @@ -48,7 +48,7 @@ public function __construct($di, $config = array()) if (!isset($di['db'])) throw new \InvalidArgumentException('Dependency injector must contain a valid database connection'); - $phalconConf = new PhalconConf(array_merge(array( + $config = array_merge(array( 'client_table' => 'oauth_clients', 'access_token_table' => 'oauth_access_tokens', 'refresh_token_table' => 'oauth_refresh_tokens', @@ -58,15 +58,17 @@ public function __construct($di, $config = array()) 'jti_table' => 'oauth_jti', 'scope_table' => 'oauth_scopes', 'public_key_table' => 'oauth_public_keys', - ), $config)); + ), $config); - $di->set(self::KEY_PHALCON_CONFIG_ARRAY, $phalconConf); + $di->set(self::KEY_PHALCON_CONFIG_ARRAY, function () use ($config) { + return $config; + }); $manager = $di->get('modelsManager'); $manager->setDi($di); $di->set('modelsManager', $manager); - $this->config = $phalconConf; + $this->config = $config; $this->di = $di; } @@ -105,19 +107,6 @@ public function isPublicClient($client_id) return empty($clients->client_secret); } - public function getClientDetails($client_id) - { - $clients = Models\OauthClients::findFirst( - array( - "conditions" => "client_id = ?1", - "bind" => array(1 => $client_id), - "limit" => 1 - ) - ); - - return $clients->toArray(); - } - public function setClientDetails($client_id, $client_secret = null, $redirect_uri = null, $grant_types = null, $scope = null, $user_id = null) { $client = new Models\OauthClients(); @@ -145,7 +134,21 @@ public function checkRestrictedGrantType($client_id, $grant_type) return true; } + public function getClientDetails($client_id) + { + $clients = Models\OauthClients::findFirst( + array( + "conditions" => "client_id = ?1", + "bind" => array(1 => $client_id), + "limit" => 1 + ) + ); + + return $clients->toArray(); + } + /* OAuth2\Storage\AccessTokenInterface */ + public function getAccessToken($access_token) { $token = Models\OauthAccessTokens::findFirst( @@ -198,24 +201,6 @@ public function unsetAccessToken($access_token) } /* OAuth2\Storage\AuthorizationCodeInterface */ - public function getAuthorizationCode($code) - { - $code = Models\OauthAuthorizationCodes::findFirst( - array( - "conditions" => "authorization_code = ?1", - "bind" => array(1 => $code), - "limit" => 1 - ) - ); - if ($code != false) { - $codeArray = $code->toArray(); - $codeArray['expires'] = strtotime($code->expires); - return $codeArray; - } else { - // If code == false, then return false - return false; - } - } public function setAuthorizationCode($code, $client_id, $user_id, $redirect_uri, $expires, $scope = null, $id_token = null) { @@ -240,6 +225,25 @@ public function setAuthorizationCode($code, $client_id, $user_id, $redirect_uri, return $authCode->save(); } + public function getAuthorizationCode($code) + { + $code = Models\OauthAuthorizationCodes::findFirst( + array( + "conditions" => "authorization_code = ?1", + "bind" => array(1 => $code), + "limit" => 1 + ) + ); + if ($code != false) { + $codeArray = $code->toArray(); + $codeArray['expires'] = strtotime($code->expires); + return $codeArray; + } else { + // If code == false, then return false + return false; + } + } + /** * @deprecated No longer used. * @see setAuthorizationCode. @@ -290,12 +294,36 @@ public function checkUserCredentials($username, $password) return false; } - public function getUserDetails($username) + public function getUser($username) { - return $this->getUser($username); + $user = Models\OauthUsers::findFirst( + array( + "conditions" => "username = ?1", + "bind" => array(1 => $username), + "limit" => 1 + ) + ); + + if ($user == false) + return false; + else + return array_merge(array('user_id' => $username), $user->toArray()); } /* OAuth2\Storage\UserClaimsInterface */ + + protected function checkPassword($user, $password) + { + return $user['password'] == $this->hashPassword($password); + } + + protected function hashPassword($password) + { + return sha1($password); + } + + /* OAuth2\Storage\RefreshTokenInterface */ + public function getUserClaims($user_id, $claims) { if (!$userDetails = $this->getUserDetails($user_id)) { @@ -321,6 +349,13 @@ public function getUserClaims($user_id, $claims) return $userClaims; } + // use a secure hashing algorithm when storing passwords. Override this for your application + + public function getUserDetails($username) + { + return $this->getUser($username); + } + protected function getUserClaim($claim, $userDetails) { $userClaims = array(); @@ -334,7 +369,8 @@ protected function getUserClaim($claim, $userDetails) return $userClaims; } - /* OAuth2\Storage\RefreshTokenInterface */ + /* OAuth2\Storage\UserCredentialsInterface */ + public function getRefreshToken($refresh_token) { $token = Models\OauthRefreshTokens::findFirst( @@ -355,7 +391,6 @@ public function getRefreshToken($refresh_token) } } - // use a secure hashing algorithm when storing passwords. Override this for your application public function setRefreshToken($refresh_token, $client_id, $user_id, $expires, $scope = null) { // convert expires to datestring @@ -386,33 +421,6 @@ public function unsetRefreshToken($refresh_token) return $token->delete(); } - /* OAuth2\Storage\UserCredentialsInterface */ - protected function checkPassword($user, $password) - { - return $user['password'] == $this->hashPassword($password); - } - - protected function hashPassword($password) - { - return sha1($password); - } - - public function getUser($username) - { - $user = Models\OauthUsers::findFirst( - array( - "conditions" => "username = ?1", - "bind" => array(1 => $username), - "limit" => 1 - ) - ); - - if ($user == false) - return false; - else - return array_merge(array('user_id' => $username), $user->toArray()); - } - public function setUser($username, $password, $firstName = null, $lastName = null) { // do not store in plaintext @@ -596,7 +604,7 @@ public function getEncryptionAlgorithm($client_id = null) public function getBuildSql($dbName = 'oauth2_server_php') { $sql = " - CREATE TABLE {$this->config->getClientTable()} ( + CREATE TABLE {$this->config['client_table']} ( `client_id` varchar(80) NOT NULL, `client_secret` varchar(80) DEFAULT NULL, `redirect_uri` varchar(2000) DEFAULT NULL, @@ -606,7 +614,7 @@ public function getBuildSql($dbName = 'oauth2_server_php') PRIMARY KEY (client_id) ); - CREATE TABLE {$this->config->getAccessTokenTable()} ( + CREATE TABLE {$this->config['access_token_table']} ( `access_token` varchar(40) NOT NULL, `valid` tinyint(1) NOT NULL DEFAULT '1', `client_ip` varchar(155) NOT NULL, @@ -618,7 +626,7 @@ public function getBuildSql($dbName = 'oauth2_server_php') PRIMARY KEY (access_token) ); - CREATE TABLE {$this->config->getCodeTable()} ( + CREATE TABLE {$this->config['code_table']} ( `authorization_code` varchar(40) NOT NULL, `client_id` varchar(80) NOT NULL, `user_id` varchar(80) DEFAULT NULL, @@ -629,7 +637,7 @@ public function getBuildSql($dbName = 'oauth2_server_php') PRIMARY KEY (authorization_code) ); - CREATE TABLE {$this->config->getRefreshTokenTable()} ( + CREATE TABLE {$this->config['refresh_token_table']} ( `refresh_token` varchar(40) NOT NULL, `valid` tinyint(1) NOT NULL DEFAULT '1', `client_id` varchar(80) NOT NULL, @@ -641,7 +649,7 @@ public function getBuildSql($dbName = 'oauth2_server_php') PRIMARY KEY (refresh_token) ); - CREATE TABLE {$this->config->getUserTable()} ( + CREATE TABLE {$this->config['user_table']} ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `status` tinyint(2) NOT NULL DEFAULT '0', `username` varchar(80) NOT NULL DEFAULT '', @@ -654,19 +662,19 @@ public function getBuildSql($dbName = 'oauth2_server_php') PRIMARY KEY (id) ); - CREATE TABLE {$this->config->getScopeTable()} ( + CREATE TABLE {$this->config['scope_table']} ( `scope` varchar(80) NOT NULL, `is_default` tinyint(1) DEFAULT NULL, PRIMARY KEY (scope) ); - CREATE TABLE {$this->config->getJwtTable()} ( + CREATE TABLE {$this->config['jwt_table']} ( `client_id` varchar(80) NOT NULL, `subject` varchar(80) DEFAULT NULL, `public_key` varchar(2000) NOT NULL ); - CREATE TABLE {$this->config->getJtiTable()} ( + CREATE TABLE {$this->config['jti_table']} ( `issuer` varchar(80) NOT NULL, `subject` varchar(80) DEFAULT NULL, `audience` varchar(80) DEFAULT NULL, @@ -674,7 +682,7 @@ public function getBuildSql($dbName = 'oauth2_server_php') `jti` varchar(2000) NOT NULL ); - CREATE TABLE {$this->config->getPublicKeyTable()} ( + CREATE TABLE {$this->config['public_key_table']} ( `client_id` varchar(80) DEFAULT NULL, `public_key` varchar(2000) DEFAULT NULL, `private_key` varchar(2000) DEFAULT NULL, @@ -685,204 +693,4 @@ public function getBuildSql($dbName = 'oauth2_server_php') return $sql; } -} - - -/** - * Class PhalconConf - * @package OAuth2\Storage\Phalcon - * - * This config class is used purely internally for communication - * between the model files and the main Phalcon storage class - * for setting table names dynamically. - */ -class PhalconConf -{ - private $client_table; - private $access_token_table; - private $refresh_token_table; - private $code_table; - private $user_table; - private $jwt_table; - private $jti_table; - private $scope_table; - private $public_key_table; - - /** - * PhalconConf constructor. - * @param array $config - * @throws \UnexpectedValueException - */ - public function __construct($config) - { - if ( - isset($config['client_table']) && - isset($config['access_token_table']) && - isset($config['refresh_token_table']) && - isset($config['code_table']) && - isset($config['user_table']) && - isset($config['jwt_table']) && - isset($config['jti_table']) && - isset($config['scope_table']) && - isset($config['public_key_table']) - ) { - $this->setClientTable($config['client_table']); - $this->setAccessTokenTable($config['access_token_table']); - $this->setRefreshTokenTable($config['refresh_token_table']); - $this->setCodeTable($config['code_table']); - $this->setUserTable($config['user_table']); - $this->setJwtTable($config['jwt_table']); - $this->setJtiTable($config['jti_table']); - $this->setScopeTable($config['scope_table']); - $this->setPublicKeyTable($config['public_key_table']); - } else { - throw new \UnexpectedValueException('Config array must contain all keys!'); - } - } - - - /** - * @return mixed - */ - public function getClientTable() - { - return $this->client_table; - } - - /** - * @param mixed $client_table - */ - public function setClientTable($client_table) - { - $this->client_table = $client_table; - } - - /** - * @return mixed - */ - public function getAccessTokenTable() - { - return $this->access_token_table; - } - - /** - * @param mixed $access_token_table - */ - public function setAccessTokenTable($access_token_table) - { - $this->access_token_table = $access_token_table; - } - - /** - * @return mixed - */ - public function getRefreshTokenTable() - { - return $this->refresh_token_table; - } - - /** - * @param mixed $refresh_token_table - */ - public function setRefreshTokenTable($refresh_token_table) - { - $this->refresh_token_table = $refresh_token_table; - } - - /** - * @return mixed - */ - public function getCodeTable() - { - return $this->code_table; - } - - /** - * @param mixed $code_table - */ - public function setCodeTable($code_table) - { - $this->code_table = $code_table; - } - - /** - * @return mixed - */ - public function getUserTable() - { - return $this->user_table; - } - - /** - * @param mixed $user_table - */ - public function setUserTable($user_table) - { - $this->user_table = $user_table; - } - - /** - * @return mixed - */ - public function getJwtTable() - { - return $this->jwt_table; - } - - /** - * @param mixed $jwt_table - */ - public function setJwtTable($jwt_table) - { - $this->jwt_table = $jwt_table; - } - - /** - * @return mixed - */ - public function getJtiTable() - { - return $this->jti_table; - } - - /** - * @param mixed $jti_table - */ - public function setJtiTable($jti_table) - { - $this->jti_table = $jti_table; - } - - /** - * @return mixed - */ - public function getScopeTable() - { - return $this->scope_table; - } - - /** - * @param mixed $scope_table - */ - public function setScopeTable($scope_table) - { - $this->scope_table = $scope_table; - } - - /** - * @return mixed - */ - public function getPublicKeyTable() - { - return $this->public_key_table; - } - - /** - * @param mixed $public_key_table - */ - public function setPublicKeyTable($public_key_table) - { - $this->public_key_table = $public_key_table; - } - } \ No newline at end of file From 4f906097abfbab64de856c033c69c6688f53178c Mon Sep 17 00:00:00 2001 From: Luca Santarella Date: Thu, 7 Jul 2016 09:12:41 -0400 Subject: [PATCH 15/19] Using old array syntax for compatibility with PHP 5.3 --- src/OAuth2/Storage/Phalcon/Phalcon.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/OAuth2/Storage/Phalcon/Phalcon.php b/src/OAuth2/Storage/Phalcon/Phalcon.php index a1d48d433..9f95bc1eb 100644 --- a/src/OAuth2/Storage/Phalcon/Phalcon.php +++ b/src/OAuth2/Storage/Phalcon/Phalcon.php @@ -518,19 +518,19 @@ public function getJti($client_id, $subject, $audience, $expires, $jti) $result = Models\OauthJti::findFirst( array( "conditions" => "client_id = :client_id: AND subject = :subject: AND audience = :audience: AND expires = :expires: AND jti = :jti:", - "bind" => [ + "bind" => array( "client_id" => $client_id, "subject" => $subject, "audience" => $audience, "expires" => $expires, "jti" => $jti - ], + ), "limit" => 1 ) ); if ($result != false) - return $result->toArray(['issuer', 'subject', 'audience', 'expires', 'jti']); + return $result->toArray(array('issuer', 'subject', 'audience', 'expires', 'jti')); else return null; } From 97d6f14977ac14e6de37b2087db494de1bd5651e Mon Sep 17 00:00:00 2001 From: Luca Santarella Date: Thu, 7 Jul 2016 09:48:29 -0400 Subject: [PATCH 16/19] Updated travis config --- .travis.yml | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index 1d463fe44..d153a70c0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,10 +6,12 @@ cache: - vendor - $HOME/cphalcon php: -- 5.3 +- 5.3.29 - 5.4 - 5.5 - 5.6 +- 7 +- hhvm env: global: - SKIP_MONGO_TESTS=1 @@ -22,13 +24,15 @@ services: - mysql - memcached before_install: - - composer install --prefer-source --no-interaction - - vendor/bin/install-phalcon.sh 2.0.x - phpenv config-rm xdebug.ini || return 0 install: -- composer install --no-interaction + - composer install --prefer-source --no-interaction + - if [[ ${TRAVIS_PHP_VERSION:0} == "5.4" ]]; then vendor/bin/install-phalcon.sh 2.0.x; fi; + - if [[ ${TRAVIS_PHP_VERSION:0} == "5.5" ]]; then vendor/bin/install-phalcon.sh 2.0.x; fi; + - if [[ ${TRAVIS_PHP_VERSION:0} == "5.6" ]]; then vendor/bin/install-phalcon.sh 2.0.x; fi; before_script: -- php -m - psql -c 'create database oauth2_server_php;' -U postgres +script: + phpunit -v after_script: -- php test/cleanup.php +- php test/cleanup.php \ No newline at end of file From ab1d2bde86f4f3d8d6abe63b01474d7d156cd895 Mon Sep 17 00:00:00 2001 From: Luca Santarella Date: Thu, 7 Jul 2016 09:49:07 -0400 Subject: [PATCH 17/19] All php 5.3 versions --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index d153a70c0..87685810f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,7 +6,7 @@ cache: - vendor - $HOME/cphalcon php: -- 5.3.29 +- 5.3 - 5.4 - 5.5 - 5.6 From 122aebddf95d40aee7f08d6032c8078e8f28cadb Mon Sep 17 00:00:00 2001 From: Luca Santarella Date: Thu, 4 Aug 2016 15:13:49 -0700 Subject: [PATCH 18/19] Requiring Phalcon extension --- test/OAuth2/Storage/Phalcon/PhalconTest.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/OAuth2/Storage/Phalcon/PhalconTest.php b/test/OAuth2/Storage/Phalcon/PhalconTest.php index 479209679..f8596aee2 100644 --- a/test/OAuth2/Storage/Phalcon/PhalconTest.php +++ b/test/OAuth2/Storage/Phalcon/PhalconTest.php @@ -8,7 +8,6 @@ namespace OAuth2\Storage\Phalcon; - use OAuth2\Storage\BaseTest; use Phalcon\Db\Adapter\Pdo\Mysql; use Phalcon\Di; @@ -17,6 +16,9 @@ use Phalcon\Mvc\Model\MetaData\Memory; use Phalcon\Mvc\Url; +/** + * @requires extension phalcon + */ class PhalconTest extends BaseTest { private $di; From a0169041b8bc395714613fa1b214004629bb7aa6 Mon Sep 17 00:00:00 2001 From: Luca Santarella Date: Thu, 4 Aug 2016 15:46:57 -0700 Subject: [PATCH 19/19] Requiring Phalcon extension for autoload --- test/OAuth2/AutoloadTest.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/test/OAuth2/AutoloadTest.php b/test/OAuth2/AutoloadTest.php index baba16b8d..5587cf061 100644 --- a/test/OAuth2/AutoloadTest.php +++ b/test/OAuth2/AutoloadTest.php @@ -13,6 +13,13 @@ public function testClassesExist() $this->assertTrue(class_exists('OAuth2\GrantType\UserCredentials')); $this->assertTrue(interface_exists('OAuth2\Storage\AccessTokenInterface')); $this->assertTrue(class_exists('OAuth2\Storage\Phalcon\Phalcon')); + } + + /** + * @requires extension phalcon + */ + public function testPhalconClassesExist() + { $this->assertTrue(class_exists('OAuth2\Storage\Phalcon\Models\OauthUsers')); } }