Fixed use of default scope so it is only for authorization requests

This commit is contained in:
Andrew Millington 2017-11-06 22:33:28 +00:00
parent cc6eb63dd8
commit 0f08063864
12 changed files with 109 additions and 53 deletions

View File

@ -11,6 +11,7 @@ namespace League\OAuth2\Server;
use League\Event\EmitterAwareInterface; use League\Event\EmitterAwareInterface;
use League\Event\EmitterAwareTrait; use League\Event\EmitterAwareTrait;
use League\OAuth2\Server\Exception\OAuthServerException; use League\OAuth2\Server\Exception\OAuthServerException;
use League\OAuth2\Server\Grant\AbstractAuthorizeGrant;
use League\OAuth2\Server\Grant\GrantTypeInterface; use League\OAuth2\Server\Grant\GrantTypeInterface;
use League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface; use League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface;
use League\OAuth2\Server\Repositories\ClientRepositoryInterface; use League\OAuth2\Server\Repositories\ClientRepositoryInterface;
@ -120,11 +121,14 @@ class AuthorizationServer implements EmitterAwareInterface
$grantType->setAccessTokenRepository($this->accessTokenRepository); $grantType->setAccessTokenRepository($this->accessTokenRepository);
$grantType->setClientRepository($this->clientRepository); $grantType->setClientRepository($this->clientRepository);
$grantType->setScopeRepository($this->scopeRepository); $grantType->setScopeRepository($this->scopeRepository);
$grantType->setDefaultScope($this->defaultScope);
$grantType->setPrivateKey($this->privateKey); $grantType->setPrivateKey($this->privateKey);
$grantType->setEmitter($this->getEmitter()); $grantType->setEmitter($this->getEmitter());
$grantType->setEncryptionKey($this->encryptionKey); $grantType->setEncryptionKey($this->encryptionKey);
if ($grantType instanceof AbstractAuthorizeGrant) {
$grantType->setDefaultScope($this->defaultScope);
}
$this->enabledGrantTypes[$grantType->getIdentifier()] = $grantType; $this->enabledGrantTypes[$grantType->getIdentifier()] = $grantType;
$this->grantTypeAccessTokenTTL[$grantType->getIdentifier()] = $accessTokenTTL; $this->grantTypeAccessTokenTTL[$grantType->getIdentifier()] = $accessTokenTTL;
} }

View File

@ -11,6 +11,8 @@
namespace League\OAuth2\Server\Grant; namespace League\OAuth2\Server\Grant;
use League\OAuth2\Server\Exception\OAuthServerException;
abstract class AbstractAuthorizeGrant extends AbstractGrant abstract class AbstractAuthorizeGrant extends AbstractGrant
{ {
/** /**
@ -39,4 +41,17 @@ abstract class AbstractAuthorizeGrant extends AbstractGrant
{ {
$this->defaultScope = $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);
}
}
} }

View File

@ -232,10 +232,6 @@ abstract class AbstractGrant implements GrantTypeInterface
$validScopes[] = $scope; $validScopes[] = $scope;
} }
if (empty($validScopes)) {
throw OAuthServerException::invalidScope($redirectUri);
}
return $validScopes; return $validScopes;
} }

View File

@ -242,13 +242,19 @@ class AuthCodeGrant extends AbstractAuthorizeGrant
} }
} }
$redirectUri = is_array($client->getRedirectUri()) ? $client->getRedirectUri()[0] : $client->getRedirectUri();
$scopes = $this->validateScopes( $scopes = $this->validateScopes(
$this->getQueryStringParameter('scope', $request, $this->defaultScope), $this->getQueryStringParameter('scope', $request, $this->defaultScope),
is_array($client->getRedirectUri()) $redirectUri
? $client->getRedirectUri()[0]
: $client->getRedirectUri()
); );
try {
$this->checkScopesRequested($scopes, $redirectUri);
} catch (OAuthServerException $ex) {
throw $ex;
}
$stateParameter = $this->getQueryStringParameter('state', $request); $stateParameter = $this->getQueryStringParameter('state', $request);
$authorizationRequest = new AuthorizationRequest(); $authorizationRequest = new AuthorizationRequest();

View File

@ -144,13 +144,19 @@ class ImplicitGrant extends AbstractAuthorizeGrant
} }
} }
$redirectUri = is_array($client->getRedirectUri()) ? $client->getRedirectUri()[0] : $client->getRedirectUri();
$scopes = $this->validateScopes( $scopes = $this->validateScopes(
$this->getQueryStringParameter('scope', $request, $this->defaultScope), $this->getQueryStringParameter('scope', $request, $this->defaultScope),
is_array($client->getRedirectUri()) $redirectUri
? $client->getRedirectUri()[0]
: $client->getRedirectUri()
); );
try {
$this->checkScopesRequested($scopes, $redirectUri);
} catch (OAuthServerException $ex) {
throw $ex;
}
// Finalize the requested scopes // Finalize the requested scopes
$finalizedScopes = $this->scopeRepository->finalizeScopes( $finalizedScopes = $this->scopeRepository->finalizeScopes(
$scopes, $scopes,

View File

@ -459,21 +459,6 @@ class AbstractGrantTest extends \PHPUnit_Framework_TestCase
$grantMock->validateScopes('basic '); $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() public function testGenerateUniqueIdentifier()
{ {
$grantMock = $this->getMockForAbstractClass(AbstractGrant::class); $grantMock = $this->getMockForAbstractClass(AbstractGrant::class);

View File

@ -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( $grant = new AuthCodeGrant(
$this->getMockBuilder(AuthCodeRepositoryInterface::class)->getMock(), $this->getMockBuilder(AuthCodeRepositoryInterface::class)->getMock(),
$this->getMockBuilder(RefreshTokenRepositoryInterface::class)->getMock(), $this->getMockBuilder(RefreshTokenRepositoryInterface::class)->getMock(),
new \DateInterval('PT10M') 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);
} }
} }

View File

@ -9,14 +9,11 @@ use League\OAuth2\Server\Repositories\ClientRepositoryInterface;
use League\OAuth2\Server\Repositories\ScopeRepositoryInterface; use League\OAuth2\Server\Repositories\ScopeRepositoryInterface;
use LeagueTests\Stubs\AccessTokenEntity; use LeagueTests\Stubs\AccessTokenEntity;
use LeagueTests\Stubs\ClientEntity; use LeagueTests\Stubs\ClientEntity;
use LeagueTests\Stubs\ScopeEntity;
use LeagueTests\Stubs\StubResponseType; use LeagueTests\Stubs\StubResponseType;
use Zend\Diactoros\ServerRequest; use Zend\Diactoros\ServerRequest;
class ClientCredentialsGrantTest extends \PHPUnit_Framework_TestCase class ClientCredentialsGrantTest extends \PHPUnit_Framework_TestCase
{ {
const DEFAULT_SCOPE = 'basic';
public function testGetIdentifier() public function testGetIdentifier()
{ {
$grant = new ClientCredentialsGrant(); $grant = new ClientCredentialsGrant();
@ -33,16 +30,13 @@ class ClientCredentialsGrantTest extends \PHPUnit_Framework_TestCase
$accessTokenRepositoryMock->method('getNewToken')->willReturn(new AccessTokenEntity()); $accessTokenRepositoryMock->method('getNewToken')->willReturn(new AccessTokenEntity());
$accessTokenRepositoryMock->method('persistNewAccessToken')->willReturnSelf(); $accessTokenRepositoryMock->method('persistNewAccessToken')->willReturnSelf();
$scope = new ScopeEntity();
$scopeRepositoryMock = $this->getMockBuilder(ScopeRepositoryInterface::class)->getMock(); $scopeRepositoryMock = $this->getMockBuilder(ScopeRepositoryInterface::class)->getMock();
$scopeRepositoryMock->method('getScopeEntityByIdentifier')->willReturn($scope);
$scopeRepositoryMock->method('finalizeScopes')->willReturnArgument(0); $scopeRepositoryMock->method('finalizeScopes')->willReturnArgument(0);
$grant = new ClientCredentialsGrant(); $grant = new ClientCredentialsGrant();
$grant->setClientRepository($clientRepositoryMock); $grant->setClientRepository($clientRepositoryMock);
$grant->setAccessTokenRepository($accessTokenRepositoryMock); $grant->setAccessTokenRepository($accessTokenRepositoryMock);
$grant->setScopeRepository($scopeRepositoryMock); $grant->setScopeRepository($scopeRepositoryMock);
$grant->setDefaultScope(self::DEFAULT_SCOPE);
$serverRequest = new ServerRequest(); $serverRequest = new ServerRequest();
$serverRequest = $serverRequest->withParsedBody( $serverRequest = $serverRequest->withParsedBody(

View File

@ -411,4 +411,42 @@ class ImplicitGrantTest extends \PHPUnit_Framework_TestCase
$grant = new ImplicitGrant(new \DateInterval('PT10M')); $grant = new ImplicitGrant(new \DateInterval('PT10M'));
$grant->completeAuthorizationRequest(new AuthorizationRequest()); $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);
}
} }

View File

@ -13,15 +13,12 @@ use League\OAuth2\Server\Repositories\UserRepositoryInterface;
use LeagueTests\Stubs\AccessTokenEntity; use LeagueTests\Stubs\AccessTokenEntity;
use LeagueTests\Stubs\ClientEntity; use LeagueTests\Stubs\ClientEntity;
use LeagueTests\Stubs\RefreshTokenEntity; use LeagueTests\Stubs\RefreshTokenEntity;
use LeagueTests\Stubs\ScopeEntity;
use LeagueTests\Stubs\StubResponseType; use LeagueTests\Stubs\StubResponseType;
use LeagueTests\Stubs\UserEntity; use LeagueTests\Stubs\UserEntity;
use Zend\Diactoros\ServerRequest; use Zend\Diactoros\ServerRequest;
class PasswordGrantTest extends \PHPUnit_Framework_TestCase class PasswordGrantTest extends \PHPUnit_Framework_TestCase
{ {
const DEFAULT_SCOPE = 'basic';
public function testGetIdentifier() public function testGetIdentifier()
{ {
$userRepositoryMock = $this->getMockBuilder(UserRepositoryInterface::class)->getMock(); $userRepositoryMock = $this->getMockBuilder(UserRepositoryInterface::class)->getMock();
@ -49,16 +46,13 @@ class PasswordGrantTest extends \PHPUnit_Framework_TestCase
$refreshTokenRepositoryMock->method('persistNewRefreshToken')->willReturnSelf(); $refreshTokenRepositoryMock->method('persistNewRefreshToken')->willReturnSelf();
$refreshTokenRepositoryMock->method('getNewRefreshToken')->willReturn(new RefreshTokenEntity()); $refreshTokenRepositoryMock->method('getNewRefreshToken')->willReturn(new RefreshTokenEntity());
$scope = new ScopeEntity();
$scopeRepositoryMock = $this->getMockBuilder(ScopeRepositoryInterface::class)->getMock(); $scopeRepositoryMock = $this->getMockBuilder(ScopeRepositoryInterface::class)->getMock();
$scopeRepositoryMock->method('getScopeEntityByIdentifier')->willReturn($scope);
$scopeRepositoryMock->method('finalizeScopes')->willReturnArgument(0); $scopeRepositoryMock->method('finalizeScopes')->willReturnArgument(0);
$grant = new PasswordGrant($userRepositoryMock, $refreshTokenRepositoryMock); $grant = new PasswordGrant($userRepositoryMock, $refreshTokenRepositoryMock);
$grant->setClientRepository($clientRepositoryMock); $grant->setClientRepository($clientRepositoryMock);
$grant->setAccessTokenRepository($accessTokenRepositoryMock); $grant->setAccessTokenRepository($accessTokenRepositoryMock);
$grant->setScopeRepository($scopeRepositoryMock); $grant->setScopeRepository($scopeRepositoryMock);
$grant->setDefaultScope(self::DEFAULT_SCOPE);
$serverRequest = new ServerRequest(); $serverRequest = new ServerRequest();
$serverRequest = $serverRequest->withParsedBody( $serverRequest = $serverRequest->withParsedBody(

View File

@ -20,8 +20,6 @@ use Zend\Diactoros\ServerRequest;
class RefreshTokenGrantTest extends \PHPUnit_Framework_TestCase class RefreshTokenGrantTest extends \PHPUnit_Framework_TestCase
{ {
const DEFAULT_SCOPE = 'basic';
/** /**
* @var CryptTraitStub * @var CryptTraitStub
*/ */
@ -49,7 +47,6 @@ class RefreshTokenGrantTest extends \PHPUnit_Framework_TestCase
$scopeRepositoryMock = $this->getMockBuilder(ScopeRepositoryInterface::class)->getMock(); $scopeRepositoryMock = $this->getMockBuilder(ScopeRepositoryInterface::class)->getMock();
$scopeEntity = new ScopeEntity(); $scopeEntity = new ScopeEntity();
$scopeEntity->setIdentifier(self::DEFAULT_SCOPE);
$scopeRepositoryMock->method('getScopeEntityByIdentifier')->willReturn($scopeEntity); $scopeRepositoryMock->method('getScopeEntityByIdentifier')->willReturn($scopeEntity);
$accessTokenRepositoryMock = $this->getMockBuilder(AccessTokenRepositoryInterface::class)->getMock(); $accessTokenRepositoryMock = $this->getMockBuilder(AccessTokenRepositoryInterface::class)->getMock();
@ -70,7 +67,6 @@ class RefreshTokenGrantTest extends \PHPUnit_Framework_TestCase
$grant->setAccessTokenRepository($accessTokenRepositoryMock); $grant->setAccessTokenRepository($accessTokenRepositoryMock);
$grant->setEncryptionKey($this->cryptStub->getKey()); $grant->setEncryptionKey($this->cryptStub->getKey());
$grant->setPrivateKey(new CryptKey('file://' . __DIR__ . '/../Stubs/private.key')); $grant->setPrivateKey(new CryptKey('file://' . __DIR__ . '/../Stubs/private.key'));
$grant->setDefaultScope(self::DEFAULT_SCOPE);
$oldRefreshToken = $this->cryptStub->doEncrypt( $oldRefreshToken = $this->cryptStub->doEncrypt(
json_encode( json_encode(
@ -78,7 +74,7 @@ class RefreshTokenGrantTest extends \PHPUnit_Framework_TestCase
'client_id' => 'foo', 'client_id' => 'foo',
'refresh_token_id' => 'zyxwvu', 'refresh_token_id' => 'zyxwvu',
'access_token_id' => 'abcdef', 'access_token_id' => 'abcdef',
'scopes' => [self::DEFAULT_SCOPE], 'scopes' => ['foo'],
'user_id' => 123, 'user_id' => 123,
'expire_time' => time() + 3600, 'expire_time' => time() + 3600,
] ]

View File

@ -11,24 +11,18 @@ use League\OAuth2\Server\Repositories\ClientRepositoryInterface;
use League\OAuth2\Server\Repositories\ScopeRepositoryInterface; use League\OAuth2\Server\Repositories\ScopeRepositoryInterface;
use LeagueTests\Stubs\AccessTokenEntity; use LeagueTests\Stubs\AccessTokenEntity;
use LeagueTests\Stubs\ClientEntity; use LeagueTests\Stubs\ClientEntity;
use LeagueTests\Stubs\ScopeEntity;
use LeagueTests\Stubs\StubResponseType; use LeagueTests\Stubs\StubResponseType;
use Zend\Diactoros\Response; use Zend\Diactoros\Response;
use Zend\Diactoros\ServerRequestFactory; use Zend\Diactoros\ServerRequestFactory;
class AuthorizationServerMiddlewareTest extends \PHPUnit_Framework_TestCase class AuthorizationServerMiddlewareTest extends \PHPUnit_Framework_TestCase
{ {
const DEFAULT_SCOPE = 'basic';
public function testValidResponse() public function testValidResponse()
{ {
$clientRepository = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock(); $clientRepository = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
$clientRepository->method('getClientEntity')->willReturn(new ClientEntity()); $clientRepository->method('getClientEntity')->willReturn(new ClientEntity());
$scope = new ScopeEntity();
$scopeRepositoryMock = $this->getMockBuilder(ScopeRepositoryInterface::class)->getMock(); $scopeRepositoryMock = $this->getMockBuilder(ScopeRepositoryInterface::class)->getMock();
$scopeRepositoryMock->method('getScopeEntityByIdentifier')->willReturn($scope);
$scopeRepositoryMock->method('finalizeScopes')->willReturnArgument(0); $scopeRepositoryMock->method('finalizeScopes')->willReturnArgument(0);
$accessRepositoryMock = $this->getMockBuilder(AccessTokenRepositoryInterface::class)->getMock(); $accessRepositoryMock = $this->getMockBuilder(AccessTokenRepositoryInterface::class)->getMock();
@ -43,7 +37,6 @@ class AuthorizationServerMiddlewareTest extends \PHPUnit_Framework_TestCase
new StubResponseType() new StubResponseType()
); );
$server->setDefaultScope(self::DEFAULT_SCOPE);
$server->enableGrantType(new ClientCredentialsGrant()); $server->enableGrantType(new ClientCredentialsGrant());
$_POST['grant_type'] = 'client_credentials'; $_POST['grant_type'] = 'client_credentials';