From 4178c95bde67fa2e9520025a13c39e353327281a Mon Sep 17 00:00:00 2001 From: Sebastian Marcet Date: Wed, 23 Mar 2016 11:10:44 -0300 Subject: [PATCH] * fix on access token revoke * improved tokens generation * fixed some typos Change-Id: Id95265d6e62dddbea4d4929e34915571614cd102 --- app/controllers/apis/ClientApiController.php | 8 +- app/libs/oauth2/models/AccessToken.php | 10 +- app/libs/oauth2/models/AuthorizationCode.php | 8 ++ app/libs/oauth2/models/RefreshToken.php | 8 ++ app/libs/openid/model/OpenIdNonce.php | 10 +- app/libs/utils/model/Identifier.php | 5 + .../services/UniqueIdentifierGenerator.php | 5 +- app/routes.php | 2 +- app/tests/OIDCProtocolTest.php | 116 +++++++++++++++++- 9 files changed, 161 insertions(+), 11 deletions(-) diff --git a/app/controllers/apis/ClientApiController.php b/app/controllers/apis/ClientApiController.php index 436b1deb..b2b537c4 100644 --- a/app/controllers/apis/ClientApiController.php +++ b/app/controllers/apis/ClientApiController.php @@ -432,8 +432,8 @@ final class ClientApiController extends AbstractRESTController implements ICRUDC if (is_null($token)) { return $this->error404(array('error' => sprintf('access token %s does not exists!', $value))); } - if ($token->getClientId() !== $client->client_id) { - return $this->error404(array( + if (intval($token->getClientId()) !== intval($client->id)) { + return $this->error412(array( 'error' => sprintf('access token %s does not belongs to client id !', $value, $id) )); } @@ -445,8 +445,8 @@ final class ClientApiController extends AbstractRESTController implements ICRUDC if (is_null($token)) { return $this->error404(array('error' => sprintf('refresh token %s does not exists!', $value))); } - if ($token->getClientId() !== $client->client_id) { - return $this->error404(array( + if (intval($token->getClientId()) !== intval($client->id)) { + return $this->error412(array( 'error' => sprintf('refresh token %s does not belongs to client id !', $value, $id) )); } diff --git a/app/libs/oauth2/models/AccessToken.php b/app/libs/oauth2/models/AccessToken.php index 2d3196a0..45d71dc9 100644 --- a/app/libs/oauth2/models/AccessToken.php +++ b/app/libs/oauth2/models/AccessToken.php @@ -95,4 +95,12 @@ class AccessToken extends Token { public function fromJSON($json){ } -} \ No newline at end of file + + /** + * @return string + */ + public function getType() + { + return 'access_token'; + } +} \ No newline at end of file diff --git a/app/libs/oauth2/models/AuthorizationCode.php b/app/libs/oauth2/models/AuthorizationCode.php index a01b66cb..0abf3567 100644 --- a/app/libs/oauth2/models/AuthorizationCode.php +++ b/app/libs/oauth2/models/AuthorizationCode.php @@ -300,4 +300,12 @@ class AuthorizationCode extends Token public function fromJSON($json) { } + + /** + * @return string + */ + public function getType() + { + return 'auth_code'; + } } \ No newline at end of file diff --git a/app/libs/oauth2/models/RefreshToken.php b/app/libs/oauth2/models/RefreshToken.php index 32907623..cab86d8e 100644 --- a/app/libs/oauth2/models/RefreshToken.php +++ b/app/libs/oauth2/models/RefreshToken.php @@ -70,4 +70,12 @@ class RefreshToken extends Token { { // TODO: Implement fromJSON() method. } + + /** + * @return string + */ + public function getType() + { + return 'refresh_token'; + } } \ No newline at end of file diff --git a/app/libs/openid/model/OpenIdNonce.php b/app/libs/openid/model/OpenIdNonce.php index 8e8ef59c..44afc284 100644 --- a/app/libs/openid/model/OpenIdNonce.php +++ b/app/libs/openid/model/OpenIdNonce.php @@ -106,4 +106,12 @@ final class OpenIdNonce extends Identifier return $nonce->setValue($value); } -} \ No newline at end of file + + /** + * @return string + */ + public function getType() + { + return 'nonce'; + } +} \ No newline at end of file diff --git a/app/libs/utils/model/Identifier.php b/app/libs/utils/model/Identifier.php index 1e1727bc..55b2a2cc 100644 --- a/app/libs/utils/model/Identifier.php +++ b/app/libs/utils/model/Identifier.php @@ -89,4 +89,9 @@ abstract class Identifier $this->value = $value; return $this; } + + /** + * @return string + */ + abstract public function getType(); } \ No newline at end of file diff --git a/app/libs/utils/services/UniqueIdentifierGenerator.php b/app/libs/utils/services/UniqueIdentifierGenerator.php index 8faa8779..eab6ad3d 100644 --- a/app/libs/utils/services/UniqueIdentifierGenerator.php +++ b/app/libs/utils/services/UniqueIdentifierGenerator.php @@ -15,6 +15,7 @@ namespace utils\services; use utils\model\Identifier; +use Zend\Crypt\Hash; /** * Class UniqueIdentifierGenerator @@ -42,11 +43,9 @@ abstract class UniqueIdentifierGenerator implements IdentifierGenerator */ public function generate(Identifier $identifier){ - $reflect = new \ReflectionClass($identifier); - $class_name = strtolower($reflect->getShortName()); do { - $key = sprintf("%s.value.%s", $class_name, $this->_generate($identifier)->getValue()); + $key = sprintf("%s.%s", $identifier->getType(), Hash::compute('sha256', $this->_generate($identifier)->getValue())); } while(!$this->cache_service->addSingleValue($key, $key)); return $identifier; diff --git a/app/routes.php b/app/routes.php index 654105c3..c2f6a3ad 100644 --- a/app/routes.php +++ b/app/routes.php @@ -156,7 +156,7 @@ Route::group(array('prefix' => 'admin/api/v1', 'before' => 'ssl|auth'), function }); - // resouce servers + // resource servers Route::group(array('prefix' => 'resource-servers', 'before' => 'oauth2.server.admin.json'), function () { Route::get('/{id}', "ApiResourceServerController@get"); Route::get('/', "ApiResourceServerController@getByPage"); diff --git a/app/tests/OIDCProtocolTest.php b/app/tests/OIDCProtocolTest.php index 94468a0a..d4bf5c75 100644 --- a/app/tests/OIDCProtocolTest.php +++ b/app/tests/OIDCProtocolTest.php @@ -88,7 +88,7 @@ class OIDCProtocolTest extends OpenStackIDBaseTest } - public function testLoginWithTralingSpace() + public function testLoginWithTrailingSpace() { $client_id = 'Jiz87D8/Vcvr6fvQbH4HyNgwTlfSyQ3x.openstack.client'; @@ -839,6 +839,120 @@ class OIDCProtocolTest extends OpenStackIDBaseTest } + public function testFlowNativeDisplay(){ + + $client_id = 'Jiz87D8/Vcvr6fvQbH4HyNgwTlfSyQ3x.openstack.client'; + $client_secret = 'ITc/6Y5N7kOtGKhgITc/6Y5N7kOtGKhgITc/6Y5N7kOtGKhgITc/6Y5N7kOtGKhg'; + + $params = array( + 'client_id' => $client_id, + 'redirect_uri' => 'https://www.test.com/oauth2', + 'response_type' => 'code', + 'scope' => sprintf('%s profile email address %s', OAuth2Protocol::OpenIdConnect_Scope, OAuth2Protocol::OfflineAccess_Scope), + OAuth2Protocol::OAuth2Protocol_LoginHint => 'sebastian@tipit.net', + OAuth2Protocol::OAuth2Protocol_Nonce => 'test_nonce', + OAuth2Protocol::OAuth2Protocol_Prompt => sprintf('%s %s',OAuth2Protocol::OAuth2Protocol_Prompt_Login, OAuth2Protocol::OAuth2Protocol_Prompt_Consent), + OAuth2Protocol::OAuth2Protocol_MaxAge => 3200, + OAuth2Protocol::OAuth2Protocol_Display => OAuth2Protocol::OAuth2Protocol_Display_Native + ); + + $response = $this->action("POST", "OAuth2ProviderController@authorize", + $params, + array(), + array(), + array()); + + $this->assertResponseStatus(302); + + $response = $this->call('GET', $response->getTargetUrl()); + + $this->assertResponseStatus(412); + + $json_response = json_decode($response->getContent(),true); + + // do login + $response = $this->call($json_response['method'], $json_response['url'], + array + ( + 'username' => 'sebastian@tipit.net', + 'password' => '1qaz2wsx', + '_token' => $json_response['required_params_valid_values']["_token"] + ) + ); + + $this->assertResponseStatus(302); + + $response = $this->action("GET", "OAuth2ProviderController@authorize", + array(), + array(), + array(), + array()); + + $this->assertResponseStatus(302); + + $response = $this->action('GET', 'UserController@getConsent'); + + $this->assertResponseStatus(412); + + $json_response = json_decode($response->getContent(),true); + + $response = $this->call($json_response['method'], $json_response['url'], array( + 'trust' => 'AllowOnce', + '_token' => $json_response['required_params_valid_values']["_token"] + )); + + $this->assertResponseStatus(302); + + // get auth code + + $response = $this->action("GET", "OAuth2ProviderController@authorize", + array(), + array(), + array(), + array()); + + $this->assertResponseStatus(302); + + $url = $response->getTargetUrl(); + + $comps = @parse_url($url); + $query = $comps['query']; + $output = array(); + parse_str($query, $output); + + $this->assertTrue(array_key_exists('code', $output)); + $this->assertTrue(!empty($output['code'])); + + $params = array( + 'code' => $output['code'], + 'redirect_uri' => 'https://www.test.com/oauth2', + 'grant_type' => OAuth2Protocol::OAuth2Protocol_GrantType_AuthCode, + ); + + $response = $this->action("POST", "OAuth2ProviderController@token", + $params, + array(), + array(), + // Symfony interally prefixes headers with "HTTP", so + array("HTTP_Authorization" => " Basic " . base64_encode($client_id . ':' . $client_secret))); + + + $this->assertResponseStatus(200); + + $this->assertEquals('application/json;charset=UTF-8', $response->headers->get('Content-Type')); + + $content = $response->getContent(); + + $response = json_decode($content); + $access_token = $response->access_token; + $refresh_token = $response->refresh_token; + $id_token = $response->id_token; + + $this->assertTrue(!empty($access_token)); + $this->assertTrue(!empty($refresh_token)); + $this->assertTrue(!empty($id_token)); + } + public function testGetRefreshTokenFromNativeAppNTimes($n=5) { $client_id = 'Jiz87D8/Vcvr6fvQbH4HyNgwKlfSyQ3x.android.openstack.client';