Skip to content

Commit cc3a244

Browse files
bypass bc breaking change and add tests
1 parent 4998c4a commit cc3a244

File tree

4 files changed

+70
-6
lines changed

4 files changed

+70
-6
lines changed

src/Entities/ClientEntityInterface.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,9 @@ public function getRedirectUri(): string|array;
4040
public function isConfidential(): bool;
4141

4242
/**
43-
* Returns true if the client handles the given grant type.
43+
* Returns true if the client supports the given grant type.
44+
*
45+
* To be added in a future major release.
4446
*/
45-
public function hasGrantType(string $grantType): bool;
47+
// public function supportsGrantType(string $grantType): bool;
4648
}

src/Entities/Traits/ClientTrait.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,9 @@ public function isConfidential(): bool
5454
}
5555

5656
/**
57-
* Returns true if the client handles the given grant type.
57+
* Returns true if the client supports the given grant type.
5858
*/
59-
public function hasGrantType(string $grantType): bool
59+
public function supportsGrantType(string $grantType): bool
6060
{
6161
return true;
6262
}

src/Grant/AbstractGrant.php

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -189,13 +189,22 @@ protected function getClientEntityOrFail(string $clientId, ServerRequestInterfac
189189
throw OAuthServerException::invalidClient($request);
190190
}
191191

192-
if (!$client->hasGrantType($this->getIdentifier())) {
192+
if ($this->supportsGrantType($client, $this->getIdentifier()) === false) {
193193
throw OAuthServerException::unauthorizedClient();
194194
}
195195

196196
return $client;
197197
}
198198

199+
/**
200+
* Returns true if the given client is authorized to use the given grant type.
201+
*/
202+
protected function supportsGrantType(ClientEntityInterface $client, string $grantType): bool
203+
{
204+
return method_exists($client, 'supportsGrantType') === false
205+
|| $client->supportsGrantType($grantType) === true;
206+
}
207+
199208
/**
200209
* Gets the client credentials from the request from the request body or
201210
* the Http Basic Authorization header
@@ -488,7 +497,7 @@ protected function issueAuthCode(
488497
*/
489498
protected function issueRefreshToken(AccessTokenEntityInterface $accessToken): ?RefreshTokenEntityInterface
490499
{
491-
if (!$accessToken->getClient()->hasGrantType('refresh_token')) {
500+
if ($this->supportsGrantType($accessToken->getClient(), 'refresh_token') === false) {
492501
return null;
493502
}
494503

tests/Grant/AbstractGrantTest.php

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,32 @@ public function testValidateClientBadClient(): void
289289
$validateClientMethod->invoke($grantMock, $serverRequest, true);
290290
}
291291

292+
public function testUnauthorizedClient(): void
293+
{
294+
$client = $this->getMockBuilder(ClientEntity::class)->getMock();
295+
$client->method('supportsGrantType')->willReturn(false);
296+
297+
$clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
298+
$clientRepositoryMock
299+
->expects(self::once())
300+
->method('getClientEntity')
301+
->with('foo')
302+
->willReturn($client);
303+
304+
/** @var AbstractGrant $grantMock */
305+
$grantMock = $this->getMockForAbstractClass(AbstractGrant::class);
306+
$grantMock->setClientRepository($clientRepositoryMock);
307+
308+
$abstractGrantReflection = new ReflectionClass($grantMock);
309+
310+
$getClientEntityOrFailMethod = $abstractGrantReflection->getMethod('getClientEntityOrFail');
311+
$getClientEntityOrFailMethod->setAccessible(true);
312+
313+
$this->expectException(OAuthServerException::class);
314+
315+
$getClientEntityOrFailMethod->invoke($grantMock, 'foo', new ServerRequest());
316+
}
317+
292318
public function testCanRespondToRequest(): void
293319
{
294320
$grantMock = $this->getMockForAbstractClass(AbstractGrant::class);
@@ -350,6 +376,33 @@ public function testIssueNullRefreshToken(): void
350376
self::assertNull($issueRefreshTokenMethod->invoke($grantMock, $accessToken));
351377
}
352378

379+
public function testIssueNullRefreshTokenUnauthorizedClient(): void
380+
{
381+
$client = $this->getMockBuilder(ClientEntity::class)->getMock();
382+
$client
383+
->expects(self::once())
384+
->method('supportsGrantType')
385+
->with('refresh_token')
386+
->willReturn(false);
387+
388+
$refreshTokenRepoMock = $this->getMockBuilder(RefreshTokenRepositoryInterface::class)->getMock();
389+
$refreshTokenRepoMock->expects(self::never())->method('getNewRefreshToken');
390+
391+
/** @var AbstractGrant $grantMock */
392+
$grantMock = $this->getMockForAbstractClass(AbstractGrant::class);
393+
$grantMock->setRefreshTokenTTL(new DateInterval('PT1M'));
394+
$grantMock->setRefreshTokenRepository($refreshTokenRepoMock);
395+
396+
$abstractGrantReflection = new ReflectionClass($grantMock);
397+
$issueRefreshTokenMethod = $abstractGrantReflection->getMethod('issueRefreshToken');
398+
$issueRefreshTokenMethod->setAccessible(true);
399+
400+
$accessToken = new AccessTokenEntity();
401+
$accessToken->setClient($client);
402+
403+
self::assertNull($issueRefreshTokenMethod->invoke($grantMock, $accessToken));
404+
}
405+
353406
public function testIssueAccessToken(): void
354407
{
355408
$accessTokenRepoMock = $this->getMockBuilder(AccessTokenRepositoryInterface::class)->getMock();

0 commit comments

Comments
 (0)