From c70451abd50aee741e668590f5c6fed641f8f534 Mon Sep 17 00:00:00 2001 From: Andrew Millington Date: Wed, 18 Oct 2017 22:08:11 +0100 Subject: [PATCH 01/34] Add an exception for a missing scope --- src/Exception/OAuthServerException.php | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/Exception/OAuthServerException.php b/src/Exception/OAuthServerException.php index 45e03c07..2258185f 100644 --- a/src/Exception/OAuthServerException.php +++ b/src/Exception/OAuthServerException.php @@ -195,6 +195,21 @@ class OAuthServerException extends \Exception ); } + /** + * Missing scope error + * + * @param null|string $redirectUri A HTTP URI to redirect the user back to + * + * @return static + */ + public static function missingScope($redirectUri = null) + { + $errorMessage = 'No scope was specified for this request'; + $hint = 'Set a default scope on the server if no scopes are passed in the request'; + + return new static($errorMessage, 11, 'missing_scope', 400, $hint, $redirectUri); + } + /** * @return string */ From c996b665285dffde76ac9452b1e7bc3e2dd55f22 Mon Sep 17 00:00:00 2001 From: Andrew Millington Date: Wed, 18 Oct 2017 22:08:41 +0100 Subject: [PATCH 02/34] Add means to set default scopes for grants --- src/Grant/AbstractGrant.php | 30 +++++++++++++++++++++------- src/Grant/AuthCodeGrant.php | 2 +- src/Grant/ClientCredentialsGrant.php | 6 +++--- src/Grant/GrantTypeInterface.php | 7 +++++++ src/Grant/ImplicitGrant.php | 6 +++--- src/Grant/PasswordGrant.php | 6 +++--- src/Grant/RefreshTokenGrant.php | 4 ++-- 7 files changed, 42 insertions(+), 19 deletions(-) diff --git a/src/Grant/AbstractGrant.php b/src/Grant/AbstractGrant.php index 3ac98cf4..b52b14cb 100644 --- a/src/Grant/AbstractGrant.php +++ b/src/Grant/AbstractGrant.php @@ -56,6 +56,11 @@ abstract class AbstractGrant implements GrantTypeInterface */ protected $scopeRepository; + /** + * @var string + */ + protected $defaultScope = ''; + /** * @var AuthCodeRepositoryInterface */ @@ -105,6 +110,14 @@ abstract class AbstractGrant implements GrantTypeInterface $this->scopeRepository = $scopeRepository; } + /** + * @param string $scope + */ + public function setDefaultScope($scope) + { + $this->defaultScope = $scope; + } + /** * @param RefreshTokenRepositoryInterface $refreshTokenRepository */ @@ -211,10 +224,8 @@ abstract class AbstractGrant implements GrantTypeInterface * * @return ScopeEntityInterface[] */ - public function validateScopes( - $scopes, - $redirectUri = null - ) { + public function validateScopes($scopes, $redirectUri = null) + { $scopesList = array_filter( explode(self::SCOPE_DELIMITER_STRING, trim($scopes)), function ($scope) { @@ -222,7 +233,8 @@ abstract class AbstractGrant implements GrantTypeInterface } ); - $scopes = []; + $validScopes = []; + foreach ($scopesList as $scopeItem) { $scope = $this->scopeRepository->getScopeEntityByIdentifier($scopeItem); @@ -230,10 +242,14 @@ abstract class AbstractGrant implements GrantTypeInterface throw OAuthServerException::invalidScope($scopeItem, $redirectUri); } - $scopes[] = $scope; + $validScopes[] = $scope; } - return $scopes; + if (empty($validScopes)) { + throw OAuthServerException::missingScope($redirectUri); + } + + return $validScopes; } /** diff --git a/src/Grant/AuthCodeGrant.php b/src/Grant/AuthCodeGrant.php index a138366f..a8528bb5 100644 --- a/src/Grant/AuthCodeGrant.php +++ b/src/Grant/AuthCodeGrant.php @@ -243,7 +243,7 @@ class AuthCodeGrant extends AbstractAuthorizeGrant } $scopes = $this->validateScopes( - $this->getQueryStringParameter('scope', $request), + $this->getQueryStringParameter('scope', $request, $this->defaultScope), is_array($client->getRedirectUri()) ? $client->getRedirectUri()[0] : $client->getRedirectUri() diff --git a/src/Grant/ClientCredentialsGrant.php b/src/Grant/ClientCredentialsGrant.php index b5b968d4..ed157aaf 100644 --- a/src/Grant/ClientCredentialsGrant.php +++ b/src/Grant/ClientCredentialsGrant.php @@ -29,13 +29,13 @@ class ClientCredentialsGrant extends AbstractGrant ) { // Validate request $client = $this->validateClient($request); - $scopes = $this->validateScopes($this->getRequestParameter('scope', $request)); + $scopes = $this->validateScopes($this->getRequestParameter('scope', $request, $this->defaultScope)); // Finalize the requested scopes - $scopes = $this->scopeRepository->finalizeScopes($scopes, $this->getIdentifier(), $client); + $finalizedScopes = $this->scopeRepository->finalizeScopes($scopes, $this->getIdentifier(), $client); // Issue and persist access token - $accessToken = $this->issueAccessToken($accessTokenTTL, $client, null, $scopes); + $accessToken = $this->issueAccessToken($accessTokenTTL, $client, null, $finalizedScopes); // Inject access token into response type $responseType->setAccessToken($accessToken); diff --git a/src/Grant/GrantTypeInterface.php b/src/Grant/GrantTypeInterface.php index 7aa98242..0e721435 100644 --- a/src/Grant/GrantTypeInterface.php +++ b/src/Grant/GrantTypeInterface.php @@ -119,6 +119,13 @@ interface GrantTypeInterface extends EmitterAwareInterface */ public function setScopeRepository(ScopeRepositoryInterface $scopeRepository); + /** + * Set the default scope. + * + * @param string $scope + */ + public function setDefaultScope($scope); + /** * Set the path to the private key. * diff --git a/src/Grant/ImplicitGrant.php b/src/Grant/ImplicitGrant.php index 466f32ce..9f000eb0 100644 --- a/src/Grant/ImplicitGrant.php +++ b/src/Grant/ImplicitGrant.php @@ -145,14 +145,14 @@ class ImplicitGrant extends AbstractAuthorizeGrant } $scopes = $this->validateScopes( - $this->getQueryStringParameter('scope', $request), + $this->getQueryStringParameter('scope', $request, $this->defaultScope), is_array($client->getRedirectUri()) ? $client->getRedirectUri()[0] : $client->getRedirectUri() ); // Finalize the requested scopes - $scopes = $this->scopeRepository->finalizeScopes( + $finalizedScopes = $this->scopeRepository->finalizeScopes( $scopes, $this->getIdentifier(), $client @@ -165,7 +165,7 @@ class ImplicitGrant extends AbstractAuthorizeGrant $authorizationRequest->setClient($client); $authorizationRequest->setRedirectUri($redirectUri); $authorizationRequest->setState($stateParameter); - $authorizationRequest->setScopes($scopes); + $authorizationRequest->setScopes($finalizedScopes); return $authorizationRequest; } diff --git a/src/Grant/PasswordGrant.php b/src/Grant/PasswordGrant.php index 31755613..cfd7e9fe 100644 --- a/src/Grant/PasswordGrant.php +++ b/src/Grant/PasswordGrant.php @@ -49,14 +49,14 @@ class PasswordGrant extends AbstractGrant ) { // Validate request $client = $this->validateClient($request); - $scopes = $this->validateScopes($this->getRequestParameter('scope', $request)); + $scopes = $this->validateScopes($this->getRequestParameter('scope', $request, $this->defaultScope)); $user = $this->validateUser($request, $client); // Finalize the requested scopes - $scopes = $this->scopeRepository->finalizeScopes($scopes, $this->getIdentifier(), $client, $user->getIdentifier()); + $finalizedScopes = $this->scopeRepository->finalizeScopes($scopes, $this->getIdentifier(), $client, $user->getIdentifier()); // Issue and persist new tokens - $accessToken = $this->issueAccessToken($accessTokenTTL, $client, $user->getIdentifier(), $scopes); + $accessToken = $this->issueAccessToken($accessTokenTTL, $client, $user->getIdentifier(), $finalizedScopes); $refreshToken = $this->issueRefreshToken($accessToken); // Inject tokens into response diff --git a/src/Grant/RefreshTokenGrant.php b/src/Grant/RefreshTokenGrant.php index 53dfdf7d..4fda5974 100644 --- a/src/Grant/RefreshTokenGrant.php +++ b/src/Grant/RefreshTokenGrant.php @@ -44,11 +44,11 @@ class RefreshTokenGrant extends AbstractGrant // Validate request $client = $this->validateClient($request); $oldRefreshToken = $this->validateOldRefreshToken($request, $client->getIdentifier()); - $scopes = $this->validateScopes($this->getRequestParameter('scope', $request)); + $scopes = $this->validateScopes($this->getRequestParameter('scope', $request, $this->defaultScope)); // If no new scopes are requested then give the access token the original session scopes if (count($scopes) === 0) { - $scopes = array_map(function ($scopeId) use ($client) { + $scopes = array_map(function ($scopeId) { $scope = $this->scopeRepository->getScopeEntityByIdentifier($scopeId); if ($scope instanceof ScopeEntityInterface === false) { From 5a28fb8af4503407de10c5b32f90c2a46ed87145 Mon Sep 17 00:00:00 2001 From: Andrew Millington Date: Wed, 18 Oct 2017 22:09:53 +0100 Subject: [PATCH 03/34] Set a default scope for the authorization server --- src/AuthorizationServer.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/AuthorizationServer.php b/src/AuthorizationServer.php index 46a9b27a..6da9c524 100644 --- a/src/AuthorizationServer.php +++ b/src/AuthorizationServer.php @@ -70,6 +70,11 @@ class AuthorizationServer implements EmitterAwareInterface */ private $encryptionKey; + /** + * @var string + */ + private $defaultScope; + /** * New server instance. * @@ -78,6 +83,7 @@ class AuthorizationServer implements EmitterAwareInterface * @param ScopeRepositoryInterface $scopeRepository * @param CryptKey|string $privateKey * @param string $encryptionKey + * @param null|string $defaultScope * @param null|ResponseTypeInterface $responseType */ public function __construct( @@ -86,6 +92,7 @@ class AuthorizationServer implements EmitterAwareInterface ScopeRepositoryInterface $scopeRepository, $privateKey, $encryptionKey, + $defaultScope = null, ResponseTypeInterface $responseType = null ) { $this->clientRepository = $clientRepository; @@ -97,6 +104,8 @@ class AuthorizationServer implements EmitterAwareInterface } $this->privateKey = $privateKey; + $this->defaultScope = $defaultScope; + $this->encryptionKey = $encryptionKey; $this->responseType = $responseType; } @@ -116,6 +125,7 @@ class AuthorizationServer implements EmitterAwareInterface $grantType->setAccessTokenRepository($this->accessTokenRepository); $grantType->setClientRepository($this->clientRepository); $grantType->setScopeRepository($this->scopeRepository); + $grantType->setDefaultScope($this->defaultScope); $grantType->setPrivateKey($this->privateKey); $grantType->setEmitter($this->getEmitter()); $grantType->setEncryptionKey($this->encryptionKey); From 4d28eadf932d8fc4747d8b69dc65142048b8e1cd Mon Sep 17 00:00:00 2001 From: Andrew Millington Date: Wed, 18 Oct 2017 22:11:02 +0100 Subject: [PATCH 04/34] Update tests so they don't trigger missing or invalid scope exceptions --- tests/Grant/AuthCodeGrantTest.php | 34 +++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/tests/Grant/AuthCodeGrantTest.php b/tests/Grant/AuthCodeGrantTest.php index 3bccba0a..025135c3 100644 --- a/tests/Grant/AuthCodeGrantTest.php +++ b/tests/Grant/AuthCodeGrantTest.php @@ -27,6 +27,9 @@ use Zend\Diactoros\ServerRequest; class AuthCodeGrantTest extends \PHPUnit_Framework_TestCase { + + const DEFAULT_SCOPE = 'default'; + /** * @var CryptTraitStub */ @@ -77,15 +80,22 @@ class AuthCodeGrantTest extends \PHPUnit_Framework_TestCase { $client = new ClientEntity(); $client->setRedirectUri('http://foo/bar'); + $clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock(); $clientRepositoryMock->method('getClientEntity')->willReturn($client); + $scope = new ScopeEntity(); + $scopeRepositoryMock = $this->getMockBuilder(ScopeRepositoryInterface::class)->getMock(); + $scopeRepositoryMock->method('getScopeEntityByIdentifier')->willReturn($scope); + $grant = new AuthCodeGrant( $this->getMockBuilder(AuthCodeRepositoryInterface::class)->getMock(), $this->getMockBuilder(RefreshTokenRepositoryInterface::class)->getMock(), new \DateInterval('PT10M') ); $grant->setClientRepository($clientRepositoryMock); + $grant->setScopeRepository($scopeRepositoryMock); + $grant->setDefaultScope(self::DEFAULT_SCOPE); $request = new ServerRequest( [], @@ -112,12 +122,18 @@ class AuthCodeGrantTest extends \PHPUnit_Framework_TestCase $clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock(); $clientRepositoryMock->method('getClientEntity')->willReturn($client); + $scope = new ScopeEntity(); + $scopeRepositoryMock = $this->getMockBuilder(ScopeRepositoryInterface::class)->getMock(); + $scopeRepositoryMock->method('getScopeEntityByIdentifier')->willReturn($scope); + $grant = new AuthCodeGrant( $this->getMockBuilder(AuthCodeRepositoryInterface::class)->getMock(), $this->getMockBuilder(RefreshTokenRepositoryInterface::class)->getMock(), new \DateInterval('PT10M') ); $grant->setClientRepository($clientRepositoryMock); + $grant->setScopeRepository($scopeRepositoryMock); + $grant->setDefaultScope(self::DEFAULT_SCOPE); $request = new ServerRequest( [], @@ -144,6 +160,10 @@ class AuthCodeGrantTest extends \PHPUnit_Framework_TestCase $clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock(); $clientRepositoryMock->method('getClientEntity')->willReturn($client); + $scope = new ScopeEntity(); + $scopeRepositoryMock = $this->getMockBuilder(ScopeRepositoryInterface::class)->getMock(); + $scopeRepositoryMock->method('getScopeEntityByIdentifier')->willReturn($scope); + $grant = new AuthCodeGrant( $this->getMockBuilder(AuthCodeRepositoryInterface::class)->getMock(), $this->getMockBuilder(RefreshTokenRepositoryInterface::class)->getMock(), @@ -151,6 +171,8 @@ class AuthCodeGrantTest extends \PHPUnit_Framework_TestCase ); $grant->enableCodeExchangeProof(); $grant->setClientRepository($clientRepositoryMock); + $grant->setScopeRepository($scopeRepositoryMock); + $grant->setDefaultScope(self::DEFAULT_SCOPE); $request = new ServerRequest( [], @@ -429,6 +451,10 @@ class AuthCodeGrantTest extends \PHPUnit_Framework_TestCase $clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock(); $clientRepositoryMock->method('getClientEntity')->willReturn($client); + $scope = new ScopeEntity(); + $scopeRepositoryMock = $this->getMockBuilder(ScopeRepositoryInterface::class)->getMock(); + $scopeRepositoryMock->method('getScopeEntityByIdentifier')->willReturn($scope); + $grant = new AuthCodeGrant( $this->getMockBuilder(AuthCodeRepositoryInterface::class)->getMock(), $this->getMockBuilder(RefreshTokenRepositoryInterface::class)->getMock(), @@ -436,6 +462,8 @@ class AuthCodeGrantTest extends \PHPUnit_Framework_TestCase ); $grant->enableCodeExchangeProof(); $grant->setClientRepository($clientRepositoryMock); + $grant->setScopeRepository($scopeRepositoryMock); + $grant->setDefaultScope(self::DEFAULT_SCOPE); $request = new ServerRequest( [], @@ -466,6 +494,10 @@ class AuthCodeGrantTest extends \PHPUnit_Framework_TestCase $clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock(); $clientRepositoryMock->method('getClientEntity')->willReturn($client); + $scope = new ScopeEntity(); + $scopeRepositoryMock = $this->getMockBuilder(ScopeRepositoryInterface::class)->getMock(); + $scopeRepositoryMock->method('getScopeEntityByIdentifier')->willReturn($scope); + $grant = new AuthCodeGrant( $this->getMockBuilder(AuthCodeRepositoryInterface::class)->getMock(), $this->getMockBuilder(RefreshTokenRepositoryInterface::class)->getMock(), @@ -473,6 +505,8 @@ class AuthCodeGrantTest extends \PHPUnit_Framework_TestCase ); $grant->enableCodeExchangeProof(); $grant->setClientRepository($clientRepositoryMock); + $grant->setScopeRepository($scopeRepositoryMock); + $grant->setDefaultScope(self::DEFAULT_SCOPE); $request = new ServerRequest( [], From 8c788e9fc8e5d6c152bce346e3ebeaae16568cb0 Mon Sep 17 00:00:00 2001 From: Andrew Millington Date: Wed, 18 Oct 2017 22:11:13 +0100 Subject: [PATCH 05/34] Update tests so they don't trigger missing or invalid scope exceptions --- tests/AuthorizationServerTest.php | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/tests/AuthorizationServerTest.php b/tests/AuthorizationServerTest.php index 91ca9e4b..15376c22 100644 --- a/tests/AuthorizationServerTest.php +++ b/tests/AuthorizationServerTest.php @@ -17,6 +17,7 @@ use League\OAuth2\Server\ResponseTypes\BearerTokenResponse; use LeagueTests\Stubs\AccessTokenEntity; use LeagueTests\Stubs\AuthCodeEntity; use LeagueTests\Stubs\ClientEntity; +use LeagueTests\Stubs\ScopeEntity; use LeagueTests\Stubs\StubResponseType; use LeagueTests\Stubs\UserEntity; use Psr\Http\Message\ResponseInterface; @@ -26,6 +27,9 @@ use Zend\Diactoros\ServerRequestFactory; class AuthorizationServerTest extends \PHPUnit_Framework_TestCase { + + const DEFAULT_SCOPE = 'basic '; + public function setUp() { // Make sure the keys have the correct permissions. @@ -41,6 +45,7 @@ class AuthorizationServerTest extends \PHPUnit_Framework_TestCase $this->getMockBuilder(ScopeRepositoryInterface::class)->getMock(), 'file://' . __DIR__ . '/Stubs/private.key', base64_encode(random_bytes(36)), + self::DEFAULT_SCOPE, new StubResponseType() ); @@ -59,7 +64,9 @@ class AuthorizationServerTest extends \PHPUnit_Framework_TestCase $clientRepository = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock(); $clientRepository->method('getClientEntity')->willReturn(new ClientEntity()); + $scope = new ScopeEntity(); $scopeRepositoryMock = $this->getMockBuilder(ScopeRepositoryInterface::class)->getMock(); + $scopeRepositoryMock->method('getScopeEntityByIdentifier')->willReturn($scope); $scopeRepositoryMock->method('finalizeScopes')->willReturnArgument(0); $accessTokenRepositoryMock = $this->getMockBuilder(AccessTokenRepositoryInterface::class)->getMock(); @@ -71,6 +78,7 @@ class AuthorizationServerTest extends \PHPUnit_Framework_TestCase $scopeRepositoryMock, 'file://' . __DIR__ . '/Stubs/private.key', base64_encode(random_bytes(36)), + self::DEFAULT_SCOPE, new StubResponseType() ); @@ -142,6 +150,10 @@ class AuthorizationServerTest extends \PHPUnit_Framework_TestCase $clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock(); $clientRepositoryMock->method('getClientEntity')->willReturn($client); + $scope = new ScopeEntity(); + $scopeRepositoryMock = $this->getMockBuilder(ScopeRepositoryInterface::class)->getMock(); + $scopeRepositoryMock->method('getScopeEntityByIdentifier')->willReturn($scope); + $grant = new AuthCodeGrant( $this->getMockBuilder(AuthCodeRepositoryInterface::class)->getMock(), $this->getMockBuilder(RefreshTokenRepositoryInterface::class)->getMock(), @@ -152,9 +164,10 @@ class AuthorizationServerTest extends \PHPUnit_Framework_TestCase $server = new AuthorizationServer( $clientRepositoryMock, $this->getMockBuilder(AccessTokenRepositoryInterface::class)->getMock(), - $this->getMockBuilder(ScopeRepositoryInterface::class)->getMock(), + $scopeRepositoryMock, 'file://' . __DIR__ . '/Stubs/private.key', - 'file://' . __DIR__ . '/Stubs/public.key' + 'file://' . __DIR__ . '/Stubs/public.key', + self::DEFAULT_SCOPE ); $server->enableGrantType($grant); From 24f29b6382fbe8e77bc6e34faddae52d1e8d69b7 Mon Sep 17 00:00:00 2001 From: Andrew Millington Date: Thu, 19 Oct 2017 22:37:19 +0100 Subject: [PATCH 06/34] Fix more tests to support default scope setting --- tests/Grant/ClientCredentialsGrantTest.php | 8 +++++++- tests/Grant/ImplicitGrantTest.php | 4 ++++ tests/Grant/PasswordGrantTest.php | 6 ++++++ tests/Grant/RefreshTokenGrantTest.php | 7 +++++++ 4 files changed, 24 insertions(+), 1 deletion(-) diff --git a/tests/Grant/ClientCredentialsGrantTest.php b/tests/Grant/ClientCredentialsGrantTest.php index a1665831..8ad7e2b7 100644 --- a/tests/Grant/ClientCredentialsGrantTest.php +++ b/tests/Grant/ClientCredentialsGrantTest.php @@ -9,11 +9,14 @@ use League\OAuth2\Server\Repositories\ClientRepositoryInterface; use League\OAuth2\Server\Repositories\ScopeRepositoryInterface; use LeagueTests\Stubs\AccessTokenEntity; use LeagueTests\Stubs\ClientEntity; +use LeagueTests\Stubs\ScopeEntity; use LeagueTests\Stubs\StubResponseType; use Zend\Diactoros\ServerRequest; class ClientCredentialsGrantTest extends \PHPUnit_Framework_TestCase { + const DEFAULT_SCOPE = 'basic'; + public function testGetIdentifier() { $grant = new ClientCredentialsGrant(); @@ -30,13 +33,16 @@ class ClientCredentialsGrantTest extends \PHPUnit_Framework_TestCase $accessTokenRepositoryMock->method('getNewToken')->willReturn(new AccessTokenEntity()); $accessTokenRepositoryMock->method('persistNewAccessToken')->willReturnSelf(); + $scope = new ScopeEntity(); $scopeRepositoryMock = $this->getMockBuilder(ScopeRepositoryInterface::class)->getMock(); + $scopeRepositoryMock->method('getScopeEntityByIdentifier')->willReturn($scope); $scopeRepositoryMock->method('finalizeScopes')->willReturnArgument(0); $grant = new ClientCredentialsGrant(); $grant->setClientRepository($clientRepositoryMock); $grant->setAccessTokenRepository($accessTokenRepositoryMock); $grant->setScopeRepository($scopeRepositoryMock); + $grant->setDefaultScope(self::DEFAULT_SCOPE); $serverRequest = new ServerRequest(); $serverRequest = $serverRequest->withParsedBody( @@ -51,4 +57,4 @@ class ClientCredentialsGrantTest extends \PHPUnit_Framework_TestCase $this->assertTrue($responseType->getAccessToken() instanceof AccessTokenEntityInterface); } -} +} \ No newline at end of file diff --git a/tests/Grant/ImplicitGrantTest.php b/tests/Grant/ImplicitGrantTest.php index 3bfe4b84..18cb04b8 100644 --- a/tests/Grant/ImplicitGrantTest.php +++ b/tests/Grant/ImplicitGrantTest.php @@ -22,6 +22,8 @@ use Zend\Diactoros\ServerRequest; class ImplicitGrantTest extends \PHPUnit_Framework_TestCase { + const DEFAULT_SCOPE = 'basic'; + /** * CryptTrait stub */ @@ -96,6 +98,7 @@ class ImplicitGrantTest extends \PHPUnit_Framework_TestCase $grant = new ImplicitGrant(new \DateInterval('PT10M')); $grant->setClientRepository($clientRepositoryMock); $grant->setScopeRepository($scopeRepositoryMock); + $grant->setDefaultScope(self::DEFAULT_SCOPE); $request = new ServerRequest( [], @@ -130,6 +133,7 @@ class ImplicitGrantTest extends \PHPUnit_Framework_TestCase $grant = new ImplicitGrant(new \DateInterval('PT10M')); $grant->setClientRepository($clientRepositoryMock); $grant->setScopeRepository($scopeRepositoryMock); + $grant->setDefaultScope(self::DEFAULT_SCOPE); $request = new ServerRequest( [], diff --git a/tests/Grant/PasswordGrantTest.php b/tests/Grant/PasswordGrantTest.php index b380bfb2..ae4b311d 100644 --- a/tests/Grant/PasswordGrantTest.php +++ b/tests/Grant/PasswordGrantTest.php @@ -13,12 +13,15 @@ use League\OAuth2\Server\Repositories\UserRepositoryInterface; use LeagueTests\Stubs\AccessTokenEntity; use LeagueTests\Stubs\ClientEntity; use LeagueTests\Stubs\RefreshTokenEntity; +use LeagueTests\Stubs\ScopeEntity; use LeagueTests\Stubs\StubResponseType; use LeagueTests\Stubs\UserEntity; use Zend\Diactoros\ServerRequest; class PasswordGrantTest extends \PHPUnit_Framework_TestCase { + const DEFAULT_SCOPE = 'basic'; + public function testGetIdentifier() { $userRepositoryMock = $this->getMockBuilder(UserRepositoryInterface::class)->getMock(); @@ -46,13 +49,16 @@ class PasswordGrantTest extends \PHPUnit_Framework_TestCase $refreshTokenRepositoryMock->method('persistNewRefreshToken')->willReturnSelf(); $refreshTokenRepositoryMock->method('getNewRefreshToken')->willReturn(new RefreshTokenEntity()); + $scope = new ScopeEntity(); $scopeRepositoryMock = $this->getMockBuilder(ScopeRepositoryInterface::class)->getMock(); + $scopeRepositoryMock->method('getScopeEntityByIdentifier')->willReturn($scope); $scopeRepositoryMock->method('finalizeScopes')->willReturnArgument(0); $grant = new PasswordGrant($userRepositoryMock, $refreshTokenRepositoryMock); $grant->setClientRepository($clientRepositoryMock); $grant->setAccessTokenRepository($accessTokenRepositoryMock); $grant->setScopeRepository($scopeRepositoryMock); + $grant->setDefaultScope(self::DEFAULT_SCOPE); $serverRequest = new ServerRequest(); $serverRequest = $serverRequest->withParsedBody( diff --git a/tests/Grant/RefreshTokenGrantTest.php b/tests/Grant/RefreshTokenGrantTest.php index 47d7ad17..514d4c62 100644 --- a/tests/Grant/RefreshTokenGrantTest.php +++ b/tests/Grant/RefreshTokenGrantTest.php @@ -20,6 +20,8 @@ use Zend\Diactoros\ServerRequest; class RefreshTokenGrantTest extends \PHPUnit_Framework_TestCase { + const DEFAULT_SCOPE = 'basic'; + /** * @var CryptTraitStub */ @@ -61,12 +63,17 @@ class RefreshTokenGrantTest extends \PHPUnit_Framework_TestCase ->expects($this->once()) ->method('persistNewRefreshToken')->willReturnSelf(); + $oldRefreshTokenCheckResult = ['scopes' => $scopeEntity->getIdentifier()]; + + $refreshTokenRepositoryMock->method('validateOldRefreshToken')->willReturn($oldRefreshTokenCheckResult); + $grant = new RefreshTokenGrant($refreshTokenRepositoryMock); $grant->setClientRepository($clientRepositoryMock); $grant->setScopeRepository($scopeRepositoryMock); $grant->setAccessTokenRepository($accessTokenRepositoryMock); $grant->setEncryptionKey($this->cryptStub->getKey()); $grant->setPrivateKey(new CryptKey('file://' . __DIR__ . '/../Stubs/private.key')); + $grant->setDefaultScope(self::DEFAULT_SCOPE); $oldRefreshToken = $this->cryptStub->doEncrypt( json_encode( From f9143b5163deb146def3400014a70a59312a69f6 Mon Sep 17 00:00:00 2001 From: Andrew Millington Date: Mon, 30 Oct 2017 23:26:11 +0000 Subject: [PATCH 07/34] Fix the refresh token grant test --- tests/Grant/RefreshTokenGrantTest.php | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/tests/Grant/RefreshTokenGrantTest.php b/tests/Grant/RefreshTokenGrantTest.php index 514d4c62..dbaf75d1 100644 --- a/tests/Grant/RefreshTokenGrantTest.php +++ b/tests/Grant/RefreshTokenGrantTest.php @@ -49,6 +49,7 @@ class RefreshTokenGrantTest extends \PHPUnit_Framework_TestCase $scopeRepositoryMock = $this->getMockBuilder(ScopeRepositoryInterface::class)->getMock(); $scopeEntity = new ScopeEntity(); + $scopeEntity->setIdentifier(self::DEFAULT_SCOPE); $scopeRepositoryMock->method('getScopeEntityByIdentifier')->willReturn($scopeEntity); $accessTokenRepositoryMock = $this->getMockBuilder(AccessTokenRepositoryInterface::class)->getMock(); @@ -63,10 +64,6 @@ class RefreshTokenGrantTest extends \PHPUnit_Framework_TestCase ->expects($this->once()) ->method('persistNewRefreshToken')->willReturnSelf(); - $oldRefreshTokenCheckResult = ['scopes' => $scopeEntity->getIdentifier()]; - - $refreshTokenRepositoryMock->method('validateOldRefreshToken')->willReturn($oldRefreshTokenCheckResult); - $grant = new RefreshTokenGrant($refreshTokenRepositoryMock); $grant->setClientRepository($clientRepositoryMock); $grant->setScopeRepository($scopeRepositoryMock); @@ -81,7 +78,7 @@ class RefreshTokenGrantTest extends \PHPUnit_Framework_TestCase 'client_id' => 'foo', 'refresh_token_id' => 'zyxwvu', 'access_token_id' => 'abcdef', - 'scopes' => ['foo'], + 'scopes' => [self::DEFAULT_SCOPE], 'user_id' => 123, 'expire_time' => time() + 3600, ] From 1161ceda0d2c31f5b0162558149d63a934168cc2 Mon Sep 17 00:00:00 2001 From: Andrew Millington Date: Mon, 30 Oct 2017 23:26:49 +0000 Subject: [PATCH 08/34] Fix the authorization server middleware test --- tests/Middleware/AuthorizationServerMiddlewareTest.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/Middleware/AuthorizationServerMiddlewareTest.php b/tests/Middleware/AuthorizationServerMiddlewareTest.php index 74dffbf7..b41774de 100644 --- a/tests/Middleware/AuthorizationServerMiddlewareTest.php +++ b/tests/Middleware/AuthorizationServerMiddlewareTest.php @@ -11,18 +11,24 @@ use League\OAuth2\Server\Repositories\ClientRepositoryInterface; use League\OAuth2\Server\Repositories\ScopeRepositoryInterface; use LeagueTests\Stubs\AccessTokenEntity; use LeagueTests\Stubs\ClientEntity; +use LeagueTests\Stubs\ScopeEntity; use LeagueTests\Stubs\StubResponseType; use Zend\Diactoros\Response; use Zend\Diactoros\ServerRequestFactory; class AuthorizationServerMiddlewareTest extends \PHPUnit_Framework_TestCase { + + const DEFAULT_SCOPE = 'basic'; + public function testValidResponse() { $clientRepository = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock(); $clientRepository->method('getClientEntity')->willReturn(new ClientEntity()); + $scope = new ScopeEntity(); $scopeRepositoryMock = $this->getMockBuilder(ScopeRepositoryInterface::class)->getMock(); + $scopeRepositoryMock->method('getScopeEntityByIdentifier')->willReturn($scope); $scopeRepositoryMock->method('finalizeScopes')->willReturnArgument(0); $accessRepositoryMock = $this->getMockBuilder(AccessTokenRepositoryInterface::class)->getMock(); @@ -34,6 +40,7 @@ class AuthorizationServerMiddlewareTest extends \PHPUnit_Framework_TestCase $scopeRepositoryMock, 'file://' . __DIR__ . '/../Stubs/private.key', base64_encode(random_bytes(36)), + self::DEFAULT_SCOPE, new StubResponseType() ); From a49f6ff80d2ed95914a04be237c844c817a974a8 Mon Sep 17 00:00:00 2001 From: Andrew Millington Date: Mon, 30 Oct 2017 23:36:19 +0000 Subject: [PATCH 09/34] Remove setting default scope in the constructor --- src/AuthorizationServer.php | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/AuthorizationServer.php b/src/AuthorizationServer.php index 6da9c524..805d1e73 100644 --- a/src/AuthorizationServer.php +++ b/src/AuthorizationServer.php @@ -73,7 +73,7 @@ class AuthorizationServer implements EmitterAwareInterface /** * @var string */ - private $defaultScope; + private $defaultScope = null; /** * New server instance. @@ -83,7 +83,6 @@ class AuthorizationServer implements EmitterAwareInterface * @param ScopeRepositoryInterface $scopeRepository * @param CryptKey|string $privateKey * @param string $encryptionKey - * @param null|string $defaultScope * @param null|ResponseTypeInterface $responseType */ public function __construct( @@ -92,7 +91,6 @@ class AuthorizationServer implements EmitterAwareInterface ScopeRepositoryInterface $scopeRepository, $privateKey, $encryptionKey, - $defaultScope = null, ResponseTypeInterface $responseType = null ) { $this->clientRepository = $clientRepository; @@ -103,9 +101,6 @@ class AuthorizationServer implements EmitterAwareInterface $privateKey = new CryptKey($privateKey); } $this->privateKey = $privateKey; - - $this->defaultScope = $defaultScope; - $this->encryptionKey = $encryptionKey; $this->responseType = $responseType; } From 3828f87b192885438febcf09c570dc56df630585 Mon Sep 17 00:00:00 2001 From: Andrew Millington Date: Mon, 30 Oct 2017 23:48:02 +0000 Subject: [PATCH 10/34] Fix tests as no longer set the default scope in the constructor Use new setDefaultScope() method instead. Also changed default scope to be a blank string instead of null --- src/AuthorizationServer.php | 12 +++++++++++- tests/AuthorizationServerTest.php | 8 ++++---- .../Middleware/AuthorizationServerMiddlewareTest.php | 2 +- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/src/AuthorizationServer.php b/src/AuthorizationServer.php index 805d1e73..1122749b 100644 --- a/src/AuthorizationServer.php +++ b/src/AuthorizationServer.php @@ -73,7 +73,7 @@ class AuthorizationServer implements EmitterAwareInterface /** * @var string */ - private $defaultScope = null; + private $defaultScope = ''; /** * New server instance. @@ -209,4 +209,14 @@ class AuthorizationServer implements EmitterAwareInterface return $this->responseType; } + + /** + * Set the default scope for the authorization server. + * + * @param string $defaultScope + */ + public function setDefaultScope($defaultScope) + { + $this->defaultScope = $defaultScope; + } } diff --git a/tests/AuthorizationServerTest.php b/tests/AuthorizationServerTest.php index 15376c22..594a7ca6 100644 --- a/tests/AuthorizationServerTest.php +++ b/tests/AuthorizationServerTest.php @@ -45,7 +45,6 @@ class AuthorizationServerTest extends \PHPUnit_Framework_TestCase $this->getMockBuilder(ScopeRepositoryInterface::class)->getMock(), 'file://' . __DIR__ . '/Stubs/private.key', base64_encode(random_bytes(36)), - self::DEFAULT_SCOPE, new StubResponseType() ); @@ -78,10 +77,10 @@ class AuthorizationServerTest extends \PHPUnit_Framework_TestCase $scopeRepositoryMock, 'file://' . __DIR__ . '/Stubs/private.key', base64_encode(random_bytes(36)), - self::DEFAULT_SCOPE, new StubResponseType() ); + $server->setDefaultScope(self::DEFAULT_SCOPE); $server->enableGrantType(new ClientCredentialsGrant(), new \DateInterval('PT1M')); $_POST['grant_type'] = 'client_credentials'; @@ -166,9 +165,10 @@ class AuthorizationServerTest extends \PHPUnit_Framework_TestCase $this->getMockBuilder(AccessTokenRepositoryInterface::class)->getMock(), $scopeRepositoryMock, 'file://' . __DIR__ . '/Stubs/private.key', - 'file://' . __DIR__ . '/Stubs/public.key', - self::DEFAULT_SCOPE + 'file://' . __DIR__ . '/Stubs/public.key' ); + + $server->setDefaultScope(self::DEFAULT_SCOPE); $server->enableGrantType($grant); $request = new ServerRequest( diff --git a/tests/Middleware/AuthorizationServerMiddlewareTest.php b/tests/Middleware/AuthorizationServerMiddlewareTest.php index b41774de..1556405a 100644 --- a/tests/Middleware/AuthorizationServerMiddlewareTest.php +++ b/tests/Middleware/AuthorizationServerMiddlewareTest.php @@ -40,10 +40,10 @@ class AuthorizationServerMiddlewareTest extends \PHPUnit_Framework_TestCase $scopeRepositoryMock, 'file://' . __DIR__ . '/../Stubs/private.key', base64_encode(random_bytes(36)), - self::DEFAULT_SCOPE, new StubResponseType() ); + $server->setDefaultScope(self::DEFAULT_SCOPE); $server->enableGrantType(new ClientCredentialsGrant()); $_POST['grant_type'] = 'client_credentials'; From d0619385b8852529e3a078513a192f7f021d39b3 Mon Sep 17 00:00:00 2001 From: Andrew Millington Date: Tue, 31 Oct 2017 21:00:14 +0000 Subject: [PATCH 11/34] Add a basic test to ensure we throw an exception when no scope is given --- tests/Grant/AbstractGrantTest.php | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tests/Grant/AbstractGrantTest.php b/tests/Grant/AbstractGrantTest.php index 542c78dc..11139bfb 100644 --- a/tests/Grant/AbstractGrantTest.php +++ b/tests/Grant/AbstractGrantTest.php @@ -459,6 +459,21 @@ class AbstractGrantTest extends \PHPUnit_Framework_TestCase $grantMock->validateScopes('basic '); } + /** + * @expectedException \League\OAuth2\Server\Exception\OAuthServerException + * @expectedExceptionCode 11 + */ + public function testValidateScopesMissingScope() + { + $scopeRepositoryMock = $this->getMockBuilder(ScopeRepositoryInterface::class)->getMock(); + $scopeRepositoryMock->method('getScopeEntityByIdentifier')->willReturn(null); + + $grantMock = $this->getMockForAbstractClass(AbstractGrant::class); + $grantMock->setScopeRepository($scopeRepositoryMock); + + $grantMock->validateScopes(''); + } + public function testGenerateUniqueIdentifier() { $grantMock = $this->getMockForAbstractClass(AbstractGrant::class); From b2fe909a71a2790d3f81404df431b30315ed5c88 Mon Sep 17 00:00:00 2001 From: Andrew Millington Date: Tue, 31 Oct 2017 22:58:07 +0000 Subject: [PATCH 12/34] Removed the missing scope exception as should be using invalid_scope --- src/Exception/OAuthServerException.php | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/src/Exception/OAuthServerException.php b/src/Exception/OAuthServerException.php index 2258185f..45e03c07 100644 --- a/src/Exception/OAuthServerException.php +++ b/src/Exception/OAuthServerException.php @@ -195,21 +195,6 @@ class OAuthServerException extends \Exception ); } - /** - * Missing scope error - * - * @param null|string $redirectUri A HTTP URI to redirect the user back to - * - * @return static - */ - public static function missingScope($redirectUri = null) - { - $errorMessage = 'No scope was specified for this request'; - $hint = 'Set a default scope on the server if no scopes are passed in the request'; - - return new static($errorMessage, 11, 'missing_scope', 400, $hint, $redirectUri); - } - /** * @return string */ From 4806eda45ae605bc5d58edd110c6a179576fa258 Mon Sep 17 00:00:00 2001 From: Andrew Millington Date: Tue, 31 Oct 2017 22:59:01 +0000 Subject: [PATCH 13/34] Change to throw invalid scope instead of missing scope exception --- src/Grant/AbstractGrant.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Grant/AbstractGrant.php b/src/Grant/AbstractGrant.php index b52b14cb..bbb9efc0 100644 --- a/src/Grant/AbstractGrant.php +++ b/src/Grant/AbstractGrant.php @@ -246,7 +246,7 @@ abstract class AbstractGrant implements GrantTypeInterface } if (empty($validScopes)) { - throw OAuthServerException::missingScope($redirectUri); + throw OAuthServerException::invalidScope($redirectUri); } return $validScopes; From bd2cdaf5da5ffbe1a2417bbb8126f8cfe03721de Mon Sep 17 00:00:00 2001 From: Andrew Millington Date: Tue, 31 Oct 2017 23:01:19 +0000 Subject: [PATCH 14/34] Change missing scope test to check for invalid_scope exception --- tests/Grant/AbstractGrantTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Grant/AbstractGrantTest.php b/tests/Grant/AbstractGrantTest.php index 11139bfb..83009716 100644 --- a/tests/Grant/AbstractGrantTest.php +++ b/tests/Grant/AbstractGrantTest.php @@ -461,7 +461,7 @@ class AbstractGrantTest extends \PHPUnit_Framework_TestCase /** * @expectedException \League\OAuth2\Server\Exception\OAuthServerException - * @expectedExceptionCode 11 + * @expectedExceptionCode 5 */ public function testValidateScopesMissingScope() { From ab760a805c36484bf8d522ae1ce7fda35c0ead99 Mon Sep 17 00:00:00 2001 From: Andrew Millington Date: Mon, 6 Nov 2017 21:19:07 +0000 Subject: [PATCH 15/34] Remove default scope from abstract grant This should be added to the AbstractAuthorizeGrant instead as it is only used for an authorization request --- src/Grant/AbstractGrant.php | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/Grant/AbstractGrant.php b/src/Grant/AbstractGrant.php index bbb9efc0..297bce2b 100644 --- a/src/Grant/AbstractGrant.php +++ b/src/Grant/AbstractGrant.php @@ -56,11 +56,6 @@ abstract class AbstractGrant implements GrantTypeInterface */ protected $scopeRepository; - /** - * @var string - */ - protected $defaultScope = ''; - /** * @var AuthCodeRepositoryInterface */ @@ -110,14 +105,6 @@ abstract class AbstractGrant implements GrantTypeInterface $this->scopeRepository = $scopeRepository; } - /** - * @param string $scope - */ - public function setDefaultScope($scope) - { - $this->defaultScope = $scope; - } - /** * @param RefreshTokenRepositoryInterface $refreshTokenRepository */ From 42ea0de9fb3ad310f6b47958269beb4c9bca6c07 Mon Sep 17 00:00:00 2001 From: Andrew Millington Date: Mon, 6 Nov 2017 21:19:38 +0000 Subject: [PATCH 16/34] Add default scope to the AbstractAuthorizeGrant --- src/Grant/AbstractAuthorizeGrant.php | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/Grant/AbstractAuthorizeGrant.php b/src/Grant/AbstractAuthorizeGrant.php index 7f05100c..6a8d7c07 100644 --- a/src/Grant/AbstractAuthorizeGrant.php +++ b/src/Grant/AbstractAuthorizeGrant.php @@ -13,6 +13,11 @@ namespace League\OAuth2\Server\Grant; abstract class AbstractAuthorizeGrant extends AbstractGrant { + /** + * @var string + */ + protected $defaultScope = ''; + /** * @param string $uri * @param array $params @@ -26,4 +31,12 @@ abstract class AbstractAuthorizeGrant extends AbstractGrant return $uri . http_build_query($params); } + + /** + * @param string $scope + */ + public function setDefaultScope($scope) + { + $this->defaultScope = $scope; + } } From 9cd86a9154e07a8a50cd5318f76de3f287b74929 Mon Sep 17 00:00:00 2001 From: Andrew Millington Date: Mon, 6 Nov 2017 21:21:14 +0000 Subject: [PATCH 17/34] Remove default scope for the ClientCredentialsGrant --- src/Grant/ClientCredentialsGrant.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Grant/ClientCredentialsGrant.php b/src/Grant/ClientCredentialsGrant.php index ed157aaf..2dce0e54 100644 --- a/src/Grant/ClientCredentialsGrant.php +++ b/src/Grant/ClientCredentialsGrant.php @@ -29,7 +29,7 @@ class ClientCredentialsGrant extends AbstractGrant ) { // Validate request $client = $this->validateClient($request); - $scopes = $this->validateScopes($this->getRequestParameter('scope', $request, $this->defaultScope)); + $scopes = $this->validateScopes($this->getRequestParameter('scope', $request)); // Finalize the requested scopes $finalizedScopes = $this->scopeRepository->finalizeScopes($scopes, $this->getIdentifier(), $client); From 82b81c7f6ff5e3edf829991493bc5c7b23a8fee4 Mon Sep 17 00:00:00 2001 From: Andrew Millington Date: Mon, 6 Nov 2017 21:22:09 +0000 Subject: [PATCH 18/34] Remove setDefaultScope function from the grant interface --- src/Grant/GrantTypeInterface.php | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/Grant/GrantTypeInterface.php b/src/Grant/GrantTypeInterface.php index 0e721435..7aa98242 100644 --- a/src/Grant/GrantTypeInterface.php +++ b/src/Grant/GrantTypeInterface.php @@ -119,13 +119,6 @@ interface GrantTypeInterface extends EmitterAwareInterface */ public function setScopeRepository(ScopeRepositoryInterface $scopeRepository); - /** - * Set the default scope. - * - * @param string $scope - */ - public function setDefaultScope($scope); - /** * Set the path to the private key. * From 093c7755fa7cd69198d60257caeba891a17103c0 Mon Sep 17 00:00:00 2001 From: Andrew Millington Date: Mon, 6 Nov 2017 21:23:14 +0000 Subject: [PATCH 19/34] Remove default scope from the Password Grant --- src/Grant/PasswordGrant.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Grant/PasswordGrant.php b/src/Grant/PasswordGrant.php index cfd7e9fe..0a0c80a7 100644 --- a/src/Grant/PasswordGrant.php +++ b/src/Grant/PasswordGrant.php @@ -49,7 +49,7 @@ class PasswordGrant extends AbstractGrant ) { // Validate request $client = $this->validateClient($request); - $scopes = $this->validateScopes($this->getRequestParameter('scope', $request, $this->defaultScope)); + $scopes = $this->validateScopes($this->getRequestParameter('scope', $request)); $user = $this->validateUser($request, $client); // Finalize the requested scopes From cc6eb63dd83c4b13b2dcb7b522e5f495cc20e3f3 Mon Sep 17 00:00:00 2001 From: Andrew Millington Date: Mon, 6 Nov 2017 21:23:52 +0000 Subject: [PATCH 20/34] Remove default scope from the Refresh Token Grant --- src/Grant/RefreshTokenGrant.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Grant/RefreshTokenGrant.php b/src/Grant/RefreshTokenGrant.php index 4fda5974..d03b4edb 100644 --- a/src/Grant/RefreshTokenGrant.php +++ b/src/Grant/RefreshTokenGrant.php @@ -44,7 +44,7 @@ class RefreshTokenGrant extends AbstractGrant // Validate request $client = $this->validateClient($request); $oldRefreshToken = $this->validateOldRefreshToken($request, $client->getIdentifier()); - $scopes = $this->validateScopes($this->getRequestParameter('scope', $request, $this->defaultScope)); + $scopes = $this->validateScopes($this->getRequestParameter('scope', $request)); // If no new scopes are requested then give the access token the original session scopes if (count($scopes) === 0) { From 0f080638641ad322a2e079170a8812f9dc21571a Mon Sep 17 00:00:00 2001 From: Andrew Millington Date: Mon, 6 Nov 2017 22:33:28 +0000 Subject: [PATCH 21/34] Fixed use of default scope so it is only for authorization requests --- src/AuthorizationServer.php | 6 ++- src/Grant/AbstractAuthorizeGrant.php | 15 ++++++++ src/Grant/AbstractGrant.php | 4 -- src/Grant/AuthCodeGrant.php | 12 ++++-- src/Grant/ImplicitGrant.php | 12 ++++-- tests/Grant/AbstractGrantTest.php | 15 -------- tests/Grant/AuthCodeGrantTest.php | 35 +++++++++++++++-- tests/Grant/ClientCredentialsGrantTest.php | 6 --- tests/Grant/ImplicitGrantTest.php | 38 +++++++++++++++++++ tests/Grant/PasswordGrantTest.php | 6 --- tests/Grant/RefreshTokenGrantTest.php | 6 +-- .../AuthorizationServerMiddlewareTest.php | 7 ---- 12 files changed, 109 insertions(+), 53 deletions(-) diff --git a/src/AuthorizationServer.php b/src/AuthorizationServer.php index 1122749b..f8674004 100644 --- a/src/AuthorizationServer.php +++ b/src/AuthorizationServer.php @@ -11,6 +11,7 @@ namespace League\OAuth2\Server; use League\Event\EmitterAwareInterface; use League\Event\EmitterAwareTrait; use League\OAuth2\Server\Exception\OAuthServerException; +use League\OAuth2\Server\Grant\AbstractAuthorizeGrant; use League\OAuth2\Server\Grant\GrantTypeInterface; use League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface; use League\OAuth2\Server\Repositories\ClientRepositoryInterface; @@ -120,11 +121,14 @@ class AuthorizationServer implements EmitterAwareInterface $grantType->setAccessTokenRepository($this->accessTokenRepository); $grantType->setClientRepository($this->clientRepository); $grantType->setScopeRepository($this->scopeRepository); - $grantType->setDefaultScope($this->defaultScope); $grantType->setPrivateKey($this->privateKey); $grantType->setEmitter($this->getEmitter()); $grantType->setEncryptionKey($this->encryptionKey); + if ($grantType instanceof AbstractAuthorizeGrant) { + $grantType->setDefaultScope($this->defaultScope); + } + $this->enabledGrantTypes[$grantType->getIdentifier()] = $grantType; $this->grantTypeAccessTokenTTL[$grantType->getIdentifier()] = $accessTokenTTL; } diff --git a/src/Grant/AbstractAuthorizeGrant.php b/src/Grant/AbstractAuthorizeGrant.php index 6a8d7c07..0362fa22 100644 --- a/src/Grant/AbstractAuthorizeGrant.php +++ b/src/Grant/AbstractAuthorizeGrant.php @@ -11,6 +11,8 @@ namespace League\OAuth2\Server\Grant; +use League\OAuth2\Server\Exception\OAuthServerException; + abstract class AbstractAuthorizeGrant extends AbstractGrant { /** @@ -39,4 +41,17 @@ abstract class AbstractAuthorizeGrant extends AbstractGrant { $this->defaultScope = $scope; } + + /** + * @param ScopeEntityInterface[] $requestedScopes + * @param string $redirectUri + * + * @throws OAuthServerException + */ + protected function checkScopesRequested($requestedScopes, $redirectUri = null) + { + if (empty($requestedScopes)) { + throw OAuthServerException::invalidScope($redirectUri); + } + } } diff --git a/src/Grant/AbstractGrant.php b/src/Grant/AbstractGrant.php index 297bce2b..b4f121da 100644 --- a/src/Grant/AbstractGrant.php +++ b/src/Grant/AbstractGrant.php @@ -232,10 +232,6 @@ abstract class AbstractGrant implements GrantTypeInterface $validScopes[] = $scope; } - if (empty($validScopes)) { - throw OAuthServerException::invalidScope($redirectUri); - } - return $validScopes; } diff --git a/src/Grant/AuthCodeGrant.php b/src/Grant/AuthCodeGrant.php index a8528bb5..e26b94aa 100644 --- a/src/Grant/AuthCodeGrant.php +++ b/src/Grant/AuthCodeGrant.php @@ -242,13 +242,19 @@ class AuthCodeGrant extends AbstractAuthorizeGrant } } + $redirectUri = is_array($client->getRedirectUri()) ? $client->getRedirectUri()[0] : $client->getRedirectUri(); + $scopes = $this->validateScopes( $this->getQueryStringParameter('scope', $request, $this->defaultScope), - is_array($client->getRedirectUri()) - ? $client->getRedirectUri()[0] - : $client->getRedirectUri() + $redirectUri ); + try { + $this->checkScopesRequested($scopes, $redirectUri); + } catch (OAuthServerException $ex) { + throw $ex; + } + $stateParameter = $this->getQueryStringParameter('state', $request); $authorizationRequest = new AuthorizationRequest(); diff --git a/src/Grant/ImplicitGrant.php b/src/Grant/ImplicitGrant.php index 9f000eb0..5e102f32 100644 --- a/src/Grant/ImplicitGrant.php +++ b/src/Grant/ImplicitGrant.php @@ -144,13 +144,19 @@ class ImplicitGrant extends AbstractAuthorizeGrant } } + $redirectUri = is_array($client->getRedirectUri()) ? $client->getRedirectUri()[0] : $client->getRedirectUri(); + $scopes = $this->validateScopes( $this->getQueryStringParameter('scope', $request, $this->defaultScope), - is_array($client->getRedirectUri()) - ? $client->getRedirectUri()[0] - : $client->getRedirectUri() + $redirectUri ); + try { + $this->checkScopesRequested($scopes, $redirectUri); + } catch (OAuthServerException $ex) { + throw $ex; + } + // Finalize the requested scopes $finalizedScopes = $this->scopeRepository->finalizeScopes( $scopes, diff --git a/tests/Grant/AbstractGrantTest.php b/tests/Grant/AbstractGrantTest.php index 83009716..542c78dc 100644 --- a/tests/Grant/AbstractGrantTest.php +++ b/tests/Grant/AbstractGrantTest.php @@ -459,21 +459,6 @@ class AbstractGrantTest extends \PHPUnit_Framework_TestCase $grantMock->validateScopes('basic '); } - /** - * @expectedException \League\OAuth2\Server\Exception\OAuthServerException - * @expectedExceptionCode 5 - */ - public function testValidateScopesMissingScope() - { - $scopeRepositoryMock = $this->getMockBuilder(ScopeRepositoryInterface::class)->getMock(); - $scopeRepositoryMock->method('getScopeEntityByIdentifier')->willReturn(null); - - $grantMock = $this->getMockForAbstractClass(AbstractGrant::class); - $grantMock->setScopeRepository($scopeRepositoryMock); - - $grantMock->validateScopes(''); - } - public function testGenerateUniqueIdentifier() { $grantMock = $this->getMockForAbstractClass(AbstractGrant::class); diff --git a/tests/Grant/AuthCodeGrantTest.php b/tests/Grant/AuthCodeGrantTest.php index 025135c3..0e85144f 100644 --- a/tests/Grant/AuthCodeGrantTest.php +++ b/tests/Grant/AuthCodeGrantTest.php @@ -1656,16 +1656,45 @@ class AuthCodeGrantTest extends \PHPUnit_Framework_TestCase } /** - * @expectedException \LogicException + * @expectedException \League\OAuth2\Server\Exception\OAuthServerException ++ * @expectedExceptionCode 5 */ - public function testCompleteAuthorizationRequestNoUser() + public function testValidateAuthorizationRequestFailsWithoutScope() { + $client = new ClientEntity(); + $client->setRedirectUri('http://foo/bar'); + + $clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock(); + $clientRepositoryMock->method('getClientEntity')->willReturn($client); + + $scope = new ScopeEntity(); + $scopeRepositoryMock = $this->getMockBuilder(ScopeRepositoryInterface::class)->getMock(); + $scopeRepositoryMock->method('getScopeEntityByIdentifier')->willReturn($scope); + $grant = new AuthCodeGrant( $this->getMockBuilder(AuthCodeRepositoryInterface::class)->getMock(), $this->getMockBuilder(RefreshTokenRepositoryInterface::class)->getMock(), new \DateInterval('PT10M') ); - $grant->completeAuthorizationRequest(new AuthorizationRequest()); + $grant->setClientRepository($clientRepositoryMock); + $grant->setScopeRepository($scopeRepositoryMock); + + $request = new ServerRequest( + [], + [], + null, + null, + 'php://input', + [], + [], + [ + 'response_type' => 'code', + 'client_id' => 'foo', + 'redirect_uri' => 'http://foo/bar', + ] + ); + + $this->assertTrue($grant->validateAuthorizationRequest($request) instanceof AuthorizationRequest); } } diff --git a/tests/Grant/ClientCredentialsGrantTest.php b/tests/Grant/ClientCredentialsGrantTest.php index 8ad7e2b7..299cf020 100644 --- a/tests/Grant/ClientCredentialsGrantTest.php +++ b/tests/Grant/ClientCredentialsGrantTest.php @@ -9,14 +9,11 @@ use League\OAuth2\Server\Repositories\ClientRepositoryInterface; use League\OAuth2\Server\Repositories\ScopeRepositoryInterface; use LeagueTests\Stubs\AccessTokenEntity; use LeagueTests\Stubs\ClientEntity; -use LeagueTests\Stubs\ScopeEntity; use LeagueTests\Stubs\StubResponseType; use Zend\Diactoros\ServerRequest; class ClientCredentialsGrantTest extends \PHPUnit_Framework_TestCase { - const DEFAULT_SCOPE = 'basic'; - public function testGetIdentifier() { $grant = new ClientCredentialsGrant(); @@ -33,16 +30,13 @@ class ClientCredentialsGrantTest extends \PHPUnit_Framework_TestCase $accessTokenRepositoryMock->method('getNewToken')->willReturn(new AccessTokenEntity()); $accessTokenRepositoryMock->method('persistNewAccessToken')->willReturnSelf(); - $scope = new ScopeEntity(); $scopeRepositoryMock = $this->getMockBuilder(ScopeRepositoryInterface::class)->getMock(); - $scopeRepositoryMock->method('getScopeEntityByIdentifier')->willReturn($scope); $scopeRepositoryMock->method('finalizeScopes')->willReturnArgument(0); $grant = new ClientCredentialsGrant(); $grant->setClientRepository($clientRepositoryMock); $grant->setAccessTokenRepository($accessTokenRepositoryMock); $grant->setScopeRepository($scopeRepositoryMock); - $grant->setDefaultScope(self::DEFAULT_SCOPE); $serverRequest = new ServerRequest(); $serverRequest = $serverRequest->withParsedBody( diff --git a/tests/Grant/ImplicitGrantTest.php b/tests/Grant/ImplicitGrantTest.php index 18cb04b8..5009c605 100644 --- a/tests/Grant/ImplicitGrantTest.php +++ b/tests/Grant/ImplicitGrantTest.php @@ -411,4 +411,42 @@ class ImplicitGrantTest extends \PHPUnit_Framework_TestCase $grant = new ImplicitGrant(new \DateInterval('PT10M')); $grant->completeAuthorizationRequest(new AuthorizationRequest()); } + + /** + * @expectedException \League\OAuth2\Server\Exception\OAuthServerException + * @expectedExceptionCode 5 + */ + public function testValidateAuthorizationRequestFailsWithoutScope() + { + $client = new ClientEntity(); + $client->setRedirectUri('http://foo/bar'); + $clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock(); + $clientRepositoryMock->method('getClientEntity')->willReturn($client); + + $scopeRepositoryMock = $this->getMockBuilder(ScopeRepositoryInterface::class)->getMock(); + $scopeEntity = new ScopeEntity(); + $scopeRepositoryMock->method('getScopeEntityByIdentifier')->willReturn($scopeEntity); + $scopeRepositoryMock->method('finalizeScopes')->willReturnArgument(0); + + $grant = new ImplicitGrant(new \DateInterval('PT10M')); + $grant->setClientRepository($clientRepositoryMock); + $grant->setScopeRepository($scopeRepositoryMock); + + $request = new ServerRequest( + [], + [], + null, + null, + 'php://input', + $headers = [], + $cookies = [], + $queryParams = [ + 'response_type' => 'code', + 'client_id' => 'foo', + 'redirect_uri' => 'http://foo/bar', + ] + ); + + $this->assertTrue($grant->validateAuthorizationRequest($request) instanceof AuthorizationRequest); + } } diff --git a/tests/Grant/PasswordGrantTest.php b/tests/Grant/PasswordGrantTest.php index ae4b311d..b380bfb2 100644 --- a/tests/Grant/PasswordGrantTest.php +++ b/tests/Grant/PasswordGrantTest.php @@ -13,15 +13,12 @@ use League\OAuth2\Server\Repositories\UserRepositoryInterface; use LeagueTests\Stubs\AccessTokenEntity; use LeagueTests\Stubs\ClientEntity; use LeagueTests\Stubs\RefreshTokenEntity; -use LeagueTests\Stubs\ScopeEntity; use LeagueTests\Stubs\StubResponseType; use LeagueTests\Stubs\UserEntity; use Zend\Diactoros\ServerRequest; class PasswordGrantTest extends \PHPUnit_Framework_TestCase { - const DEFAULT_SCOPE = 'basic'; - public function testGetIdentifier() { $userRepositoryMock = $this->getMockBuilder(UserRepositoryInterface::class)->getMock(); @@ -49,16 +46,13 @@ class PasswordGrantTest extends \PHPUnit_Framework_TestCase $refreshTokenRepositoryMock->method('persistNewRefreshToken')->willReturnSelf(); $refreshTokenRepositoryMock->method('getNewRefreshToken')->willReturn(new RefreshTokenEntity()); - $scope = new ScopeEntity(); $scopeRepositoryMock = $this->getMockBuilder(ScopeRepositoryInterface::class)->getMock(); - $scopeRepositoryMock->method('getScopeEntityByIdentifier')->willReturn($scope); $scopeRepositoryMock->method('finalizeScopes')->willReturnArgument(0); $grant = new PasswordGrant($userRepositoryMock, $refreshTokenRepositoryMock); $grant->setClientRepository($clientRepositoryMock); $grant->setAccessTokenRepository($accessTokenRepositoryMock); $grant->setScopeRepository($scopeRepositoryMock); - $grant->setDefaultScope(self::DEFAULT_SCOPE); $serverRequest = new ServerRequest(); $serverRequest = $serverRequest->withParsedBody( diff --git a/tests/Grant/RefreshTokenGrantTest.php b/tests/Grant/RefreshTokenGrantTest.php index dbaf75d1..47d7ad17 100644 --- a/tests/Grant/RefreshTokenGrantTest.php +++ b/tests/Grant/RefreshTokenGrantTest.php @@ -20,8 +20,6 @@ use Zend\Diactoros\ServerRequest; class RefreshTokenGrantTest extends \PHPUnit_Framework_TestCase { - const DEFAULT_SCOPE = 'basic'; - /** * @var CryptTraitStub */ @@ -49,7 +47,6 @@ class RefreshTokenGrantTest extends \PHPUnit_Framework_TestCase $scopeRepositoryMock = $this->getMockBuilder(ScopeRepositoryInterface::class)->getMock(); $scopeEntity = new ScopeEntity(); - $scopeEntity->setIdentifier(self::DEFAULT_SCOPE); $scopeRepositoryMock->method('getScopeEntityByIdentifier')->willReturn($scopeEntity); $accessTokenRepositoryMock = $this->getMockBuilder(AccessTokenRepositoryInterface::class)->getMock(); @@ -70,7 +67,6 @@ class RefreshTokenGrantTest extends \PHPUnit_Framework_TestCase $grant->setAccessTokenRepository($accessTokenRepositoryMock); $grant->setEncryptionKey($this->cryptStub->getKey()); $grant->setPrivateKey(new CryptKey('file://' . __DIR__ . '/../Stubs/private.key')); - $grant->setDefaultScope(self::DEFAULT_SCOPE); $oldRefreshToken = $this->cryptStub->doEncrypt( json_encode( @@ -78,7 +74,7 @@ class RefreshTokenGrantTest extends \PHPUnit_Framework_TestCase 'client_id' => 'foo', 'refresh_token_id' => 'zyxwvu', 'access_token_id' => 'abcdef', - 'scopes' => [self::DEFAULT_SCOPE], + 'scopes' => ['foo'], 'user_id' => 123, 'expire_time' => time() + 3600, ] diff --git a/tests/Middleware/AuthorizationServerMiddlewareTest.php b/tests/Middleware/AuthorizationServerMiddlewareTest.php index 1556405a..74dffbf7 100644 --- a/tests/Middleware/AuthorizationServerMiddlewareTest.php +++ b/tests/Middleware/AuthorizationServerMiddlewareTest.php @@ -11,24 +11,18 @@ use League\OAuth2\Server\Repositories\ClientRepositoryInterface; use League\OAuth2\Server\Repositories\ScopeRepositoryInterface; use LeagueTests\Stubs\AccessTokenEntity; use LeagueTests\Stubs\ClientEntity; -use LeagueTests\Stubs\ScopeEntity; use LeagueTests\Stubs\StubResponseType; use Zend\Diactoros\Response; use Zend\Diactoros\ServerRequestFactory; class AuthorizationServerMiddlewareTest extends \PHPUnit_Framework_TestCase { - - const DEFAULT_SCOPE = 'basic'; - public function testValidResponse() { $clientRepository = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock(); $clientRepository->method('getClientEntity')->willReturn(new ClientEntity()); - $scope = new ScopeEntity(); $scopeRepositoryMock = $this->getMockBuilder(ScopeRepositoryInterface::class)->getMock(); - $scopeRepositoryMock->method('getScopeEntityByIdentifier')->willReturn($scope); $scopeRepositoryMock->method('finalizeScopes')->willReturnArgument(0); $accessRepositoryMock = $this->getMockBuilder(AccessTokenRepositoryInterface::class)->getMock(); @@ -43,7 +37,6 @@ class AuthorizationServerMiddlewareTest extends \PHPUnit_Framework_TestCase new StubResponseType() ); - $server->setDefaultScope(self::DEFAULT_SCOPE); $server->enableGrantType(new ClientCredentialsGrant()); $_POST['grant_type'] = 'client_credentials'; From 13be5578253e0d549c6a76b4c2481441825e4358 Mon Sep 17 00:00:00 2001 From: Andrew Millington Date: Mon, 6 Nov 2017 22:51:11 +0000 Subject: [PATCH 22/34] Re-add the complete testCompleteAuthorizationRequestNoUser() --- tests/Grant/AuthCodeGrantTest.php | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tests/Grant/AuthCodeGrantTest.php b/tests/Grant/AuthCodeGrantTest.php index 0e85144f..395d1ace 100644 --- a/tests/Grant/AuthCodeGrantTest.php +++ b/tests/Grant/AuthCodeGrantTest.php @@ -1655,6 +1655,20 @@ class AuthCodeGrantTest extends \PHPUnit_Framework_TestCase $this->assertTrue($response->getRefreshToken() instanceof RefreshTokenEntityInterface); } + /** + * @expectedException \LogicException + */ + public function testCompleteAuthorizationRequestNoUser() + { + $grant = new AuthCodeGrant( + $this->getMockBuilder(AuthCodeRepositoryInterface::class)->getMock(), + $this->getMockBuilder(RefreshTokenRepositoryInterface::class)->getMock(), + new \DateInterval('PT10M') + ); + + $grant->completeAuthorizationRequest(new AuthorizationRequest()); + } + /** * @expectedException \League\OAuth2\Server\Exception\OAuthServerException + * @expectedExceptionCode 5 From ce8248c10f56115fed3b8445a45fc09460e1c3c6 Mon Sep 17 00:00:00 2001 From: Andrew Millington Date: Mon, 6 Nov 2017 22:56:54 +0000 Subject: [PATCH 23/34] Remove erroneous character --- tests/Grant/AuthCodeGrantTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Grant/AuthCodeGrantTest.php b/tests/Grant/AuthCodeGrantTest.php index 395d1ace..ebfd4878 100644 --- a/tests/Grant/AuthCodeGrantTest.php +++ b/tests/Grant/AuthCodeGrantTest.php @@ -1671,7 +1671,7 @@ class AuthCodeGrantTest extends \PHPUnit_Framework_TestCase /** * @expectedException \League\OAuth2\Server\Exception\OAuthServerException -+ * @expectedExceptionCode 5 + * @expectedExceptionCode 5 */ public function testValidateAuthorizationRequestFailsWithoutScope() { From c895885700e0648e723136412a40cf2a8bb0f8b2 Mon Sep 17 00:00:00 2001 From: Sephster Date: Mon, 13 Nov 2017 22:19:44 +0000 Subject: [PATCH 24/34] Modify grants so only auth requests use default scopes --- src/Grant/AbstractAuthorizeGrant.php | 21 ------------------- src/Grant/AbstractGrant.php | 26 +++++++++++++++++------ src/Grant/AuthCodeGrant.php | 12 +++-------- src/Grant/ClientCredentialsGrant.php | 2 +- src/Grant/GrantTypeInterface.php | 7 +++++++ src/Grant/ImplicitGrant.php | 12 +++-------- src/Grant/PasswordGrant.php | 2 +- src/Grant/RefreshTokenGrant.php | 31 +++++++++------------------- 8 files changed, 45 insertions(+), 68 deletions(-) diff --git a/src/Grant/AbstractAuthorizeGrant.php b/src/Grant/AbstractAuthorizeGrant.php index 0362fa22..0ef8a8b0 100644 --- a/src/Grant/AbstractAuthorizeGrant.php +++ b/src/Grant/AbstractAuthorizeGrant.php @@ -33,25 +33,4 @@ abstract class AbstractAuthorizeGrant extends AbstractGrant return $uri . http_build_query($params); } - - /** - * @param string $scope - */ - public function setDefaultScope($scope) - { - $this->defaultScope = $scope; - } - - /** - * @param ScopeEntityInterface[] $requestedScopes - * @param string $redirectUri - * - * @throws OAuthServerException - */ - protected function checkScopesRequested($requestedScopes, $redirectUri = null) - { - if (empty($requestedScopes)) { - throw OAuthServerException::invalidScope($redirectUri); - } - } } diff --git a/src/Grant/AbstractGrant.php b/src/Grant/AbstractGrant.php index b4f121da..419631a4 100644 --- a/src/Grant/AbstractGrant.php +++ b/src/Grant/AbstractGrant.php @@ -81,6 +81,11 @@ abstract class AbstractGrant implements GrantTypeInterface */ protected $privateKey; + /** + * @string + */ + protected $defaultScope; + /** * @param ClientRepositoryInterface $clientRepository */ @@ -147,6 +152,14 @@ abstract class AbstractGrant implements GrantTypeInterface $this->privateKey = $key; } + /** + * @param string $scope + */ + public function setDefaultScope($scope) + { + $this->defaultScope = $scope; + } + /** * Validate the client. * @@ -213,12 +226,9 @@ abstract class AbstractGrant implements GrantTypeInterface */ public function validateScopes($scopes, $redirectUri = null) { - $scopesList = array_filter( - explode(self::SCOPE_DELIMITER_STRING, trim($scopes)), - function ($scope) { - return !empty($scope); - } - ); + $scopesList = array_filter(explode(self::SCOPE_DELIMITER_STRING, trim($scopes)), function ($scope) { + return !empty($scope); + }); $validScopes = []; @@ -232,6 +242,10 @@ abstract class AbstractGrant implements GrantTypeInterface $validScopes[] = $scope; } + if (empty($validScopes)) { + throw OAuthServerException::invalidScope($redirectUri); + } + return $validScopes; } diff --git a/src/Grant/AuthCodeGrant.php b/src/Grant/AuthCodeGrant.php index e26b94aa..a8528bb5 100644 --- a/src/Grant/AuthCodeGrant.php +++ b/src/Grant/AuthCodeGrant.php @@ -242,19 +242,13 @@ class AuthCodeGrant extends AbstractAuthorizeGrant } } - $redirectUri = is_array($client->getRedirectUri()) ? $client->getRedirectUri()[0] : $client->getRedirectUri(); - $scopes = $this->validateScopes( $this->getQueryStringParameter('scope', $request, $this->defaultScope), - $redirectUri + is_array($client->getRedirectUri()) + ? $client->getRedirectUri()[0] + : $client->getRedirectUri() ); - try { - $this->checkScopesRequested($scopes, $redirectUri); - } catch (OAuthServerException $ex) { - throw $ex; - } - $stateParameter = $this->getQueryStringParameter('state', $request); $authorizationRequest = new AuthorizationRequest(); diff --git a/src/Grant/ClientCredentialsGrant.php b/src/Grant/ClientCredentialsGrant.php index 2dce0e54..ed157aaf 100644 --- a/src/Grant/ClientCredentialsGrant.php +++ b/src/Grant/ClientCredentialsGrant.php @@ -29,7 +29,7 @@ class ClientCredentialsGrant extends AbstractGrant ) { // Validate request $client = $this->validateClient($request); - $scopes = $this->validateScopes($this->getRequestParameter('scope', $request)); + $scopes = $this->validateScopes($this->getRequestParameter('scope', $request, $this->defaultScope)); // Finalize the requested scopes $finalizedScopes = $this->scopeRepository->finalizeScopes($scopes, $this->getIdentifier(), $client); diff --git a/src/Grant/GrantTypeInterface.php b/src/Grant/GrantTypeInterface.php index 7aa98242..0e721435 100644 --- a/src/Grant/GrantTypeInterface.php +++ b/src/Grant/GrantTypeInterface.php @@ -119,6 +119,13 @@ interface GrantTypeInterface extends EmitterAwareInterface */ public function setScopeRepository(ScopeRepositoryInterface $scopeRepository); + /** + * Set the default scope. + * + * @param string $scope + */ + public function setDefaultScope($scope); + /** * Set the path to the private key. * diff --git a/src/Grant/ImplicitGrant.php b/src/Grant/ImplicitGrant.php index 5e102f32..9f000eb0 100644 --- a/src/Grant/ImplicitGrant.php +++ b/src/Grant/ImplicitGrant.php @@ -144,19 +144,13 @@ class ImplicitGrant extends AbstractAuthorizeGrant } } - $redirectUri = is_array($client->getRedirectUri()) ? $client->getRedirectUri()[0] : $client->getRedirectUri(); - $scopes = $this->validateScopes( $this->getQueryStringParameter('scope', $request, $this->defaultScope), - $redirectUri + is_array($client->getRedirectUri()) + ? $client->getRedirectUri()[0] + : $client->getRedirectUri() ); - try { - $this->checkScopesRequested($scopes, $redirectUri); - } catch (OAuthServerException $ex) { - throw $ex; - } - // Finalize the requested scopes $finalizedScopes = $this->scopeRepository->finalizeScopes( $scopes, diff --git a/src/Grant/PasswordGrant.php b/src/Grant/PasswordGrant.php index 0a0c80a7..cfd7e9fe 100644 --- a/src/Grant/PasswordGrant.php +++ b/src/Grant/PasswordGrant.php @@ -49,7 +49,7 @@ class PasswordGrant extends AbstractGrant ) { // Validate request $client = $this->validateClient($request); - $scopes = $this->validateScopes($this->getRequestParameter('scope', $request)); + $scopes = $this->validateScopes($this->getRequestParameter('scope', $request, $this->defaultScope)); $user = $this->validateUser($request, $client); // Finalize the requested scopes diff --git a/src/Grant/RefreshTokenGrant.php b/src/Grant/RefreshTokenGrant.php index d03b4edb..66a3b266 100644 --- a/src/Grant/RefreshTokenGrant.php +++ b/src/Grant/RefreshTokenGrant.php @@ -44,28 +44,17 @@ class RefreshTokenGrant extends AbstractGrant // Validate request $client = $this->validateClient($request); $oldRefreshToken = $this->validateOldRefreshToken($request, $client->getIdentifier()); - $scopes = $this->validateScopes($this->getRequestParameter('scope', $request)); + $scopes = $this->validateScopes($this->getRequestParameter( + 'scope', + $request, + implode(self::SCOPE_DELIMITER_STRING, $oldRefreshToken['scopes'])) + ); - // If no new scopes are requested then give the access token the original session scopes - if (count($scopes) === 0) { - $scopes = array_map(function ($scopeId) { - $scope = $this->scopeRepository->getScopeEntityByIdentifier($scopeId); - - if ($scope instanceof ScopeEntityInterface === false) { - // @codeCoverageIgnoreStart - throw OAuthServerException::invalidScope($scopeId); - // @codeCoverageIgnoreEnd - } - - return $scope; - }, $oldRefreshToken['scopes']); - } else { - // The OAuth spec says that a refreshed access token can have the original scopes or fewer so ensure - // the request doesn't include any new scopes - foreach ($scopes as $scope) { - if (in_array($scope->getIdentifier(), $oldRefreshToken['scopes']) === false) { - throw OAuthServerException::invalidScope($scope->getIdentifier()); - } + // The OAuth spec says that a refreshed access token can have the original scopes or fewer so ensure + // the request doesn't include any new scopes + foreach ($scopes as $scope) { + if (in_array($scope->getIdentifier(), $oldRefreshToken['scopes']) === false) { + throw OAuthServerException::invalidScope($scope->getIdentifier()); } } From 512d4898e230f6edce995e8c00504e7e96ef144b Mon Sep 17 00:00:00 2001 From: Sephster Date: Mon, 13 Nov 2017 22:20:16 +0000 Subject: [PATCH 25/34] Revert previous change --- src/AuthorizationServer.php | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/AuthorizationServer.php b/src/AuthorizationServer.php index f8674004..42313bff 100644 --- a/src/AuthorizationServer.php +++ b/src/AuthorizationServer.php @@ -121,14 +121,11 @@ class AuthorizationServer implements EmitterAwareInterface $grantType->setAccessTokenRepository($this->accessTokenRepository); $grantType->setClientRepository($this->clientRepository); $grantType->setScopeRepository($this->scopeRepository); + $grantType->setDefaultScope($this->defaultScope); $grantType->setPrivateKey($this->privateKey); $grantType->setEmitter($this->getEmitter()); $grantType->setEncryptionKey($this->encryptionKey); - if ($grantType instanceof AbstractAuthorizeGrant) { - $grantType->setDefaultScope($this->defaultScope); - } - $this->enabledGrantTypes[$grantType->getIdentifier()] = $grantType; $this->grantTypeAccessTokenTTL[$grantType->getIdentifier()] = $accessTokenTTL; } From 65789e0f397a26ab5851c5840c8fc3dc42810191 Mon Sep 17 00:00:00 2001 From: Sephster Date: Mon, 13 Nov 2017 22:20:42 +0000 Subject: [PATCH 26/34] Fix tests to support default scopes for authorization requests --- tests/Grant/ClientCredentialsGrantTest.php | 6 +++++ tests/Grant/PasswordGrantTest.php | 6 +++++ tests/Grant/RefreshTokenGrantTest.php | 24 ++++++++----------- .../AuthorizationServerMiddlewareTest.php | 6 +++++ 4 files changed, 28 insertions(+), 14 deletions(-) diff --git a/tests/Grant/ClientCredentialsGrantTest.php b/tests/Grant/ClientCredentialsGrantTest.php index 299cf020..8ad7e2b7 100644 --- a/tests/Grant/ClientCredentialsGrantTest.php +++ b/tests/Grant/ClientCredentialsGrantTest.php @@ -9,11 +9,14 @@ use League\OAuth2\Server\Repositories\ClientRepositoryInterface; use League\OAuth2\Server\Repositories\ScopeRepositoryInterface; use LeagueTests\Stubs\AccessTokenEntity; use LeagueTests\Stubs\ClientEntity; +use LeagueTests\Stubs\ScopeEntity; use LeagueTests\Stubs\StubResponseType; use Zend\Diactoros\ServerRequest; class ClientCredentialsGrantTest extends \PHPUnit_Framework_TestCase { + const DEFAULT_SCOPE = 'basic'; + public function testGetIdentifier() { $grant = new ClientCredentialsGrant(); @@ -30,13 +33,16 @@ class ClientCredentialsGrantTest extends \PHPUnit_Framework_TestCase $accessTokenRepositoryMock->method('getNewToken')->willReturn(new AccessTokenEntity()); $accessTokenRepositoryMock->method('persistNewAccessToken')->willReturnSelf(); + $scope = new ScopeEntity(); $scopeRepositoryMock = $this->getMockBuilder(ScopeRepositoryInterface::class)->getMock(); + $scopeRepositoryMock->method('getScopeEntityByIdentifier')->willReturn($scope); $scopeRepositoryMock->method('finalizeScopes')->willReturnArgument(0); $grant = new ClientCredentialsGrant(); $grant->setClientRepository($clientRepositoryMock); $grant->setAccessTokenRepository($accessTokenRepositoryMock); $grant->setScopeRepository($scopeRepositoryMock); + $grant->setDefaultScope(self::DEFAULT_SCOPE); $serverRequest = new ServerRequest(); $serverRequest = $serverRequest->withParsedBody( diff --git a/tests/Grant/PasswordGrantTest.php b/tests/Grant/PasswordGrantTest.php index b380bfb2..ae4b311d 100644 --- a/tests/Grant/PasswordGrantTest.php +++ b/tests/Grant/PasswordGrantTest.php @@ -13,12 +13,15 @@ use League\OAuth2\Server\Repositories\UserRepositoryInterface; use LeagueTests\Stubs\AccessTokenEntity; use LeagueTests\Stubs\ClientEntity; use LeagueTests\Stubs\RefreshTokenEntity; +use LeagueTests\Stubs\ScopeEntity; use LeagueTests\Stubs\StubResponseType; use LeagueTests\Stubs\UserEntity; use Zend\Diactoros\ServerRequest; class PasswordGrantTest extends \PHPUnit_Framework_TestCase { + const DEFAULT_SCOPE = 'basic'; + public function testGetIdentifier() { $userRepositoryMock = $this->getMockBuilder(UserRepositoryInterface::class)->getMock(); @@ -46,13 +49,16 @@ class PasswordGrantTest extends \PHPUnit_Framework_TestCase $refreshTokenRepositoryMock->method('persistNewRefreshToken')->willReturnSelf(); $refreshTokenRepositoryMock->method('getNewRefreshToken')->willReturn(new RefreshTokenEntity()); + $scope = new ScopeEntity(); $scopeRepositoryMock = $this->getMockBuilder(ScopeRepositoryInterface::class)->getMock(); + $scopeRepositoryMock->method('getScopeEntityByIdentifier')->willReturn($scope); $scopeRepositoryMock->method('finalizeScopes')->willReturnArgument(0); $grant = new PasswordGrant($userRepositoryMock, $refreshTokenRepositoryMock); $grant->setClientRepository($clientRepositoryMock); $grant->setAccessTokenRepository($accessTokenRepositoryMock); $grant->setScopeRepository($scopeRepositoryMock); + $grant->setDefaultScope(self::DEFAULT_SCOPE); $serverRequest = new ServerRequest(); $serverRequest = $serverRequest->withParsedBody( diff --git a/tests/Grant/RefreshTokenGrantTest.php b/tests/Grant/RefreshTokenGrantTest.php index 47d7ad17..eb6e18fb 100644 --- a/tests/Grant/RefreshTokenGrantTest.php +++ b/tests/Grant/RefreshTokenGrantTest.php @@ -45,21 +45,18 @@ class RefreshTokenGrantTest extends \PHPUnit_Framework_TestCase $clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock(); $clientRepositoryMock->method('getClientEntity')->willReturn($client); - $scopeRepositoryMock = $this->getMockBuilder(ScopeRepositoryInterface::class)->getMock(); $scopeEntity = new ScopeEntity(); + $scopeEntity->setIdentifier('foo'); + $scopeRepositoryMock = $this->getMockBuilder(ScopeRepositoryInterface::class)->getMock(); $scopeRepositoryMock->method('getScopeEntityByIdentifier')->willReturn($scopeEntity); $accessTokenRepositoryMock = $this->getMockBuilder(AccessTokenRepositoryInterface::class)->getMock(); $accessTokenRepositoryMock->method('getNewToken')->willReturn(new AccessTokenEntity()); - $accessTokenRepositoryMock - ->expects($this->once()) - ->method('persistNewAccessToken')->willReturnSelf(); + $accessTokenRepositoryMock->expects($this->once())->method('persistNewAccessToken')->willReturnSelf(); $refreshTokenRepositoryMock = $this->getMockBuilder(RefreshTokenRepositoryInterface::class)->getMock(); $refreshTokenRepositoryMock->method('getNewRefreshToken')->willReturn(new RefreshTokenEntity()); - $refreshTokenRepositoryMock - ->expects($this->once()) - ->method('persistNewRefreshToken')->willReturnSelf(); + $refreshTokenRepositoryMock->expects($this->once())->method('persistNewRefreshToken')->willReturnSelf(); $grant = new RefreshTokenGrant($refreshTokenRepositoryMock); $grant->setClientRepository($clientRepositoryMock); @@ -82,13 +79,12 @@ class RefreshTokenGrantTest extends \PHPUnit_Framework_TestCase ); $serverRequest = new ServerRequest(); - $serverRequest = $serverRequest->withParsedBody( - [ - 'client_id' => 'foo', - 'client_secret' => 'bar', - 'refresh_token' => $oldRefreshToken, - ] - ); + $serverRequest = $serverRequest->withParsedBody([ + 'client_id' => 'foo', + 'client_secret' => 'bar', + 'refresh_token' => $oldRefreshToken, + 'scopes' => ['foo'], + ]); $responseType = new StubResponseType(); $grant->respondToAccessTokenRequest($serverRequest, $responseType, new \DateInterval('PT5M')); diff --git a/tests/Middleware/AuthorizationServerMiddlewareTest.php b/tests/Middleware/AuthorizationServerMiddlewareTest.php index 74dffbf7..c44681e1 100644 --- a/tests/Middleware/AuthorizationServerMiddlewareTest.php +++ b/tests/Middleware/AuthorizationServerMiddlewareTest.php @@ -11,18 +11,23 @@ use League\OAuth2\Server\Repositories\ClientRepositoryInterface; use League\OAuth2\Server\Repositories\ScopeRepositoryInterface; use LeagueTests\Stubs\AccessTokenEntity; use LeagueTests\Stubs\ClientEntity; +use LeagueTests\Stubs\ScopeEntity; use LeagueTests\Stubs\StubResponseType; use Zend\Diactoros\Response; use Zend\Diactoros\ServerRequestFactory; class AuthorizationServerMiddlewareTest extends \PHPUnit_Framework_TestCase { + const DEFAULT_SCOPE = 'basic'; + public function testValidResponse() { $clientRepository = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock(); $clientRepository->method('getClientEntity')->willReturn(new ClientEntity()); + $scopeEntity = new ScopeEntity; $scopeRepositoryMock = $this->getMockBuilder(ScopeRepositoryInterface::class)->getMock(); + $scopeRepositoryMock->method('getScopeEntityByIdentifier')->willReturn($scopeEntity); $scopeRepositoryMock->method('finalizeScopes')->willReturnArgument(0); $accessRepositoryMock = $this->getMockBuilder(AccessTokenRepositoryInterface::class)->getMock(); @@ -37,6 +42,7 @@ class AuthorizationServerMiddlewareTest extends \PHPUnit_Framework_TestCase new StubResponseType() ); + $server->setDefaultScope(self::DEFAULT_SCOPE); $server->enableGrantType(new ClientCredentialsGrant()); $_POST['grant_type'] = 'client_credentials'; From eb645063c7c4ef43d3bfd1df514a8b6bdd7b5e35 Mon Sep 17 00:00:00 2001 From: Sephster Date: Mon, 13 Nov 2017 22:25:31 +0000 Subject: [PATCH 27/34] Reverted the abstract authorise grant to its previous state --- src/Grant/AbstractAuthorizeGrant.php | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/Grant/AbstractAuthorizeGrant.php b/src/Grant/AbstractAuthorizeGrant.php index 0ef8a8b0..7f05100c 100644 --- a/src/Grant/AbstractAuthorizeGrant.php +++ b/src/Grant/AbstractAuthorizeGrant.php @@ -11,15 +11,8 @@ namespace League\OAuth2\Server\Grant; -use League\OAuth2\Server\Exception\OAuthServerException; - abstract class AbstractAuthorizeGrant extends AbstractGrant { - /** - * @var string - */ - protected $defaultScope = ''; - /** * @param string $uri * @param array $params From c6bf2e1df099d4c76fdf98f210cc8a24590fabaf Mon Sep 17 00:00:00 2001 From: Sephster Date: Mon, 13 Nov 2017 22:31:50 +0000 Subject: [PATCH 28/34] Remove unnecessary white spaces --- tests/AuthorizationServerTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/AuthorizationServerTest.php b/tests/AuthorizationServerTest.php index 594a7ca6..4fe21724 100644 --- a/tests/AuthorizationServerTest.php +++ b/tests/AuthorizationServerTest.php @@ -28,7 +28,7 @@ use Zend\Diactoros\ServerRequestFactory; class AuthorizationServerTest extends \PHPUnit_Framework_TestCase { - const DEFAULT_SCOPE = 'basic '; + const DEFAULT_SCOPE = 'basic'; public function setUp() { From a5c5929dc9eb5e6fc5c5b1676459464f39bfe6bd Mon Sep 17 00:00:00 2001 From: Sephster Date: Mon, 13 Nov 2017 22:34:12 +0000 Subject: [PATCH 29/34] Change default scope to be basic --- tests/Grant/AuthCodeGrantTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Grant/AuthCodeGrantTest.php b/tests/Grant/AuthCodeGrantTest.php index ebfd4878..179d5feb 100644 --- a/tests/Grant/AuthCodeGrantTest.php +++ b/tests/Grant/AuthCodeGrantTest.php @@ -28,7 +28,7 @@ use Zend\Diactoros\ServerRequest; class AuthCodeGrantTest extends \PHPUnit_Framework_TestCase { - const DEFAULT_SCOPE = 'default'; + const DEFAULT_SCOPE = 'basic'; /** * @var CryptTraitStub From 1e3a84fc851efbe7a9d95d4096c62ba5b0578d99 Mon Sep 17 00:00:00 2001 From: Sephster Date: Mon, 13 Nov 2017 23:00:27 +0000 Subject: [PATCH 30/34] Add a test to ensure response requests fail without a scope specified --- tests/Grant/ClientCredentialsGrantTest.php | 38 ++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/tests/Grant/ClientCredentialsGrantTest.php b/tests/Grant/ClientCredentialsGrantTest.php index 8ad7e2b7..848d8ea7 100644 --- a/tests/Grant/ClientCredentialsGrantTest.php +++ b/tests/Grant/ClientCredentialsGrantTest.php @@ -57,4 +57,42 @@ class ClientCredentialsGrantTest extends \PHPUnit_Framework_TestCase $this->assertTrue($responseType->getAccessToken() instanceof AccessTokenEntityInterface); } + + /** + * @expectedException \League\OAuth2\Server\Exception\OAuthServerException + * @expectedExceptionCode 5 + */ + public function testRespondToRequestFailsWithoutScope() + { + $client = new ClientEntity(); + $clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock(); + $clientRepositoryMock->method('getClientEntity')->willReturn($client); + + $accessTokenRepositoryMock = $this->getMockBuilder(AccessTokenRepositoryInterface::class)->getMock(); + $accessTokenRepositoryMock->method('getNewToken')->willReturn(new AccessTokenEntity()); + $accessTokenRepositoryMock->method('persistNewAccessToken')->willReturnSelf(); + + $scope = new ScopeEntity(); + $scopeRepositoryMock = $this->getMockBuilder(ScopeRepositoryInterface::class)->getMock(); + $scopeRepositoryMock->method('getScopeEntityByIdentifier')->willReturn($scope); + $scopeRepositoryMock->method('finalizeScopes')->willReturnArgument(0); + + $grant = new ClientCredentialsGrant(); + $grant->setClientRepository($clientRepositoryMock); + $grant->setAccessTokenRepository($accessTokenRepositoryMock); + $grant->setScopeRepository($scopeRepositoryMock); + + $serverRequest = new ServerRequest(); + $serverRequest = $serverRequest->withParsedBody( + [ + 'client_id' => 'foo', + 'client_secret' => 'bar', + ] + ); + + $responseType = new StubResponseType(); + $grant->respondToAccessTokenRequest($serverRequest, $responseType, new \DateInterval('PT5M')); + + $this->assertTrue($responseType->getAccessToken() instanceof AccessTokenEntityInterface); + } } \ No newline at end of file From 1bcee9aabac6dc7c784ae4008e08826e700ec4a6 Mon Sep 17 00:00:00 2001 From: Sephster Date: Mon, 13 Nov 2017 23:16:30 +0000 Subject: [PATCH 31/34] Add a test for a missing scope for the password grant --- tests/Grant/AuthCodeGrantTest.php | 2 - tests/Grant/ClientCredentialsGrantTest.php | 2 - tests/Grant/ImplicitGrantTest.php | 2 - tests/Grant/PasswordGrantTest.php | 46 ++++++++++++++++++++++ 4 files changed, 46 insertions(+), 6 deletions(-) diff --git a/tests/Grant/AuthCodeGrantTest.php b/tests/Grant/AuthCodeGrantTest.php index 179d5feb..4a1c6d4a 100644 --- a/tests/Grant/AuthCodeGrantTest.php +++ b/tests/Grant/AuthCodeGrantTest.php @@ -1708,7 +1708,5 @@ class AuthCodeGrantTest extends \PHPUnit_Framework_TestCase 'redirect_uri' => 'http://foo/bar', ] ); - - $this->assertTrue($grant->validateAuthorizationRequest($request) instanceof AuthorizationRequest); } } diff --git a/tests/Grant/ClientCredentialsGrantTest.php b/tests/Grant/ClientCredentialsGrantTest.php index 848d8ea7..8559490d 100644 --- a/tests/Grant/ClientCredentialsGrantTest.php +++ b/tests/Grant/ClientCredentialsGrantTest.php @@ -92,7 +92,5 @@ class ClientCredentialsGrantTest extends \PHPUnit_Framework_TestCase $responseType = new StubResponseType(); $grant->respondToAccessTokenRequest($serverRequest, $responseType, new \DateInterval('PT5M')); - - $this->assertTrue($responseType->getAccessToken() instanceof AccessTokenEntityInterface); } } \ No newline at end of file diff --git a/tests/Grant/ImplicitGrantTest.php b/tests/Grant/ImplicitGrantTest.php index 5009c605..6e175ea6 100644 --- a/tests/Grant/ImplicitGrantTest.php +++ b/tests/Grant/ImplicitGrantTest.php @@ -446,7 +446,5 @@ class ImplicitGrantTest extends \PHPUnit_Framework_TestCase 'redirect_uri' => 'http://foo/bar', ] ); - - $this->assertTrue($grant->validateAuthorizationRequest($request) instanceof AuthorizationRequest); } } diff --git a/tests/Grant/PasswordGrantTest.php b/tests/Grant/PasswordGrantTest.php index ae4b311d..8c4337ba 100644 --- a/tests/Grant/PasswordGrantTest.php +++ b/tests/Grant/PasswordGrantTest.php @@ -173,4 +173,50 @@ class PasswordGrantTest extends \PHPUnit_Framework_TestCase $responseType = new StubResponseType(); $grant->respondToAccessTokenRequest($serverRequest, $responseType, new \DateInterval('PT5M')); } + + /** + * @expectedException \League\OAuth2\Server\Exception\OAuthServerException + * @expectedExceptionCode 5 + */ + public function testRespondToRequestFailsWithoutScope() + { + $client = new ClientEntity(); + $clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock(); + $clientRepositoryMock->method('getClientEntity')->willReturn($client); + + $accessTokenRepositoryMock = $this->getMockBuilder(AccessTokenRepositoryInterface::class)->getMock(); + $accessTokenRepositoryMock->method('getNewToken')->willReturn(new AccessTokenEntity()); + $accessTokenRepositoryMock->method('persistNewAccessToken')->willReturnSelf(); + + $userRepositoryMock = $this->getMockBuilder(UserRepositoryInterface::class)->getMock(); + $userEntity = new UserEntity(); + $userRepositoryMock->method('getUserEntityByUserCredentials')->willReturn($userEntity); + + $refreshTokenRepositoryMock = $this->getMockBuilder(RefreshTokenRepositoryInterface::class)->getMock(); + $refreshTokenRepositoryMock->method('persistNewRefreshToken')->willReturnSelf(); + $refreshTokenRepositoryMock->method('getNewRefreshToken')->willReturn(new RefreshTokenEntity()); + + $scope = new ScopeEntity(); + $scopeRepositoryMock = $this->getMockBuilder(ScopeRepositoryInterface::class)->getMock(); + $scopeRepositoryMock->method('getScopeEntityByIdentifier')->willReturn($scope); + $scopeRepositoryMock->method('finalizeScopes')->willReturnArgument(0); + + $grant = new PasswordGrant($userRepositoryMock, $refreshTokenRepositoryMock); + $grant->setClientRepository($clientRepositoryMock); + $grant->setAccessTokenRepository($accessTokenRepositoryMock); + $grant->setScopeRepository($scopeRepositoryMock); + + $serverRequest = new ServerRequest(); + $serverRequest = $serverRequest->withParsedBody( + [ + 'client_id' => 'foo', + 'client_secret' => 'bar', + 'username' => 'foo', + 'password' => 'bar', + ] + ); + + $responseType = new StubResponseType(); + $grant->respondToAccessTokenRequest($serverRequest, $responseType, new \DateInterval('PT5M')); + } } From 6e6baf5b7551f5180f0e71ac3a0a60e9193abcd4 Mon Sep 17 00:00:00 2001 From: Sephster Date: Mon, 13 Nov 2017 23:57:24 +0000 Subject: [PATCH 32/34] Remove abstract authorize grant use --- src/AuthorizationServer.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/AuthorizationServer.php b/src/AuthorizationServer.php index 40386653..c375af47 100644 --- a/src/AuthorizationServer.php +++ b/src/AuthorizationServer.php @@ -12,7 +12,6 @@ namespace League\OAuth2\Server; use League\Event\EmitterAwareInterface; use League\Event\EmitterAwareTrait; use League\OAuth2\Server\Exception\OAuthServerException; -use League\OAuth2\Server\Grant\AbstractAuthorizeGrant; use League\OAuth2\Server\Grant\GrantTypeInterface; use League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface; use League\OAuth2\Server\Repositories\ClientRepositoryInterface; From dc9c1a10234bab396592f62f41131d80006819fc Mon Sep 17 00:00:00 2001 From: Sephster Date: Mon, 13 Nov 2017 23:59:55 +0000 Subject: [PATCH 33/34] Remove blank line to keep code consistent --- tests/Grant/AuthCodeGrantTest.php | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/Grant/AuthCodeGrantTest.php b/tests/Grant/AuthCodeGrantTest.php index 6b06fe37..0e24d120 100644 --- a/tests/Grant/AuthCodeGrantTest.php +++ b/tests/Grant/AuthCodeGrantTest.php @@ -27,7 +27,6 @@ use Zend\Diactoros\ServerRequest; class AuthCodeGrantTest extends TestCase { - const DEFAULT_SCOPE = 'basic'; /** From b50c7622db08b34959407dc59aa7cc2e789d7379 Mon Sep 17 00:00:00 2001 From: Sephster Date: Tue, 14 Nov 2017 00:12:04 +0000 Subject: [PATCH 34/34] Add in validation for authorization requests. Fixes thephpleague/oauth2-server#677 --- tests/Grant/AuthCodeGrantTest.php | 2 ++ tests/Grant/ImplicitGrantTest.php | 2 ++ 2 files changed, 4 insertions(+) diff --git a/tests/Grant/AuthCodeGrantTest.php b/tests/Grant/AuthCodeGrantTest.php index 0e24d120..6b60f2b0 100644 --- a/tests/Grant/AuthCodeGrantTest.php +++ b/tests/Grant/AuthCodeGrantTest.php @@ -1707,5 +1707,7 @@ class AuthCodeGrantTest extends TestCase 'redirect_uri' => 'http://foo/bar', ] ); + + $grant->validateAuthorizationRequest($request); } } diff --git a/tests/Grant/ImplicitGrantTest.php b/tests/Grant/ImplicitGrantTest.php index db62d09c..dff2c341 100644 --- a/tests/Grant/ImplicitGrantTest.php +++ b/tests/Grant/ImplicitGrantTest.php @@ -447,5 +447,7 @@ class ImplicitGrantTest extends TestCase 'redirect_uri' => 'http://foo/bar', ] ); + + $grant->validateAuthorizationRequest($request); } }