From 06654c4fa99364e441808486979c57c8932d934f Mon Sep 17 00:00:00 2001 From: Kalmer Kaurson Date: Thu, 28 Aug 2025 17:20:53 +0300 Subject: [PATCH 1/8] fix refresh access token when no refresh token --- CHANGELOG.md | 1 + src/BaseOAuth.php | 4 ++-- src/OAuthToken.php | 26 +++++++++++++++++++++ tests/BaseOAuthTest.php | 52 +++++++++++++++++++++++++++++++++++++++-- tests/TokenTest.php | 14 +++++++++++ 5 files changed, 93 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c187a24..db38cec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ Yii Framework 2 authclient extension Change Log 2.2.18 under development ------------------------ +- Bug #396: Fix `BaseOAuth` method - `refreshAccessToken` when no refresh token exists (kalmer) - Bug #393: Fix type for `BaseOAuth` property - `accessToken` (max-s-lab) diff --git a/src/BaseOAuth.php b/src/BaseOAuth.php index 45a2908..78dca28 100644 --- a/src/BaseOAuth.php +++ b/src/BaseOAuth.php @@ -7,9 +7,9 @@ namespace yii\authclient; +use Yii; use yii\base\Exception; use yii\base\InvalidArgumentException; -use Yii; use yii\helpers\Inflector; use yii\httpclient\Request; @@ -291,7 +291,7 @@ protected function restoreAccessToken() $token = $this->getState('token'); if (is_object($token)) { /** @var OAuthToken $token */ - if ($token->getIsExpired() && $this->autoRefreshAccessToken) { + if ($token->getIsExpired() && $this->autoRefreshAccessToken && $token->getHasRefreshToken()) { $token = $this->refreshAccessToken($token); } } diff --git a/src/OAuthToken.php b/src/OAuthToken.php index 2d4b34e..c0e1051 100644 --- a/src/OAuthToken.php +++ b/src/OAuthToken.php @@ -35,6 +35,10 @@ class OAuthToken extends BaseObject * @var string key in [[params]] array, which stores token secret key. */ public $tokenSecretParamKey = 'oauth_token_secret'; + /** + * @var string key in [[params]] array, which stores refresh token key. + */ + public $refreshTokenParamKey = 'refresh_token'; /** * @var int object creation timestamp. */ @@ -59,6 +63,9 @@ public function __construct(array $config = []) if (array_key_exists('tokenSecretParamKey', $config)) { $this->tokenSecretParamKey = ArrayHelper::remove($config, 'tokenSecretParamKey'); } + if (array_key_exists('refreshTokenParamKey', $config)) { + $this->refreshTokenParamKey = ArrayHelper::remove($config, 'refreshTokenParamKey'); + } parent::__construct($config); } @@ -224,4 +231,23 @@ public function getIsValid() return (!empty($token) && !$this->getIsExpired()); } + + public function getRefreshToken() + { + return $this->getParam($this->refreshTokenParamKey); + } + + /** + * Sets refresh token. + * @param string $refreshToken + */ + public function setRefreshToken($refreshToken) + { + $this->setParam($this->refreshTokenParamKey, $refreshToken); + } + + public function getHasRefreshToken() + { + return !!$this->getRefreshToken(); + } } diff --git a/tests/BaseOAuthTest.php b/tests/BaseOAuthTest.php index add36dd..93727cd 100644 --- a/tests/BaseOAuthTest.php +++ b/tests/BaseOAuthTest.php @@ -2,9 +2,9 @@ namespace yiiunit\extensions\authclient; -use yii\authclient\signature\PlainText; -use yii\authclient\OAuthToken; use yii\authclient\BaseOAuth; +use yii\authclient\OAuthToken; +use yii\authclient\signature\PlainText; use yii\httpclient\Client; use yii\httpclient\Request; use yii\httpclient\Response; @@ -267,6 +267,54 @@ public function sendRequestDataProvider() 'Client error' => [400, 'yii\\authclient\\ClientErrorResponseException'], 'Server error' => [500, 'yii\\authclient\\InvalidResponseException'], ]; + } + + public function testDoNotRestoreAccessTokenWithNoRefreshToken() + { + /** + * @var BaseOAuth|\PHPUnit_Framework_MockObject_MockObject + */ + $oauthClient = $this->getMockBuilder(BaseOAuth::class) + ->setMethods(['composeRequestCurlOptions', 'refreshAccessToken', 'applyAccessTokenToRequest', 'initUserAttributes', 'getState']) + ->getMock(); + + $oauthClient->expects($this->never()) + ->method('refreshAccessToken'); + + $accessToken = new OAuthToken(); + $accessToken->setExpireDuration(-100); + + $oauthClient->expects($this->once()) + ->method('getState') + ->willReturn($accessToken); + + $this->assertSame($accessToken, $oauthClient->getAccessToken()); + } + + public function testRestoreAccessTokenWithRefreshToken() + { + /** + * @var BaseOAuth|\PHPUnit_Framework_MockObject_MockObject + */ + $oauthClient = $this->getMockBuilder(BaseOAuth::class) + ->setMethods(['composeRequestCurlOptions', 'refreshAccessToken', 'applyAccessTokenToRequest', 'initUserAttributes', 'getState']) + ->getMock(); + + $oauthClient->expects($this->once()) + ->method('refreshAccessToken') + ->willReturn(new OAuthToken()); + + $accessToken = new OAuthToken([ + 'params' => [ + 'refresh_token' => 'test_refresh_token', + ], + ]); + $accessToken->setExpireDuration(-100); + + $oauthClient->expects($this->once()) + ->method('getState') + ->willReturn($accessToken); + $this->assertNotSame($accessToken, $oauthClient->getAccessToken()); } } diff --git a/tests/TokenTest.php b/tests/TokenTest.php index 949c693..c788742 100644 --- a/tests/TokenTest.php +++ b/tests/TokenTest.php @@ -2,6 +2,7 @@ namespace yiiunit\extensions\authclient; +use Yii; use yii\authclient\OAuthToken; class TokenTest extends TestCase @@ -11,6 +12,7 @@ public function testCreate() $config = [ 'tokenParamKey' => 'test_token_param_key', 'tokenSecretParamKey' => 'test_token_secret_param_key', + 'refreshTokenParamKey' => 'test_refresh_token_param_key', ]; $oauthToken = new OAuthToken($config); $this->assertTrue(is_object($oauthToken), 'Unable to create access token!'); @@ -27,6 +29,7 @@ public function testCreateWithIncorrectConfigOrder() 'tokenSecret' => 'tokenSecret', 'tokenParamKey' => 'test_token_param_key', 'tokenSecretParamKey' => 'test_token_secret_param_key', + 'refreshTokenParamKey' => 'test_refresh_token_param_key', ]; $oauthToken = new OAuthToken($config); $this->assertInternalType('object', $oauthToken, 'Unable to create access token!'); @@ -144,4 +147,15 @@ public function testGetIsValid() $oauthToken->createTimestamp = $oauthToken->createTimestamp - ($expireDuration + 1); $this->assertFalse($oauthToken->getIsValid(), 'Expired token is valid!'); } + + public function testHasRefreshToken() + { + $oauthToken = new OAuthToken([ + 'params' => [ + 'refresh_token' => 'test_refresh_token', + ], + ]); + + $this->assertTrue($oauthToken->getHasRefreshToken()); + } } From 3a998a43c9817a1f39e102af355a9b043f5186a6 Mon Sep 17 00:00:00 2001 From: Kalmer Date: Thu, 28 Aug 2025 18:14:22 +0300 Subject: [PATCH 2/8] update github build --- .github/workflows/build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 65c872d..b7e29fa 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -17,7 +17,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v5 - name: Install PHP uses: shivammathur/setup-php@v2 with: @@ -26,7 +26,7 @@ jobs: id: composer-cache run: echo "::set-output name=dir::$(composer config cache-files-dir)" - name: Cache composer dependencies - uses: actions/cache@v1 + uses: actions/cache@v4 with: path: ${{ steps.composer-cache.outputs.dir }} key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} From d60e7efcc21387adafaae0c2e34cce6fbba39050 Mon Sep 17 00:00:00 2001 From: Kalmer Kaurson Date: Fri, 29 Aug 2025 13:13:59 +0300 Subject: [PATCH 3/8] fix some test --- tests/OAuth1Test.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/OAuth1Test.php b/tests/OAuth1Test.php index 594d017..db503fc 100644 --- a/tests/OAuth1Test.php +++ b/tests/OAuth1Test.php @@ -3,8 +3,8 @@ namespace yiiunit\extensions\authclient; use yii\authclient\OAuth1; -use yii\authclient\signature\BaseMethod; use yii\authclient\OAuthToken; +use yii\authclient\signature\BaseMethod; class OAuth1Test extends TestCase { @@ -27,9 +27,11 @@ protected function setUp() */ protected function createClient() { - $oauthClient = $this->getMockBuilder(OAuth1::className()) + $oauthClient = $this->getMockBuilder(OAuth1::class) ->setMethods(['initUserAttributes']) ->getMock(); + $oauthClient->apiBaseUrl = 'https://www.google.com'; + return $oauthClient; } From 06fb91b18fca1bb38578a636b0ab214e1a7ac412 Mon Sep 17 00:00:00 2001 From: Kalmer Kaurson Date: Fri, 29 Aug 2025 13:19:15 +0300 Subject: [PATCH 4/8] stoneage compatibility --- tests/BaseOAuthTest.php | 4 ++-- tests/OAuth1Test.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/BaseOAuthTest.php b/tests/BaseOAuthTest.php index 93727cd..e34d7a5 100644 --- a/tests/BaseOAuthTest.php +++ b/tests/BaseOAuthTest.php @@ -274,7 +274,7 @@ public function testDoNotRestoreAccessTokenWithNoRefreshToken() /** * @var BaseOAuth|\PHPUnit_Framework_MockObject_MockObject */ - $oauthClient = $this->getMockBuilder(BaseOAuth::class) + $oauthClient = $this->getMockBuilder(BaseOAuth::className()) ->setMethods(['composeRequestCurlOptions', 'refreshAccessToken', 'applyAccessTokenToRequest', 'initUserAttributes', 'getState']) ->getMock(); @@ -296,7 +296,7 @@ public function testRestoreAccessTokenWithRefreshToken() /** * @var BaseOAuth|\PHPUnit_Framework_MockObject_MockObject */ - $oauthClient = $this->getMockBuilder(BaseOAuth::class) + $oauthClient = $this->getMockBuilder(BaseOAuth::className()) ->setMethods(['composeRequestCurlOptions', 'refreshAccessToken', 'applyAccessTokenToRequest', 'initUserAttributes', 'getState']) ->getMock(); diff --git a/tests/OAuth1Test.php b/tests/OAuth1Test.php index db503fc..9ded758 100644 --- a/tests/OAuth1Test.php +++ b/tests/OAuth1Test.php @@ -27,7 +27,7 @@ protected function setUp() */ protected function createClient() { - $oauthClient = $this->getMockBuilder(OAuth1::class) + $oauthClient = $this->getMockBuilder(OAuth1::className()) ->setMethods(['initUserAttributes']) ->getMock(); $oauthClient->apiBaseUrl = 'https://www.google.com'; From 39f126cdbbb5c800d641b36c2a245b039fb7f52e Mon Sep 17 00:00:00 2001 From: Alexander Makarov Date: Fri, 29 Aug 2025 16:46:52 +0300 Subject: [PATCH 5/8] Update changelog --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index db38cec..a8e3212 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,8 +4,8 @@ Yii Framework 2 authclient extension Change Log 2.2.18 under development ------------------------ -- Bug #396: Fix `BaseOAuth` method - `refreshAccessToken` when no refresh token exists (kalmer) -- Bug #393: Fix type for `BaseOAuth` property - `accessToken` (max-s-lab) +- Bug #396: Fix `BaseOAuth::refreshAccessToken()` when no refresh token exists (kalmer) +- Bug #393: Fix type for `BaseOAuth::$accessToken` (max-s-lab) 2.2.17 February 13, 2025 From f1d6cc9e182e3f4d7feadcfe2f0f6649152d4d76 Mon Sep 17 00:00:00 2001 From: kalmerkaurson <56919431+kalmerkaurson@users.noreply.github.com> Date: Mon, 1 Sep 2025 12:01:57 +0300 Subject: [PATCH 6/8] Update src/BaseOAuth.php Co-authored-by: Alexander Makarov --- src/BaseOAuth.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/BaseOAuth.php b/src/BaseOAuth.php index 78dca28..7c22c48 100644 --- a/src/BaseOAuth.php +++ b/src/BaseOAuth.php @@ -291,7 +291,7 @@ protected function restoreAccessToken() $token = $this->getState('token'); if (is_object($token)) { /** @var OAuthToken $token */ - if ($token->getIsExpired() && $this->autoRefreshAccessToken && $token->getHasRefreshToken()) { + if ($token->getIsExpired() && $this->autoRefreshAccessToken && $token->hasRefreshToken()) { $token = $this->refreshAccessToken($token); } } From 0b60cbd74928a2bb718838cfda1be6811c515fd1 Mon Sep 17 00:00:00 2001 From: kalmerkaurson <56919431+kalmerkaurson@users.noreply.github.com> Date: Mon, 1 Sep 2025 12:02:14 +0300 Subject: [PATCH 7/8] Update tests/TokenTest.php Co-authored-by: Alexander Makarov --- tests/TokenTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/TokenTest.php b/tests/TokenTest.php index c788742..326bbd9 100644 --- a/tests/TokenTest.php +++ b/tests/TokenTest.php @@ -156,6 +156,6 @@ public function testHasRefreshToken() ], ]); - $this->assertTrue($oauthToken->getHasRefreshToken()); + $this->assertTrue($oauthToken->hasRefreshToken()); } } From c5493c5dc0698a9bf4e62d0b6f426f7e2001ee34 Mon Sep 17 00:00:00 2001 From: kalmerkaurson <56919431+kalmerkaurson@users.noreply.github.com> Date: Mon, 1 Sep 2025 12:02:22 +0300 Subject: [PATCH 8/8] Update src/OAuthToken.php Co-authored-by: Alexander Makarov --- src/OAuthToken.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/OAuthToken.php b/src/OAuthToken.php index c0e1051..6514569 100644 --- a/src/OAuthToken.php +++ b/src/OAuthToken.php @@ -246,7 +246,7 @@ public function setRefreshToken($refreshToken) $this->setParam($this->refreshTokenParamKey, $refreshToken); } - public function getHasRefreshToken() + public function hasRefreshToken() { return !!$this->getRefreshToken(); }