From ec8a663a8188a32ecc44afba069a95bd5674632b Mon Sep 17 00:00:00 2001 From: Chris Tanaskoski Date: Thu, 29 Nov 2018 09:28:36 +0100 Subject: [PATCH 1/4] Added test for respondToAccessTokenRequest using Http Basic Auth for client credentials --- tests/Grant/AuthCodeGrantTest.php | 70 +++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/tests/Grant/AuthCodeGrantTest.php b/tests/Grant/AuthCodeGrantTest.php index 3ea7105a..ff051087 100644 --- a/tests/Grant/AuthCodeGrantTest.php +++ b/tests/Grant/AuthCodeGrantTest.php @@ -606,6 +606,76 @@ class AuthCodeGrantTest extends TestCase $this->assertInstanceOf(RefreshTokenEntityInterface::class, $response->getRefreshToken()); } + public function testRespondToAccessTokenRequestUsingHttpBasicAuth() + { + $client = new ClientEntity(); + $client->setIdentifier('foo'); + $client->setRedirectUri('http://foo/bar'); + $client->setConfidential(); + $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); + + $accessTokenRepositoryMock = $this->getMockBuilder(AccessTokenRepositoryInterface::class)->getMock(); + $accessTokenRepositoryMock->method('getNewToken')->willReturn(new AccessTokenEntity()); + $accessTokenRepositoryMock->method('persistNewAccessToken')->willReturnSelf(); + + $refreshTokenRepositoryMock = $this->getMockBuilder(RefreshTokenRepositoryInterface::class)->getMock(); + $refreshTokenRepositoryMock->method('persistNewRefreshToken')->willReturnSelf(); + $refreshTokenRepositoryMock->method('getNewRefreshToken')->willReturn(new RefreshTokenEntity()); + + $grant = new AuthCodeGrant( + $this->getMockBuilder(AuthCodeRepositoryInterface::class)->getMock(), + $this->getMockBuilder(RefreshTokenRepositoryInterface::class)->getMock(), + new \DateInterval('PT10M') + ); + $grant->setClientRepository($clientRepositoryMock); + $grant->setScopeRepository($scopeRepositoryMock); + $grant->setAccessTokenRepository($accessTokenRepositoryMock); + $grant->setRefreshTokenRepository($refreshTokenRepositoryMock); + $grant->setEncryptionKey($this->cryptStub->getKey()); + $grant->setPrivateKey(new CryptKey('file://' . __DIR__ . '/../Stubs/private.key')); + + $request = new ServerRequest( + [], + [], + null, + 'POST', + 'php://input', + [ + 'Authorization' => 'Basic Zm9vOmJhcg==', + ], + [], + [], + [ + 'grant_type' => 'authorization_code', + 'redirect_uri' => 'http://foo/bar', + 'code' => $this->cryptStub->doEncrypt( + json_encode( + [ + 'auth_code_id' => uniqid(), + 'client_id' => 'foo', + 'expire_time' => time() + 3600, + 'user_id' => 123, + 'scopes' => ['foo'], + 'redirect_uri' => 'http://foo/bar', + ] + ) + ), + ] + ); + + /** @var StubResponseType $response */ + $response = $grant->respondToAccessTokenRequest($request, new StubResponseType(), new \DateInterval('PT10M')); + + $this->assertInstanceOf(AccessTokenEntityInterface::class, $response->getAccessToken()); + $this->assertInstanceOf(RefreshTokenEntityInterface::class, $response->getRefreshToken()); + } + public function testRespondToAccessTokenRequestForPublicClient() { $client = new ClientEntity(); From b6955a6c65c84e4b4c4faa360ae70ea9477ecd7c Mon Sep 17 00:00:00 2001 From: Chris Tanaskoski Date: Thu, 29 Nov 2018 09:33:12 +0100 Subject: [PATCH 2/4] Fixed respondToAccessTokenRequest such that it accepts client_id through request body and Http Basic Auth --- src/Grant/AbstractGrant.php | 33 ++++++++++++++++++++++++--------- src/Grant/AuthCodeGrant.php | 6 +----- 2 files changed, 25 insertions(+), 14 deletions(-) diff --git a/src/Grant/AbstractGrant.php b/src/Grant/AbstractGrant.php index 4531a6a3..65ab16cf 100644 --- a/src/Grant/AbstractGrant.php +++ b/src/Grant/AbstractGrant.php @@ -171,15 +171,7 @@ abstract class AbstractGrant implements GrantTypeInterface */ protected function validateClient(ServerRequestInterface $request) { - list($basicAuthUser, $basicAuthPassword) = $this->getBasicAuthCredentials($request); - - $clientId = $this->getRequestParameter('client_id', $request, $basicAuthUser); - - if (is_null($clientId)) { - throw OAuthServerException::invalidRequest('client_id'); - } - - $clientSecret = $this->getRequestParameter('client_secret', $request, $basicAuthPassword); + list($clientId, $clientSecret) = $this->getClientCredentials($request); if ($this->clientRepository->validateClient($clientId, $clientSecret, $this->getIdentifier()) === false) { $this->getEmitter()->emit(new RequestEvent(RequestEvent::CLIENT_AUTHENTICATION_FAILED, $request)); @@ -199,6 +191,29 @@ abstract class AbstractGrant implements GrantTypeInterface return $client; } + /** + * Gets the client credentials from the request from the request body or + * the Http Basic Authorization header + * + * @param ServerRequestInterface $request + * + * @return array + */ + protected function getClientCredentials(ServerRequestInterface $request) + { + list($basicAuthUser, $basicAuthPassword) = $this->getBasicAuthCredentials($request); + + $clientId = $this->getRequestParameter('client_id', $request, $basicAuthUser); + + if (is_null($clientId)) { + throw OAuthServerException::invalidRequest('client_id'); + } + + $clientSecret = $this->getRequestParameter('client_secret', $request, $basicAuthPassword); + + return [$clientId, $clientSecret]; + } + /** * Validate redirectUri from the request. * If a redirect URI is provided ensure it matches what is pre-registered diff --git a/src/Grant/AuthCodeGrant.php b/src/Grant/AuthCodeGrant.php index 974f8373..c340fe96 100644 --- a/src/Grant/AuthCodeGrant.php +++ b/src/Grant/AuthCodeGrant.php @@ -90,11 +90,7 @@ class AuthCodeGrant extends AbstractAuthorizeGrant ResponseTypeInterface $responseType, \DateInterval $accessTokenTTL ) { - $clientId = $this->getRequestParameter('client_id', $request, null); - - if ($clientId === null) { - throw OAuthServerException::invalidRequest('client_id'); - } + list($clientId) = $this->getClientCredentials($request); $client = $this->clientRepository->getClientEntity($clientId); From fd65bf9e544262949baa46fa2ad9ca2f4e75e787 Mon Sep 17 00:00:00 2001 From: sephster Date: Mon, 10 Dec 2018 22:51:58 +0000 Subject: [PATCH 3/4] Streamline tests --- tests/Grant/AuthCodeGrantTest.php | 42 ++++++++++--------------------- 1 file changed, 13 insertions(+), 29 deletions(-) diff --git a/tests/Grant/AuthCodeGrantTest.php b/tests/Grant/AuthCodeGrantTest.php index ff051087..3abf232c 100644 --- a/tests/Grant/AuthCodeGrantTest.php +++ b/tests/Grant/AuthCodeGrantTest.php @@ -610,35 +610,30 @@ class AuthCodeGrantTest extends TestCase { $client = new ClientEntity(); $client->setIdentifier('foo'); - $client->setRedirectUri('http://foo/bar'); - $client->setConfidential(); $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('getScopeEntityByIdentifier')->willReturn(new ScopeEntity()); $scopeRepositoryMock->method('finalizeScopes')->willReturnArgument(0); $accessTokenRepositoryMock = $this->getMockBuilder(AccessTokenRepositoryInterface::class)->getMock(); $accessTokenRepositoryMock->method('getNewToken')->willReturn(new AccessTokenEntity()); - $accessTokenRepositoryMock->method('persistNewAccessToken')->willReturnSelf(); $refreshTokenRepositoryMock = $this->getMockBuilder(RefreshTokenRepositoryInterface::class)->getMock(); - $refreshTokenRepositoryMock->method('persistNewRefreshToken')->willReturnSelf(); $refreshTokenRepositoryMock->method('getNewRefreshToken')->willReturn(new RefreshTokenEntity()); - $grant = new AuthCodeGrant( + $authCodeGrant = new AuthCodeGrant( $this->getMockBuilder(AuthCodeRepositoryInterface::class)->getMock(), - $this->getMockBuilder(RefreshTokenRepositoryInterface::class)->getMock(), + $refreshTokenRepositoryMock, new \DateInterval('PT10M') ); - $grant->setClientRepository($clientRepositoryMock); - $grant->setScopeRepository($scopeRepositoryMock); - $grant->setAccessTokenRepository($accessTokenRepositoryMock); - $grant->setRefreshTokenRepository($refreshTokenRepositoryMock); - $grant->setEncryptionKey($this->cryptStub->getKey()); - $grant->setPrivateKey(new CryptKey('file://' . __DIR__ . '/../Stubs/private.key')); + + $authCodeGrant->setClientRepository($clientRepositoryMock); + $authCodeGrant->setScopeRepository($scopeRepositoryMock); + $authCodeGrant->setAccessTokenRepository($accessTokenRepositoryMock); + $authCodeGrant->setEncryptionKey($this->cryptStub->getKey()); + $authCodeGrant->setPrivateKey(new CryptKey('file://' . __DIR__ . '/../Stubs/private.key')); $request = new ServerRequest( [], @@ -647,7 +642,7 @@ class AuthCodeGrantTest extends TestCase 'POST', 'php://input', [ - 'Authorization' => 'Basic Zm9vOmJhcg==', + //'Authorization' => 'Basic Zm9vOmJhcg==', ], [], [], @@ -670,7 +665,7 @@ class AuthCodeGrantTest extends TestCase ); /** @var StubResponseType $response */ - $response = $grant->respondToAccessTokenRequest($request, new StubResponseType(), new \DateInterval('PT10M')); + $response = $authCodeGrant->respondToAccessTokenRequest($request, new StubResponseType(), new \DateInterval('PT10M')); $this->assertInstanceOf(AccessTokenEntityInterface::class, $response->getAccessToken()); $this->assertInstanceOf(RefreshTokenEntityInterface::class, $response->getRefreshToken()); @@ -1035,27 +1030,16 @@ class AuthCodeGrantTest extends TestCase public function testRespondToAccessTokenRequestExpiredCode() { - $client = new ClientEntity(); - $client->setIdentifier('foo'); - $client->setRedirectUri('http://foo/bar'); - $client->setConfidential(); $clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock(); - $clientRepositoryMock->method('getClientEntity')->willReturn($client); - - $accessTokenRepositoryMock = $this->getMockBuilder(AccessTokenRepositoryInterface::class)->getMock(); - $accessTokenRepositoryMock->method('persistNewAccessToken')->willReturnSelf(); - - $refreshTokenRepositoryMock = $this->getMockBuilder(RefreshTokenRepositoryInterface::class)->getMock(); - $refreshTokenRepositoryMock->method('persistNewRefreshToken')->willReturnSelf(); + $clientRepositoryMock->method('getClientEntity')->willReturn(new ClientEntity()); $grant = new AuthCodeGrant( $this->getMockBuilder(AuthCodeRepositoryInterface::class)->getMock(), $this->getMockBuilder(RefreshTokenRepositoryInterface::class)->getMock(), new \DateInterval('PT10M') ); + $grant->setClientRepository($clientRepositoryMock); - $grant->setAccessTokenRepository($accessTokenRepositoryMock); - $grant->setRefreshTokenRepository($refreshTokenRepositoryMock); $grant->setEncryptionKey($this->cryptStub->getKey()); $request = new ServerRequest( From 894724c45b903c1865143c2f672a1b21cb8dd07a Mon Sep 17 00:00:00 2001 From: sephster Date: Mon, 10 Dec 2018 23:01:45 +0000 Subject: [PATCH 4/4] Remove invalid commenting --- 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 3abf232c..c7f08a1a 100644 --- a/tests/Grant/AuthCodeGrantTest.php +++ b/tests/Grant/AuthCodeGrantTest.php @@ -642,7 +642,7 @@ class AuthCodeGrantTest extends TestCase 'POST', 'php://input', [ - //'Authorization' => 'Basic Zm9vOmJhcg==', + 'Authorization' => 'Basic Zm9vOmJhcg==', ], [], [],