Skip to content

Commit b8e1830

Browse files
authored
Merge pull request #1449 from hafezdivandari/fix-revoke-refresh-token
Fix issue and persist a new refresh token when revoking refresh token is disabled
2 parents 2c698e2 + c25b439 commit b8e1830

File tree

3 files changed

+26
-10
lines changed

3 files changed

+26
-10
lines changed

CHANGELOG.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
99
- Auto-generated event emitter is now persisted. Previously, a new emitter was generated every time (PR #1428)
1010
- Fixed bug where you could not omit a redirect uri even if one had not been specified during the auth request (PR #1428)
1111
- Fixed bug where "state" parameter wasn't present on `invalid_scope` error response and wasn't on fragment part of `access_denied` redirect URI on Implicit grant (PR #1298)
12-
12+
- Fixed bug where disabling refresh token revocation via `revokeRefreshTokens(false)` unintentionally disables issuing new refresh token (PR #1449)
13+
-
1314
## [9.0.0] - released 2024-05-13
1415
### Added
1516
- Device Authorization Grant added (PR #1074)

src/Grant/RefreshTokenGrant.php

+4-6
Original file line numberDiff line numberDiff line change
@@ -83,13 +83,11 @@ public function respondToAccessTokenRequest(
8383
$responseType->setAccessToken($accessToken);
8484

8585
// Issue and persist new refresh token if given
86-
if ($this->revokeRefreshTokens) {
87-
$refreshToken = $this->issueRefreshToken($accessToken);
86+
$refreshToken = $this->issueRefreshToken($accessToken);
8887

89-
if ($refreshToken !== null) {
90-
$this->getEmitter()->emit(new RequestRefreshTokenEvent(RequestEvent::REFRESH_TOKEN_ISSUED, $request, $refreshToken));
91-
$responseType->setRefreshToken($refreshToken);
92-
}
88+
if ($refreshToken !== null) {
89+
$this->getEmitter()->emit(new RequestRefreshTokenEvent(RequestEvent::REFRESH_TOKEN_ISSUED, $request, $refreshToken));
90+
$responseType->setRefreshToken($refreshToken);
9391
}
9492

9593
return $responseType;

tests/Grant/RefreshTokenGrantTest.php

+20-3
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace LeagueTests\Grant;
66

77
use DateInterval;
8+
use Laminas\Diactoros\Response;
89
use Laminas\Diactoros\ServerRequest;
910
use League\OAuth2\Server\CryptKey;
1011
use League\OAuth2\Server\Entities\RefreshTokenEntityInterface;
@@ -14,6 +15,7 @@
1415
use League\OAuth2\Server\Repositories\ClientRepositoryInterface;
1516
use League\OAuth2\Server\Repositories\RefreshTokenRepositoryInterface;
1617
use League\OAuth2\Server\Repositories\ScopeRepositoryInterface;
18+
use League\OAuth2\Server\ResponseTypes\BearerTokenResponse;
1719
use LeagueTests\Stubs\AccessTokenEntity;
1820
use LeagueTests\Stubs\ClientEntity;
1921
use LeagueTests\Stubs\CryptTraitStub;
@@ -688,11 +690,15 @@ public function testUnrevokedRefreshToken(): void
688690
$scopeRepositoryMock->method('getScopeEntityByIdentifier')->willReturn($scopeEntity);
689691
$scopeRepositoryMock->method('finalizeScopes')->willReturn([$scopeEntity]);
690692

693+
$accessTokenEntity = new AccessTokenEntity();
694+
$accessTokenEntity->setClient($client);
695+
691696
$accessTokenRepositoryMock = $this->getMockBuilder(AccessTokenRepositoryInterface::class)->getMock();
692-
$accessTokenRepositoryMock->method('getNewToken')->willReturn(new AccessTokenEntity());
697+
$accessTokenRepositoryMock->method('getNewToken')->willReturn($accessTokenEntity);
693698
$accessTokenRepositoryMock->expects(self::once())->method('persistNewAccessToken')->willReturnSelf();
694699

695700
$refreshTokenRepositoryMock = $this->getMockBuilder(RefreshTokenRepositoryInterface::class)->getMock();
701+
$refreshTokenRepositoryMock->method('getNewRefreshToken')->willReturn(new RefreshTokenEntity());
696702
$refreshTokenRepositoryMock->method('isRefreshTokenRevoked')->willReturn(false);
697703
$refreshTokenRepositoryMock->expects(self::never())->method('revokeRefreshToken');
698704

@@ -727,11 +733,22 @@ public function testUnrevokedRefreshToken(): void
727733
$grant->setScopeRepository($scopeRepositoryMock);
728734
$grant->setAccessTokenRepository($accessTokenRepositoryMock);
729735
$grant->setEncryptionKey($this->cryptStub->getKey());
730-
$grant->setPrivateKey(new CryptKey('file://' . __DIR__ . '/../Stubs/private.key'));
736+
$grant->setPrivateKey($privateKey = new CryptKey('file://' . __DIR__ . '/../Stubs/private.key'));
731737
$grant->revokeRefreshTokens(false);
732738

733-
$grant->respondToAccessTokenRequest($serverRequest, new StubResponseType(), new DateInterval('PT5M'));
739+
$responseType = new BearerTokenResponse();
740+
$responseType->setPrivateKey($privateKey);
741+
$responseType->setEncryptionKey($this->cryptStub->getKey());
742+
743+
$response = $grant->respondToAccessTokenRequest($serverRequest, $responseType, new DateInterval('PT5M'))
744+
->generateHttpResponse(new Response());
745+
746+
$json = json_decode((string) $response->getBody());
734747

735748
self::assertFalse($refreshTokenRepositoryMock->isRefreshTokenRevoked($refreshTokenId));
749+
self::assertEquals('Bearer', $json->token_type);
750+
self::assertObjectHasProperty('expires_in', $json);
751+
self::assertObjectHasProperty('access_token', $json);
752+
self::assertObjectHasProperty('refresh_token', $json);
736753
}
737754
}

0 commit comments

Comments
 (0)