Merge pull request #811 from Sephster/master

Add default scopes to authentication server
This commit is contained in:
Andrew Millington 2017-11-16 19:27:41 +00:00 committed by GitHub
commit 5f4ec6a154
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 314 additions and 63 deletions

View File

@ -71,6 +71,11 @@ class AuthorizationServer implements EmitterAwareInterface
*/ */
private $encryptionKey; private $encryptionKey;
/**
* @var string
*/
private $defaultScope = '';
/** /**
* New server instance. * New server instance.
* *
@ -97,7 +102,6 @@ class AuthorizationServer implements EmitterAwareInterface
$privateKey = new CryptKey($privateKey); $privateKey = new CryptKey($privateKey);
} }
$this->privateKey = $privateKey; $this->privateKey = $privateKey;
$this->encryptionKey = $encryptionKey; $this->encryptionKey = $encryptionKey;
$this->responseType = $responseType; $this->responseType = $responseType;
} }
@ -117,6 +121,7 @@ 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);
@ -205,4 +210,14 @@ class AuthorizationServer implements EmitterAwareInterface
return $this->responseType; return $this->responseType;
} }
/**
* Set the default scope for the authorization server.
*
* @param string $defaultScope
*/
public function setDefaultScope($defaultScope)
{
$this->defaultScope = $defaultScope;
}
} }

View File

@ -81,6 +81,11 @@ abstract class AbstractGrant implements GrantTypeInterface
*/ */
protected $privateKey; protected $privateKey;
/**
* @string
*/
protected $defaultScope;
/** /**
* @param ClientRepositoryInterface $clientRepository * @param ClientRepositoryInterface $clientRepository
*/ */
@ -147,6 +152,14 @@ abstract class AbstractGrant implements GrantTypeInterface
$this->privateKey = $key; $this->privateKey = $key;
} }
/**
* @param string $scope
*/
public function setDefaultScope($scope)
{
$this->defaultScope = $scope;
}
/** /**
* Validate the client. * Validate the client.
* *
@ -211,18 +224,14 @@ abstract class AbstractGrant implements GrantTypeInterface
* *
* @return ScopeEntityInterface[] * @return ScopeEntityInterface[]
*/ */
public function validateScopes( public function validateScopes($scopes, $redirectUri = null)
$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) { $validScopes = [];
return !empty($scope);
}
);
$scopes = [];
foreach ($scopesList as $scopeItem) { foreach ($scopesList as $scopeItem) {
$scope = $this->scopeRepository->getScopeEntityByIdentifier($scopeItem); $scope = $this->scopeRepository->getScopeEntityByIdentifier($scopeItem);
@ -230,10 +239,14 @@ abstract class AbstractGrant implements GrantTypeInterface
throw OAuthServerException::invalidScope($scopeItem, $redirectUri); throw OAuthServerException::invalidScope($scopeItem, $redirectUri);
} }
$scopes[] = $scope; $validScopes[] = $scope;
} }
return $scopes; if (empty($validScopes)) {
throw OAuthServerException::invalidScope($redirectUri);
}
return $validScopes;
} }
/** /**

View File

@ -243,7 +243,7 @@ class AuthCodeGrant extends AbstractAuthorizeGrant
} }
$scopes = $this->validateScopes( $scopes = $this->validateScopes(
$this->getQueryStringParameter('scope', $request), $this->getQueryStringParameter('scope', $request, $this->defaultScope),
is_array($client->getRedirectUri()) is_array($client->getRedirectUri())
? $client->getRedirectUri()[0] ? $client->getRedirectUri()[0]
: $client->getRedirectUri() : $client->getRedirectUri()

View File

@ -29,13 +29,13 @@ class ClientCredentialsGrant extends AbstractGrant
) { ) {
// Validate request // Validate request
$client = $this->validateClient($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 // 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 // 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 // Inject access token into response type
$responseType->setAccessToken($accessToken); $responseType->setAccessToken($accessToken);

View File

@ -119,6 +119,13 @@ interface GrantTypeInterface extends EmitterAwareInterface
*/ */
public function setScopeRepository(ScopeRepositoryInterface $scopeRepository); public function setScopeRepository(ScopeRepositoryInterface $scopeRepository);
/**
* Set the default scope.
*
* @param string $scope
*/
public function setDefaultScope($scope);
/** /**
* Set the path to the private key. * Set the path to the private key.
* *

View File

@ -152,14 +152,14 @@ class ImplicitGrant extends AbstractAuthorizeGrant
} }
$scopes = $this->validateScopes( $scopes = $this->validateScopes(
$this->getQueryStringParameter('scope', $request), $this->getQueryStringParameter('scope', $request, $this->defaultScope),
is_array($client->getRedirectUri()) is_array($client->getRedirectUri())
? $client->getRedirectUri()[0] ? $client->getRedirectUri()[0]
: $client->getRedirectUri() : $client->getRedirectUri()
); );
// Finalize the requested scopes // Finalize the requested scopes
$scopes = $this->scopeRepository->finalizeScopes( $finalizedScopes = $this->scopeRepository->finalizeScopes(
$scopes, $scopes,
$this->getIdentifier(), $this->getIdentifier(),
$client $client
@ -172,7 +172,7 @@ class ImplicitGrant extends AbstractAuthorizeGrant
$authorizationRequest->setClient($client); $authorizationRequest->setClient($client);
$authorizationRequest->setRedirectUri($redirectUri); $authorizationRequest->setRedirectUri($redirectUri);
$authorizationRequest->setState($stateParameter); $authorizationRequest->setState($stateParameter);
$authorizationRequest->setScopes($scopes); $authorizationRequest->setScopes($finalizedScopes);
return $authorizationRequest; return $authorizationRequest;
} }

View File

@ -49,14 +49,14 @@ class PasswordGrant extends AbstractGrant
) { ) {
// Validate request // Validate request
$client = $this->validateClient($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); $user = $this->validateUser($request, $client);
// Finalize the requested scopes // 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 // 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); $refreshToken = $this->issueRefreshToken($accessToken);
// Inject tokens into response // Inject tokens into response

View File

@ -44,28 +44,17 @@ class RefreshTokenGrant extends AbstractGrant
// Validate request // Validate request
$client = $this->validateClient($request); $client = $this->validateClient($request);
$oldRefreshToken = $this->validateOldRefreshToken($request, $client->getIdentifier()); $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 // The OAuth spec says that a refreshed access token can have the original scopes or fewer so ensure
if (count($scopes) === 0) { // the request doesn't include any new scopes
$scopes = array_map(function ($scopeId) use ($client) { foreach ($scopes as $scope) {
$scope = $this->scopeRepository->getScopeEntityByIdentifier($scopeId); if (in_array($scope->getIdentifier(), $oldRefreshToken['scopes']) === false) {
throw OAuthServerException::invalidScope($scope->getIdentifier());
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());
}
} }
} }

View File

@ -16,6 +16,7 @@ use League\OAuth2\Server\ResponseTypes\BearerTokenResponse;
use LeagueTests\Stubs\AccessTokenEntity; use LeagueTests\Stubs\AccessTokenEntity;
use LeagueTests\Stubs\AuthCodeEntity; use LeagueTests\Stubs\AuthCodeEntity;
use LeagueTests\Stubs\ClientEntity; use LeagueTests\Stubs\ClientEntity;
use LeagueTests\Stubs\ScopeEntity;
use LeagueTests\Stubs\StubResponseType; use LeagueTests\Stubs\StubResponseType;
use LeagueTests\Stubs\UserEntity; use LeagueTests\Stubs\UserEntity;
use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ResponseInterface;
@ -26,6 +27,9 @@ use Zend\Diactoros\ServerRequestFactory;
class AuthorizationServerTest extends TestCase class AuthorizationServerTest extends TestCase
{ {
const DEFAULT_SCOPE = 'basic';
public function setUp() public function setUp()
{ {
// Make sure the keys have the correct permissions. // Make sure the keys have the correct permissions.
@ -59,7 +63,9 @@ class AuthorizationServerTest extends TestCase
$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);
$accessTokenRepositoryMock = $this->getMockBuilder(AccessTokenRepositoryInterface::class)->getMock(); $accessTokenRepositoryMock = $this->getMockBuilder(AccessTokenRepositoryInterface::class)->getMock();
@ -74,6 +80,7 @@ class AuthorizationServerTest extends TestCase
new StubResponseType() new StubResponseType()
); );
$server->setDefaultScope(self::DEFAULT_SCOPE);
$server->enableGrantType(new ClientCredentialsGrant(), new \DateInterval('PT1M')); $server->enableGrantType(new ClientCredentialsGrant(), new \DateInterval('PT1M'));
$_POST['grant_type'] = 'client_credentials'; $_POST['grant_type'] = 'client_credentials';
@ -142,6 +149,10 @@ class AuthorizationServerTest extends TestCase
$clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock(); $clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
$clientRepositoryMock->method('getClientEntity')->willReturn($client); $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(),
@ -152,10 +163,12 @@ class AuthorizationServerTest extends TestCase
$server = new AuthorizationServer( $server = new AuthorizationServer(
$clientRepositoryMock, $clientRepositoryMock,
$this->getMockBuilder(AccessTokenRepositoryInterface::class)->getMock(), $this->getMockBuilder(AccessTokenRepositoryInterface::class)->getMock(),
$this->getMockBuilder(ScopeRepositoryInterface::class)->getMock(), $scopeRepositoryMock,
'file://' . __DIR__ . '/Stubs/private.key', 'file://' . __DIR__ . '/Stubs/private.key',
'file://' . __DIR__ . '/Stubs/public.key' 'file://' . __DIR__ . '/Stubs/public.key'
); );
$server->setDefaultScope(self::DEFAULT_SCOPE);
$server->enableGrantType($grant); $server->enableGrantType($grant);
$request = new ServerRequest( $request = new ServerRequest(

View File

@ -27,6 +27,8 @@ use Zend\Diactoros\ServerRequest;
class AuthCodeGrantTest extends TestCase class AuthCodeGrantTest extends TestCase
{ {
const DEFAULT_SCOPE = 'basic';
/** /**
* @var CryptTraitStub * @var CryptTraitStub
*/ */
@ -77,15 +79,22 @@ class AuthCodeGrantTest extends TestCase
{ {
$client = new ClientEntity(); $client = new ClientEntity();
$client->setRedirectUri('http://foo/bar'); $client->setRedirectUri('http://foo/bar');
$clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock(); $clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
$clientRepositoryMock->method('getClientEntity')->willReturn($client); $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->setClientRepository($clientRepositoryMock); $grant->setClientRepository($clientRepositoryMock);
$grant->setScopeRepository($scopeRepositoryMock);
$grant->setDefaultScope(self::DEFAULT_SCOPE);
$request = new ServerRequest( $request = new ServerRequest(
[], [],
@ -112,12 +121,18 @@ class AuthCodeGrantTest extends TestCase
$clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock(); $clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
$clientRepositoryMock->method('getClientEntity')->willReturn($client); $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->setClientRepository($clientRepositoryMock); $grant->setClientRepository($clientRepositoryMock);
$grant->setScopeRepository($scopeRepositoryMock);
$grant->setDefaultScope(self::DEFAULT_SCOPE);
$request = new ServerRequest( $request = new ServerRequest(
[], [],
@ -144,6 +159,10 @@ class AuthCodeGrantTest extends TestCase
$clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock(); $clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
$clientRepositoryMock->method('getClientEntity')->willReturn($client); $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(),
@ -151,6 +170,8 @@ class AuthCodeGrantTest extends TestCase
); );
$grant->enableCodeExchangeProof(); $grant->enableCodeExchangeProof();
$grant->setClientRepository($clientRepositoryMock); $grant->setClientRepository($clientRepositoryMock);
$grant->setScopeRepository($scopeRepositoryMock);
$grant->setDefaultScope(self::DEFAULT_SCOPE);
$request = new ServerRequest( $request = new ServerRequest(
[], [],
@ -429,6 +450,10 @@ class AuthCodeGrantTest extends TestCase
$clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock(); $clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
$clientRepositoryMock->method('getClientEntity')->willReturn($client); $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(),
@ -436,6 +461,8 @@ class AuthCodeGrantTest extends TestCase
); );
$grant->enableCodeExchangeProof(); $grant->enableCodeExchangeProof();
$grant->setClientRepository($clientRepositoryMock); $grant->setClientRepository($clientRepositoryMock);
$grant->setScopeRepository($scopeRepositoryMock);
$grant->setDefaultScope(self::DEFAULT_SCOPE);
$request = new ServerRequest( $request = new ServerRequest(
[], [],
@ -466,6 +493,10 @@ class AuthCodeGrantTest extends TestCase
$clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock(); $clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
$clientRepositoryMock->method('getClientEntity')->willReturn($client); $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(),
@ -473,6 +504,8 @@ class AuthCodeGrantTest extends TestCase
); );
$grant->enableCodeExchangeProof(); $grant->enableCodeExchangeProof();
$grant->setClientRepository($clientRepositoryMock); $grant->setClientRepository($clientRepositoryMock);
$grant->setScopeRepository($scopeRepositoryMock);
$grant->setDefaultScope(self::DEFAULT_SCOPE);
$request = new ServerRequest( $request = new ServerRequest(
[], [],
@ -1634,4 +1667,47 @@ class AuthCodeGrantTest extends TestCase
$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);
$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);
$request = new ServerRequest(
[],
[],
null,
null,
'php://input',
[],
[],
[
'response_type' => 'code',
'client_id' => 'foo',
'redirect_uri' => 'http://foo/bar',
]
);
$grant->validateAuthorizationRequest($request);
}
} }

View File

@ -9,12 +9,15 @@ 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 PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
use Zend\Diactoros\ServerRequest; use Zend\Diactoros\ServerRequest;
class ClientCredentialsGrantTest extends TestCase class ClientCredentialsGrantTest extends TestCase
{ {
const DEFAULT_SCOPE = 'basic';
public function testGetIdentifier() public function testGetIdentifier()
{ {
$grant = new ClientCredentialsGrant(); $grant = new ClientCredentialsGrant();
@ -31,7 +34,48 @@ class ClientCredentialsGrantTest extends 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);
$grant = new ClientCredentialsGrant();
$grant->setClientRepository($clientRepositoryMock);
$grant->setAccessTokenRepository($accessTokenRepositoryMock);
$grant->setScopeRepository($scopeRepositoryMock);
$grant->setDefaultScope(self::DEFAULT_SCOPE);
$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);
}
/**
* @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); $scopeRepositoryMock->method('finalizeScopes')->willReturnArgument(0);
$grant = new ClientCredentialsGrant(); $grant = new ClientCredentialsGrant();
@ -49,7 +93,5 @@ class ClientCredentialsGrantTest extends TestCase
$responseType = new StubResponseType(); $responseType = new StubResponseType();
$grant->respondToAccessTokenRequest($serverRequest, $responseType, new \DateInterval('PT5M')); $grant->respondToAccessTokenRequest($serverRequest, $responseType, new \DateInterval('PT5M'));
$this->assertTrue($responseType->getAccessToken() instanceof AccessTokenEntityInterface);
} }
} }

View File

@ -23,6 +23,8 @@ use Zend\Diactoros\ServerRequest;
class ImplicitGrantTest extends TestCase class ImplicitGrantTest extends TestCase
{ {
const DEFAULT_SCOPE = 'basic';
/** /**
* CryptTrait stub * CryptTrait stub
*/ */
@ -97,6 +99,7 @@ class ImplicitGrantTest extends TestCase
$grant = new ImplicitGrant(new \DateInterval('PT10M')); $grant = new ImplicitGrant(new \DateInterval('PT10M'));
$grant->setClientRepository($clientRepositoryMock); $grant->setClientRepository($clientRepositoryMock);
$grant->setScopeRepository($scopeRepositoryMock); $grant->setScopeRepository($scopeRepositoryMock);
$grant->setDefaultScope(self::DEFAULT_SCOPE);
$request = new ServerRequest( $request = new ServerRequest(
[], [],
@ -131,6 +134,7 @@ class ImplicitGrantTest extends TestCase
$grant = new ImplicitGrant(new \DateInterval('PT10M')); $grant = new ImplicitGrant(new \DateInterval('PT10M'));
$grant->setClientRepository($clientRepositoryMock); $grant->setClientRepository($clientRepositoryMock);
$grant->setScopeRepository($scopeRepositoryMock); $grant->setScopeRepository($scopeRepositoryMock);
$grant->setDefaultScope(self::DEFAULT_SCOPE);
$request = new ServerRequest( $request = new ServerRequest(
[], [],
@ -408,4 +412,42 @@ class ImplicitGrantTest extends 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',
]
);
$grant->validateAuthorizationRequest($request);
}
} }

View File

@ -13,6 +13,7 @@ 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 PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
@ -20,6 +21,8 @@ use Zend\Diactoros\ServerRequest;
class PasswordGrantTest extends TestCase class PasswordGrantTest extends TestCase
{ {
const DEFAULT_SCOPE = 'basic';
public function testGetIdentifier() public function testGetIdentifier()
{ {
$userRepositoryMock = $this->getMockBuilder(UserRepositoryInterface::class)->getMock(); $userRepositoryMock = $this->getMockBuilder(UserRepositoryInterface::class)->getMock();
@ -47,13 +50,16 @@ class PasswordGrantTest extends 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(
@ -168,4 +174,50 @@ class PasswordGrantTest extends TestCase
$responseType = new StubResponseType(); $responseType = new StubResponseType();
$grant->respondToAccessTokenRequest($serverRequest, $responseType, new \DateInterval('PT5M')); $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'));
}
} }

View File

@ -46,21 +46,18 @@ class RefreshTokenGrantTest extends TestCase
$clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock(); $clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
$clientRepositoryMock->method('getClientEntity')->willReturn($client); $clientRepositoryMock->method('getClientEntity')->willReturn($client);
$scopeRepositoryMock = $this->getMockBuilder(ScopeRepositoryInterface::class)->getMock();
$scopeEntity = new ScopeEntity(); $scopeEntity = new ScopeEntity();
$scopeEntity->setIdentifier('foo');
$scopeRepositoryMock = $this->getMockBuilder(ScopeRepositoryInterface::class)->getMock();
$scopeRepositoryMock->method('getScopeEntityByIdentifier')->willReturn($scopeEntity); $scopeRepositoryMock->method('getScopeEntityByIdentifier')->willReturn($scopeEntity);
$accessTokenRepositoryMock = $this->getMockBuilder(AccessTokenRepositoryInterface::class)->getMock(); $accessTokenRepositoryMock = $this->getMockBuilder(AccessTokenRepositoryInterface::class)->getMock();
$accessTokenRepositoryMock->method('getNewToken')->willReturn(new AccessTokenEntity()); $accessTokenRepositoryMock->method('getNewToken')->willReturn(new AccessTokenEntity());
$accessTokenRepositoryMock $accessTokenRepositoryMock->expects($this->once())->method('persistNewAccessToken')->willReturnSelf();
->expects($this->once())
->method('persistNewAccessToken')->willReturnSelf();
$refreshTokenRepositoryMock = $this->getMockBuilder(RefreshTokenRepositoryInterface::class)->getMock(); $refreshTokenRepositoryMock = $this->getMockBuilder(RefreshTokenRepositoryInterface::class)->getMock();
$refreshTokenRepositoryMock->method('getNewRefreshToken')->willReturn(new RefreshTokenEntity()); $refreshTokenRepositoryMock->method('getNewRefreshToken')->willReturn(new RefreshTokenEntity());
$refreshTokenRepositoryMock $refreshTokenRepositoryMock->expects($this->once())->method('persistNewRefreshToken')->willReturnSelf();
->expects($this->once())
->method('persistNewRefreshToken')->willReturnSelf();
$grant = new RefreshTokenGrant($refreshTokenRepositoryMock); $grant = new RefreshTokenGrant($refreshTokenRepositoryMock);
$grant->setClientRepository($clientRepositoryMock); $grant->setClientRepository($clientRepositoryMock);
@ -83,13 +80,12 @@ class RefreshTokenGrantTest extends TestCase
); );
$serverRequest = new ServerRequest(); $serverRequest = new ServerRequest();
$serverRequest = $serverRequest->withParsedBody( $serverRequest = $serverRequest->withParsedBody([
[ 'client_id' => 'foo',
'client_id' => 'foo', 'client_secret' => 'bar',
'client_secret' => 'bar', 'refresh_token' => $oldRefreshToken,
'refresh_token' => $oldRefreshToken, 'scopes' => ['foo'],
] ]);
);
$responseType = new StubResponseType(); $responseType = new StubResponseType();
$grant->respondToAccessTokenRequest($serverRequest, $responseType, new \DateInterval('PT5M')); $grant->respondToAccessTokenRequest($serverRequest, $responseType, new \DateInterval('PT5M'));

View File

@ -11,6 +11,7 @@ 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 PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
use Zend\Diactoros\Response; use Zend\Diactoros\Response;
@ -18,12 +19,16 @@ use Zend\Diactoros\ServerRequestFactory;
class AuthorizationServerMiddlewareTest extends TestCase class AuthorizationServerMiddlewareTest extends 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());
$scopeEntity = new ScopeEntity;
$scopeRepositoryMock = $this->getMockBuilder(ScopeRepositoryInterface::class)->getMock(); $scopeRepositoryMock = $this->getMockBuilder(ScopeRepositoryInterface::class)->getMock();
$scopeRepositoryMock->method('getScopeEntityByIdentifier')->willReturn($scopeEntity);
$scopeRepositoryMock->method('finalizeScopes')->willReturnArgument(0); $scopeRepositoryMock->method('finalizeScopes')->willReturnArgument(0);
$accessRepositoryMock = $this->getMockBuilder(AccessTokenRepositoryInterface::class)->getMock(); $accessRepositoryMock = $this->getMockBuilder(AccessTokenRepositoryInterface::class)->getMock();
@ -38,6 +43,7 @@ class AuthorizationServerMiddlewareTest extends 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';