diff --git a/app/database/seeds/TestSeeder.php b/app/database/seeds/TestSeeder.php index 207faf28..1144d90c 100644 --- a/app/database/seeds/TestSeeder.php +++ b/app/database/seeds/TestSeeder.php @@ -179,7 +179,9 @@ PPK; State varchar(64), Postcode varchar(64), Country varchar(2), - Gender varchar(32) + Gender varchar(32), + EmailVerified integer, + Active integer ); SQL; @@ -202,6 +204,8 @@ SQL; 'Postcode' => '1824', 'Country' => 'AR', 'Locale' => 'ESP', + 'Active' => 1, + 'EmailVerified' => 1, ) ); @@ -222,6 +226,8 @@ SQL; 'Postcode' => '1824', 'Country' => 'AR', 'Locale' => 'ESP', + 'Active' => 1, + 'EmailVerified' => 1, ) ); @@ -242,6 +248,8 @@ SQL; 'Postcode' => '1824', 'Country' => 'AR', 'Locale' => 'ESP', + 'Active' => 1, + 'EmailVerified' => 1, ) ); @@ -262,6 +270,8 @@ SQL; 'Postcode' => '1824', 'Country' => 'AR', 'Locale' => 'ESP', + 'Active' => 1, + 'EmailVerified' => 1, ) ); @@ -282,6 +292,8 @@ SQL; 'Postcode' => '1824', 'Country' => 'AR', 'Locale' => 'ESP', + 'Active' => 1, + 'EmailVerified' => 1, ) ); @@ -302,6 +314,8 @@ SQL; 'Postcode' => '1824', 'Country' => 'AR', 'Locale' => 'ESP', + 'Active' => 1, + 'EmailVerified' => 1, ) ); @@ -322,6 +336,8 @@ SQL; 'Postcode' => '1824', 'Country' => 'AR', 'Locale' => 'ESP', + 'Active' => 1, + 'EmailVerified' => 1, ) ); diff --git a/app/services/oauth2/TokenService.php b/app/services/oauth2/TokenService.php index aea58459..99aaf2ef 100644 --- a/app/services/oauth2/TokenService.php +++ b/app/services/oauth2/TokenService.php @@ -17,13 +17,14 @@ namespace services\oauth2; use AccessToken as DBAccessToken; use DB; use Event; +use Session; +use Crypt; +use Log; use libs\oauth2\exceptions\ReplayAttackAuthCodeException; use libs\oauth2\exceptions\ReplayAttackRefreshTokenException; use oauth2\exceptions\RevokedAccessTokenException; use oauth2\exceptions\RevokedAccessTokenExceptionxtends; use oauth2\exceptions\RevokedRefreshTokenException; -use Session; -use Crypt; use jwa\cryptographic_algorithms\HashFunctionAlgorithm; use jwt\IBasicJWT; use jwt\impl\JWTClaimSet; @@ -38,7 +39,6 @@ use oauth2\exceptions\InvalidClientCredentials; use oauth2\exceptions\InvalidGrantTypeException; use oauth2\exceptions\RecipientKeyNotFoundException; use oauth2\exceptions\ReplayAttackException; -use oauth2\heuristics\ClientEncryptionKeyFinder; use oauth2\heuristics\EncryptionClientPublicKeyFinder; use oauth2\heuristics\SigningClientPublicKeyFinder; use oauth2\models\AccessToken; @@ -449,6 +449,21 @@ final class TokenService implements ITokenService $access_token_db->save(); //check if use refresh tokens... + Log::debug + ( + sprintf + ( + 'use_refresh_token: %s - app_type: %s - scopes: %s - auth_code_access_type: %s - prompt: %s - approval_prompt: %s', + $client->use_refresh_token, + $client->getApplicationType(), + $auth_code->getScope(), + $auth_code->getAccessType(), + $auth_code->getPrompt(), + $auth_code->getApprovalPrompt() + + ) + ); + if ( $client->use_refresh_token && @@ -468,11 +483,12 @@ final class TokenService implements ITokenService ( !$auth_code->getHasPreviousUserConsent() || // google oauth2 protocol - $auth_code->getApprovalPrompt() == OAuth2Protocol::OAuth2Protocol_Approval_Prompt_Force || + strpos($auth_code->getApprovalPrompt(),OAuth2Protocol::OAuth2Protocol_Approval_Prompt_Force) !== false || // http://openid.net/specs/openid-connect-core-1_0.html#OfflineAccess - $auth_code->getPrompt() == OAuth2Protocol::OAuth2Protocol_Prompt_Consent + strpos($auth_code->getPrompt(), OAuth2Protocol::OAuth2Protocol_Prompt_Consent) !== false ) { + Log::debug('creating refresh token ....'); $this_var->createRefreshToken($access_token); } } @@ -1401,14 +1417,13 @@ final class TokenService implements ITokenService * @param string $nonce * @param string $client_id * @param AccessToken|null $access_token - * @param AuthorizationCode $auth_code + * @param AuthorizationCode|null $auth_code * @return IBasicJWT * @throws AbsentClientException + * @throws AbsentCurrentUserException + * @throws ConfigurationException * @throws InvalidClientCredentials - * @throws RecipientKeyNotFoundException * @throws \jwt\exceptions\ClaimAlreadyExistsException - * @throws \oauth2\exceptions\InvalidClientType - * @throws \oauth2\exceptions\ServerKeyNotFoundException */ public function createIdToken ( diff --git a/app/tests/OAuth2ProtocolTest.php b/app/tests/OAuth2ProtocolTest.php index 0e7dbb6f..bd57a3fd 100644 --- a/app/tests/OAuth2ProtocolTest.php +++ b/app/tests/OAuth2ProtocolTest.php @@ -224,7 +224,7 @@ class OAuth2ProtocolTest extends OpenStackIDBaseTest } - public function testTokenNTimes($n = 10000){ + public function testTokenNTimes($n = 100){ for($i=0; $i< $n ;$i++){ $this->testToken($i === 0); diff --git a/app/tests/OIDCProtocolTest.php b/app/tests/OIDCProtocolTest.php index 9d04678a..94468a0a 100644 --- a/app/tests/OIDCProtocolTest.php +++ b/app/tests/OIDCProtocolTest.php @@ -642,7 +642,6 @@ class OIDCProtocolTest extends OpenStackIDBaseTest 'grant_type' => OAuth2Protocol::OAuth2Protocol_GrantType_AuthCode, ); - $response = $this->action("POST", "OAuth2ProviderController@token", $params, array(), @@ -696,7 +695,151 @@ class OIDCProtocolTest extends OpenStackIDBaseTest return $access_token; } - public function testGetResfreshTokenFromNativeAppNTimes($n=5) + public function testGetRefreshTokenWithPromptSetToConsentLogin(){ + + $client_id = 'Jiz87D8/Vcvr6fvQbH4HyNgwTlfSyQ3x.openstack.client'; + $client_secret = 'ITc/6Y5N7kOtGKhgITc/6Y5N7kOtGKhgITc/6Y5N7kOtGKhgITc/6Y5N7kOtGKhg'; + $use_enc = true; + + $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 + ); + + $response = $this->action("POST", "OAuth2ProviderController@authorize", + $params, + array(), + array(), + array()); + + $this->assertResponseStatus(302); + + $url = $response->getTargetUrl(); + + $response = $this->call('GET', $url); + + $this->assertResponseStatus(200); + + // verify that login hint (email) is populated + $this->assertTrue(str_contains($response->getContent(), 'sebastian@tipit.net')); + + // do login + $response = $this->call('POST', $url, + array + ( + 'username' => 'sebastian@tipit.net', + 'password' => '1qaz2wsx', + '_token' => Session::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(200); + + $response = $this->action('POST', 'UserController@getConsent', array( + 'trust' => 'AllowOnce', + '_token' => Session::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)); + + $jwt = BasicJWTFactory::build($id_token); + + if ($use_enc) { + $this->assertTrue($jwt instanceof IJWE); + + $recipient_key = RSAJWKFactory::build + ( + new RSAJWKPEMPrivateKeySpecification + ( + TestSeeder::$client_private_key_1, + RSAJWKPEMPrivateKeySpecification::WithoutPassword, + $jwt->getJOSEHeader()->getAlgorithm()->getString() + ) + ); + + $recipient_key->setKeyUse(JSONWebKeyPublicKeyUseValues::Encryption)->setId('recipient_public_key'); + + + $jwt->setRecipientKey($recipient_key); + + $payload = $jwt->getPlainText(); + + $jwt = BasicJWTFactory::build($payload); + + $this->assertTrue($jwt instanceof IJWS); + } + + } + + public function testGetRefreshTokenFromNativeAppNTimes($n=5) { $client_id = 'Jiz87D8/Vcvr6fvQbH4HyNgwKlfSyQ3x.android.openstack.client'; $client_secret = '11c/6Y5N7kOtGKhg11c/6Y5N7kOtGKhg11c/6Y5N7kOtGKhg11c/6Y5N7kOtGKhgfdfdfdf'; diff --git a/app/tests/OpenIdProtocolTest.php b/app/tests/OpenIdProtocolTest.php index 1defef99..d02c85c6 100644 --- a/app/tests/OpenIdProtocolTest.php +++ b/app/tests/OpenIdProtocolTest.php @@ -400,7 +400,7 @@ class OpenIdProtocolTest extends OpenStackIDBaseTest $response = $this->action("POST", "OpenIdProviderController@endpoint", $params); - $this->assertResponseStatus(400); + $this->assertResponseStatus(404); } public function testAuthenticationCheckImmediateAuthenticationPrivateSession() diff --git a/app/views/oauth2/profile/clients.blade.php b/app/views/oauth2/profile/clients.blade.php index 8d1af508..7136eb70 100644 --- a/app/views/oauth2/profile/clients.blade.php +++ b/app/views/oauth2/profile/clients.blade.php @@ -6,6 +6,7 @@ @include('menu',array('is_oauth2_admin' => $is_oauth2_admin, 'is_openstackid_admin' => $is_openstackid_admin))
+
 Registered Applications @@ -60,9 +61,9 @@ @endif +
-