From a148da2ecfb6bffdf7b63f56f0ce8b194fc4d89a Mon Sep 17 00:00:00 2001 From: ErickSkrauch Date: Mon, 23 Sep 2019 00:53:13 +0300 Subject: [PATCH] Add tests for the legacy tokens --- .../OAuth2/Grants/RefreshTokenGrant.php | 2 +- api/components/User/LegacyOAuth2Identity.php | 2 +- api/tests/functional.suite.dist.yml | 2 +- .../functional/oauth/RefreshTokenCest.php | 15 +++- .../components/User/IdentityFactoryTest.php | 32 +++----- .../User/LegacyOAuth2IdentityTest.php | 39 +++------ common/tests/_support/FixtureHelper.php | 4 + common/tests/_support/Redis/Fixture.php | 82 +++++++++++++++++++ .../LegacyOauthAccessTokenFixture.php | 14 ++++ .../LegacyOauthAccessTokenScopeFixture.php | 16 ++++ .../LegacyOauthRefreshTokenFixture.php | 14 ++++ .../LegacyOauthSessionScopeFixtures.php | 16 ++++ .../legacy-oauth-access-tokens-scopes.php | 4 + .../data/legacy-oauth-access-tokens.php | 16 ++++ .../data/legacy-oauth-refresh-tokens.php | 8 ++ .../data/legacy-oauth-sessions-scopes.php | 4 + common/tests/fixtures/data/oauth-sessions.php | 4 + 17 files changed, 222 insertions(+), 52 deletions(-) create mode 100644 common/tests/_support/Redis/Fixture.php create mode 100644 common/tests/fixtures/LegacyOauthAccessTokenFixture.php create mode 100644 common/tests/fixtures/LegacyOauthAccessTokenScopeFixture.php create mode 100644 common/tests/fixtures/LegacyOauthRefreshTokenFixture.php create mode 100644 common/tests/fixtures/LegacyOauthSessionScopeFixtures.php create mode 100644 common/tests/fixtures/data/legacy-oauth-access-tokens-scopes.php create mode 100644 common/tests/fixtures/data/legacy-oauth-access-tokens.php create mode 100644 common/tests/fixtures/data/legacy-oauth-refresh-tokens.php create mode 100644 common/tests/fixtures/data/legacy-oauth-sessions-scopes.php diff --git a/api/components/OAuth2/Grants/RefreshTokenGrant.php b/api/components/OAuth2/Grants/RefreshTokenGrant.php index b1ce1bf..53d7b12 100644 --- a/api/components/OAuth2/Grants/RefreshTokenGrant.php +++ b/api/components/OAuth2/Grants/RefreshTokenGrant.php @@ -14,7 +14,7 @@ use Yii; class RefreshTokenGrant extends BaseRefreshTokenGrant { /** - * Previously, refresh tokens was stored in Redis. + * Previously, refresh tokens were stored in Redis. * If received refresh token is matches the legacy token template, * restore the information from the legacy storage. * diff --git a/api/components/User/LegacyOAuth2Identity.php b/api/components/User/LegacyOAuth2Identity.php index 422a460..44b5023 100644 --- a/api/components/User/LegacyOAuth2Identity.php +++ b/api/components/User/LegacyOAuth2Identity.php @@ -32,7 +32,7 @@ class LegacyOAuth2Identity implements IdentityInterface { */ private $session = false; - private function __construct(string $accessToken, string $sessionId, array $scopes) { + private function __construct(string $accessToken, int $sessionId, array $scopes) { $this->accessToken = $accessToken; $this->sessionId = $sessionId; $this->scopes = $scopes; diff --git a/api/tests/functional.suite.dist.yml b/api/tests/functional.suite.dist.yml index 93e869e..c5ed796 100644 --- a/api/tests/functional.suite.dist.yml +++ b/api/tests/functional.suite.dist.yml @@ -17,4 +17,4 @@ modules: host: redis port: 6379 database: 0 - cleanupBefore: 'test' + cleanupBefore: 'suite' diff --git a/api/tests/functional/oauth/RefreshTokenCest.php b/api/tests/functional/oauth/RefreshTokenCest.php index dc5e291..edc68bb 100644 --- a/api/tests/functional/oauth/RefreshTokenCest.php +++ b/api/tests/functional/oauth/RefreshTokenCest.php @@ -4,6 +4,7 @@ declare(strict_types=1); namespace api\tests\functional\oauth; use api\tests\functional\_steps\OauthSteps; +use api\tests\FunctionalTester; class RefreshTokenCest { @@ -53,6 +54,18 @@ class RefreshTokenCest { $this->canSeeRefreshTokenSuccess($I); } + public function refreshTokenUsingLegacyToken(FunctionalTester $I) { + $I->wantTo('refresh token using the legacy token'); + $I->sendPOST('/api/oauth2/v1/token', [ + 'grant_type' => 'refresh_token', + 'refresh_token' => 'op7kPGAgHlsXRBJtkFg7wKOTpodvtHVW5NxR7Tjr', + 'client_id' => 'test1', + 'client_secret' => 'eEvrKHF47sqiaX94HsX-xXzdGiz3mcsq', + 'scope' => 'minecraft_server_session account_info', + ]); + $this->canSeeRefreshTokenSuccess($I); + } + public function passInvalidRefreshToken(OauthSteps $I) { $I->wantToTest('behaviour of the server when invalid refresh token passed'); $I->sendPOST('/api/oauth2/v1/token', [ @@ -85,7 +98,7 @@ class RefreshTokenCest { ]); } - private function canSeeRefreshTokenSuccess(OauthSteps $I) { + private function canSeeRefreshTokenSuccess(FunctionalTester $I) { $I->canSeeResponseCodeIs(200); $I->canSeeResponseContainsJson([ 'token_type' => 'Bearer', diff --git a/api/tests/unit/components/User/IdentityFactoryTest.php b/api/tests/unit/components/User/IdentityFactoryTest.php index 899f364..73bb6a4 100644 --- a/api/tests/unit/components/User/IdentityFactoryTest.php +++ b/api/tests/unit/components/User/IdentityFactoryTest.php @@ -3,40 +3,30 @@ declare(strict_types=1); namespace api\tests\unit\components\User; -use api\components\OAuth2\Component; -use api\components\OAuth2\Entities\AccessTokenEntity; use api\components\User\IdentityFactory; use api\components\User\JwtIdentity; use api\components\User\LegacyOAuth2Identity; use api\tests\unit\TestCase; use Carbon\Carbon; -use League\OAuth2\Server\AbstractServer; -use League\OAuth2\Server\Storage\AccessTokenInterface; -use Yii; +use common\tests\fixtures; use yii\web\UnauthorizedHttpException; class IdentityFactoryTest extends TestCase { + public function _fixtures(): array { + return [ + fixtures\LegacyOauthAccessTokenFixture::class, + fixtures\LegacyOauthAccessTokenScopeFixture::class, + ]; + } + public function testFindIdentityByAccessToken() { - // Find identity by jwt token + // Find identity by the JWT $identity = IdentityFactory::findIdentityByAccessToken('eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiJ9.eyJlbHktc2NvcGVzIjoiYWNjb3VudHNfd2ViX3VzZXIiLCJpYXQiOjE1NjQ2MTA1NDIsImV4cCI6MTU2NDYxNDE0Miwic3ViIjoiZWx5fDEifQ.4Oidvuo4spvUf9hkpHR72eeqZUh2Zbxh_L8Od3vcgTj--0iOrcOEp6zwmEW6vF7BTHtjz2b3mXce61bqsCjXjQ'); $this->assertInstanceOf(JwtIdentity::class, $identity); - // Find identity by oauth2 token - $accessToken = new AccessTokenEntity(mock(AbstractServer::class)); - $accessToken->setExpireTime(time() + 3600); - $accessToken->setId('mock-token'); - - /** @var AccessTokenInterface|\Mockery\MockInterface $accessTokensStorage */ - $accessTokensStorage = mock(AccessTokenInterface::class); - $accessTokensStorage->shouldReceive('get')->with('mock-token')->andReturn($accessToken); - - /** @var Component|\Mockery\MockInterface $component */ - $component = mock(Component::class); - $component->shouldReceive('getAccessTokenStorage')->andReturn($accessTokensStorage); - Yii::$app->set('oauth', $component); - - $identity = IdentityFactory::findIdentityByAccessToken('mock-token'); + // Find identity by the legacy OAuth2 token + $identity = IdentityFactory::findIdentityByAccessToken('ZZQP8sS9urzriy8N9h6FwFNMOH3PkZ5T5PLqS6SX'); $this->assertInstanceOf(LegacyOAuth2Identity::class, $identity); } diff --git a/api/tests/unit/components/User/LegacyOAuth2IdentityTest.php b/api/tests/unit/components/User/LegacyOAuth2IdentityTest.php index e19804d..9c37d29 100644 --- a/api/tests/unit/components/User/LegacyOAuth2IdentityTest.php +++ b/api/tests/unit/components/User/LegacyOAuth2IdentityTest.php @@ -3,52 +3,37 @@ declare(strict_types=1); namespace api\tests\unit\components\User; -use api\components\OAuth2\Component; -use api\components\OAuth2\Entities\AccessTokenEntity; use api\components\User\LegacyOAuth2Identity; use api\tests\unit\TestCase; -use Yii; +use common\tests\fixtures; use yii\web\UnauthorizedHttpException; class LegacyOAuth2IdentityTest extends TestCase { - public function testFindIdentityByAccessToken() { - $accessToken = new AccessTokenEntity(mock(AbstractServer::class)); - $accessToken->setExpireTime(time() + 3600); - $accessToken->setId('mock-token'); - $this->mockFoundedAccessToken($accessToken); + public function _fixtures(): array { + return [ + fixtures\LegacyOauthAccessTokenFixture::class, + fixtures\LegacyOauthAccessTokenScopeFixture::class, + ]; + } - $identity = LegacyOAuth2Identity::findIdentityByAccessToken('mock-token'); - $this->assertSame('mock-token', $identity->getId()); + public function testFindIdentityByAccessToken() { + $identity = LegacyOAuth2Identity::findIdentityByAccessToken('ZZQP8sS9urzriy8N9h6FwFNMOH3PkZ5T5PLqS6SX'); + $this->assertSame('ZZQP8sS9urzriy8N9h6FwFNMOH3PkZ5T5PLqS6SX', $identity->getId()); } public function testFindIdentityByAccessTokenWithNonExistsToken() { $this->expectException(UnauthorizedHttpException::class); $this->expectExceptionMessage('Incorrect token'); - LegacyOAuth2Identity::findIdentityByAccessToken('not exists token'); + LegacyOAuth2Identity::findIdentityByAccessToken('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'); } public function testFindIdentityByAccessTokenWithExpiredToken() { $this->expectException(UnauthorizedHttpException::class); $this->expectExceptionMessage('Token expired'); - $accessToken = new AccessTokenEntity(mock(AbstractServer::class)); - $accessToken->setExpireTime(time() - 3600); - $this->mockFoundedAccessToken($accessToken); - - LegacyOAuth2Identity::findIdentityByAccessToken('mock-token'); - } - - private function mockFoundedAccessToken(AccessTokenEntity $accessToken) { - /** @var AccessTokenInterface|\Mockery\MockInterface $accessTokensStorage */ - $accessTokensStorage = mock(AccessTokenInterface::class); - $accessTokensStorage->shouldReceive('get')->with('mock-token')->andReturn($accessToken); - - /** @var Component|\Mockery\MockInterface $component */ - $component = mock(Component::class); - $component->shouldReceive('getAccessTokenStorage')->andReturn($accessTokensStorage); - Yii::$app->set('oauth', $component); + LegacyOAuth2Identity::findIdentityByAccessToken('rc0sOF1SLdOxuD3bJcCQENmGTeYrGgy12qJScMx4'); } } diff --git a/common/tests/_support/FixtureHelper.php b/common/tests/_support/FixtureHelper.php index 7fb0d73..31b4070 100644 --- a/common/tests/_support/FixtureHelper.php +++ b/common/tests/_support/FixtureHelper.php @@ -52,7 +52,11 @@ class FixtureHelper extends Module { 'usernamesHistory' => fixtures\UsernameHistoryFixture::class, 'oauthClients' => fixtures\OauthClientFixture::class, 'oauthSessions' => fixtures\OauthSessionFixture::class, + 'legacyOauthSessionsScopes' => fixtures\LegacyOauthSessionScopeFixtures::class, + 'legacyOauthAccessTokens' => fixtures\LegacyOauthAccessTokenFixture::class, + 'legacyOauthAccessTokensScopes' => fixtures\LegacyOauthAccessTokenScopeFixture::class, 'oauthRefreshTokens' => fixtures\OauthRefreshTokensFixture::class, + 'legacyOauthRefreshTokens' => fixtures\LegacyOauthRefreshTokenFixture::class, 'minecraftAccessKeys' => fixtures\MinecraftAccessKeyFixture::class, ]; } diff --git a/common/tests/_support/Redis/Fixture.php b/common/tests/_support/Redis/Fixture.php new file mode 100644 index 0000000..e69cc75 --- /dev/null +++ b/common/tests/_support/Redis/Fixture.php @@ -0,0 +1,82 @@ +redis = Instance::ensure($this->redis, Connection::class); + } + + public function load() { + $this->data = []; + foreach ($this->getData() as $key => $data) { + $key = $this->buildKey($key); + $preparedData = $this->prepareData($data); + if (is_array($preparedData)) { + $this->redis->sadd($key, ...$preparedData); + } else { + $this->redis->set($key, $preparedData); + } + + $this->data[$key] = $data; + } + } + + public function unload() { + $this->redis->flushdb(); + } + + protected function getData(): array { + return $this->loadData($this->dataFile); + } + + protected function prepareData($input) { + if (is_string($input)) { + return $input; + } + + if (is_int($input) || is_bool($input)) { + return (string)$input; + } + + if (is_array($input)) { + if (!ArrayHelper::isAssociative($input)) { + return $input; + } + + return Json::encode($input); + } + + throw new InvalidArgumentException('Unsupported input type'); + } + + protected function buildKey($key): string { + return $this->keysPrefix . $key . $this->keysPostfix; + } + +} diff --git a/common/tests/fixtures/LegacyOauthAccessTokenFixture.php b/common/tests/fixtures/LegacyOauthAccessTokenFixture.php new file mode 100644 index 0000000..397ff71 --- /dev/null +++ b/common/tests/fixtures/LegacyOauthAccessTokenFixture.php @@ -0,0 +1,14 @@ + ['minecraft_server_session', 'obtain_own_account_info'], +]; diff --git a/common/tests/fixtures/data/legacy-oauth-access-tokens.php b/common/tests/fixtures/data/legacy-oauth-access-tokens.php new file mode 100644 index 0000000..dfa4445 --- /dev/null +++ b/common/tests/fixtures/data/legacy-oauth-access-tokens.php @@ -0,0 +1,16 @@ + [ + 'id' => 'ZZQP8sS9urzriy8N9h6FwFNMOH3PkZ5T5PLqS6SX', + 'session_id' => 1, + 'expire_time' => Carbon::now()->addHour()->getTimestamp(), + ], + 'rc0sOF1SLdOxuD3bJcCQENmGTeYrGgy12qJScMx4' => [ + 'id' => 'rc0sOF1SLdOxuD3bJcCQENmGTeYrGgy12qJScMx4', + 'session_id' => 1, + 'expire_time' => Carbon::now()->subHour()->getTimestamp(), + ], +]; diff --git a/common/tests/fixtures/data/legacy-oauth-refresh-tokens.php b/common/tests/fixtures/data/legacy-oauth-refresh-tokens.php new file mode 100644 index 0000000..1cd6ff4 --- /dev/null +++ b/common/tests/fixtures/data/legacy-oauth-refresh-tokens.php @@ -0,0 +1,8 @@ + [ + 'id' => 'op7kPGAgHlsXRBJtkFg7wKOTpodvtHVW5NxR7Tjr', + 'access_token_id' => 'cynbpR53GK5HyvHuTtriHP7JpdqvFaYnWSS1twXX', + 'session_id' => 1, + ], +]; diff --git a/common/tests/fixtures/data/legacy-oauth-sessions-scopes.php b/common/tests/fixtures/data/legacy-oauth-sessions-scopes.php new file mode 100644 index 0000000..510c92c --- /dev/null +++ b/common/tests/fixtures/data/legacy-oauth-sessions-scopes.php @@ -0,0 +1,4 @@ + ['minecraft_server_session', 'obtain_own_account_info'], +]; diff --git a/common/tests/fixtures/data/oauth-sessions.php b/common/tests/fixtures/data/oauth-sessions.php index 1075642..5828c20 100644 --- a/common/tests/fixtures/data/oauth-sessions.php +++ b/common/tests/fixtures/data/oauth-sessions.php @@ -3,24 +3,28 @@ return [ 'admin-test1' => [ 'account_id' => 1, 'client_id' => 'test1', + 'legacy_id' => 1, 'scopes' => null, 'created_at' => 1479944472, ], 'banned-account-session' => [ 'account_id' => 10, 'client_id' => 'test1', + 'legacy_id' => 2, 'scopes' => null, 'created_at' => 1481421663, ], 'deleted-client-session' => [ 'account_id' => 1, 'client_id' => 'deleted-oauth-client-with-sessions', + 'legacy_id' => 3, 'scopes' => null, 'created_at' => 1519510065, ], 'actual-deleted-client-session' => [ 'account_id' => 2, 'client_id' => 'deleted-oauth-client-with-sessions', + 'legacy_id' => 4, 'scopes' => null, 'created_at' => 1519511568, ],