Add tests for invalid client exception

This commit is contained in:
Andrew Millington 2018-05-13 17:29:07 +01:00
parent ff5e9f57a5
commit 33ce849617
6 changed files with 104 additions and 16 deletions

View File

@ -9,6 +9,7 @@
namespace League\OAuth2\Server\Exception; namespace League\OAuth2\Server\Exception;
use Psr\Http\Message\ServerRequest;
use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ResponseInterface;
class OAuthServerException extends \Exception class OAuthServerException extends \Exception
@ -38,6 +39,11 @@ class OAuthServerException extends \Exception
*/ */
private $payload; private $payload;
/**
* @var ServerRequest
*/
private $serverRequest;
/** /**
* Throw a new exception. * Throw a new exception.
* *
@ -84,6 +90,16 @@ class OAuthServerException extends \Exception
$this->payload = $payload; $this->payload = $payload;
} }
/**
* Set the server request that is responsible for generating the exception
*
* @return void
*/
public function setServerRequest($serverRequest)
{
$this->ServerRequest = $serverRequest;
}
/** /**
* Unsupported grant type error. * Unsupported grant type error.
* *
@ -117,13 +133,19 @@ class OAuthServerException extends \Exception
/** /**
* Invalid client error. * Invalid client error.
* *
* @param ServerRequest $serverRequest
*
* @return static * @return static
*/ */
public static function invalidClient() public static function invalidClient($serverRequest)
{ {
$errorMessage = 'Client authentication failed'; $errorMessage = 'Client authentication failed';
return new static($errorMessage, 4, 'invalid_client', 401); $exception = new static('Client authentication failed', 4, 'invalid_client', 401);
$exception->setServerRequest($serverRequest);
return $exception;
} }
/** /**
@ -294,8 +316,8 @@ class OAuthServerException extends \Exception
// include the "WWW-Authenticate" response header field // include the "WWW-Authenticate" response header field
// matching the authentication scheme used by the client. // matching the authentication scheme used by the client.
// @codeCoverageIgnoreStart // @codeCoverageIgnoreStart
if ($this->errorType === 'invalid_client' && array_key_exists('HTTP_AUTHORIZATION', $_SERVER) !== false) { if ($this->errorType === 'invalid_client' && $this->ServerRequest->hasHeader('Authorization') === true) {
$authScheme = strpos($_SERVER['HTTP_AUTHORIZATION'], 'Bearer') === 0 ? 'Bearer' : 'Basic'; $authScheme = strpos($this->ServerRequest->getHeader('Authorization')[0], 'Bearer') === 0 ? 'Bearer' : 'Basic';
$headers['WWW-Authenticate'] = $authScheme . ' realm="OAuth"'; $headers['WWW-Authenticate'] = $authScheme . ' realm="OAuth"';
} }

View File

@ -190,7 +190,7 @@ abstract class AbstractGrant implements GrantTypeInterface
if ($client instanceof ClientEntityInterface === false) { if ($client instanceof ClientEntityInterface === false) {
$this->getEmitter()->emit(new RequestEvent(RequestEvent::CLIENT_AUTHENTICATION_FAILED, $request)); $this->getEmitter()->emit(new RequestEvent(RequestEvent::CLIENT_AUTHENTICATION_FAILED, $request));
throw OAuthServerException::invalidClient(); throw OAuthServerException::invalidClient($request);
} }
// If a redirect URI is provided ensure it matches what is pre-registered // If a redirect URI is provided ensure it matches what is pre-registered
@ -201,13 +201,13 @@ abstract class AbstractGrant implements GrantTypeInterface
&& (strcmp($client->getRedirectUri(), $redirectUri) !== 0) && (strcmp($client->getRedirectUri(), $redirectUri) !== 0)
) { ) {
$this->getEmitter()->emit(new RequestEvent(RequestEvent::CLIENT_AUTHENTICATION_FAILED, $request)); $this->getEmitter()->emit(new RequestEvent(RequestEvent::CLIENT_AUTHENTICATION_FAILED, $request));
throw OAuthServerException::invalidClient(); throw OAuthServerException::invalidClient($request);
} elseif ( } elseif (
is_array($client->getRedirectUri()) is_array($client->getRedirectUri())
&& in_array($redirectUri, $client->getRedirectUri(), true) === false && in_array($redirectUri, $client->getRedirectUri(), true) === false
) { ) {
$this->getEmitter()->emit(new RequestEvent(RequestEvent::CLIENT_AUTHENTICATION_FAILED, $request)); $this->getEmitter()->emit(new RequestEvent(RequestEvent::CLIENT_AUTHENTICATION_FAILED, $request));
throw OAuthServerException::invalidClient(); throw OAuthServerException::invalidClient($request);
} }
} }

View File

@ -236,7 +236,7 @@ class AuthCodeGrant extends AbstractAuthorizeGrant
if ($client instanceof ClientEntityInterface === false) { if ($client instanceof ClientEntityInterface === false) {
$this->getEmitter()->emit(new RequestEvent(RequestEvent::CLIENT_AUTHENTICATION_FAILED, $request)); $this->getEmitter()->emit(new RequestEvent(RequestEvent::CLIENT_AUTHENTICATION_FAILED, $request));
throw OAuthServerException::invalidClient(); throw OAuthServerException::invalidClient($request);
} }
$redirectUri = $this->getQueryStringParameter('redirect_uri', $request); $redirectUri = $this->getQueryStringParameter('redirect_uri', $request);
@ -247,18 +247,18 @@ class AuthCodeGrant extends AbstractAuthorizeGrant
&& (strcmp($client->getRedirectUri(), $redirectUri) !== 0) && (strcmp($client->getRedirectUri(), $redirectUri) !== 0)
) { ) {
$this->getEmitter()->emit(new RequestEvent(RequestEvent::CLIENT_AUTHENTICATION_FAILED, $request)); $this->getEmitter()->emit(new RequestEvent(RequestEvent::CLIENT_AUTHENTICATION_FAILED, $request));
throw OAuthServerException::invalidClient(); throw OAuthServerException::invalidClient($request);
} elseif ( } elseif (
is_array($client->getRedirectUri()) is_array($client->getRedirectUri())
&& in_array($redirectUri, $client->getRedirectUri(), true) === false && in_array($redirectUri, $client->getRedirectUri(), true) === false
) { ) {
$this->getEmitter()->emit(new RequestEvent(RequestEvent::CLIENT_AUTHENTICATION_FAILED, $request)); $this->getEmitter()->emit(new RequestEvent(RequestEvent::CLIENT_AUTHENTICATION_FAILED, $request));
throw OAuthServerException::invalidClient(); throw OAuthServerException::invalidClient($request);
} }
} elseif (is_array($client->getRedirectUri()) && count($client->getRedirectUri()) !== 1 } elseif (is_array($client->getRedirectUri()) && count($client->getRedirectUri()) !== 1
|| empty($client->getRedirectUri())) { || empty($client->getRedirectUri())) {
$this->getEmitter()->emit(new RequestEvent(RequestEvent::CLIENT_AUTHENTICATION_FAILED, $request)); $this->getEmitter()->emit(new RequestEvent(RequestEvent::CLIENT_AUTHENTICATION_FAILED, $request));
throw OAuthServerException::invalidClient(); throw OAuthServerException::invalidClient($request);
} else { } else {
$redirectUri = is_array($client->getRedirectUri()) $redirectUri = is_array($client->getRedirectUri())
? $client->getRedirectUri()[0] ? $client->getRedirectUri()[0]

View File

@ -131,7 +131,7 @@ class ImplicitGrant extends AbstractAuthorizeGrant
if ($client instanceof ClientEntityInterface === false) { if ($client instanceof ClientEntityInterface === false) {
$this->getEmitter()->emit(new RequestEvent(RequestEvent::CLIENT_AUTHENTICATION_FAILED, $request)); $this->getEmitter()->emit(new RequestEvent(RequestEvent::CLIENT_AUTHENTICATION_FAILED, $request));
throw OAuthServerException::invalidClient(); throw OAuthServerException::invalidClient($request);
} }
$redirectUri = $this->getQueryStringParameter('redirect_uri', $request); $redirectUri = $this->getQueryStringParameter('redirect_uri', $request);
@ -141,18 +141,18 @@ class ImplicitGrant extends AbstractAuthorizeGrant
&& (strcmp($client->getRedirectUri(), $redirectUri) !== 0) && (strcmp($client->getRedirectUri(), $redirectUri) !== 0)
) { ) {
$this->getEmitter()->emit(new RequestEvent(RequestEvent::CLIENT_AUTHENTICATION_FAILED, $request)); $this->getEmitter()->emit(new RequestEvent(RequestEvent::CLIENT_AUTHENTICATION_FAILED, $request));
throw OAuthServerException::invalidClient(); throw OAuthServerException::invalidClient($request);
} elseif ( } elseif (
is_array($client->getRedirectUri()) is_array($client->getRedirectUri())
&& in_array($redirectUri, $client->getRedirectUri(), true) === false && in_array($redirectUri, $client->getRedirectUri(), true) === false
) { ) {
$this->getEmitter()->emit(new RequestEvent(RequestEvent::CLIENT_AUTHENTICATION_FAILED, $request)); $this->getEmitter()->emit(new RequestEvent(RequestEvent::CLIENT_AUTHENTICATION_FAILED, $request));
throw OAuthServerException::invalidClient(); throw OAuthServerException::invalidClient($request);
} }
} elseif (is_array($client->getRedirectUri()) && count($client->getRedirectUri()) !== 1 } elseif (is_array($client->getRedirectUri()) && count($client->getRedirectUri()) !== 1
|| empty($client->getRedirectUri())) { || empty($client->getRedirectUri())) {
$this->getEmitter()->emit(new RequestEvent(RequestEvent::CLIENT_AUTHENTICATION_FAILED, $request)); $this->getEmitter()->emit(new RequestEvent(RequestEvent::CLIENT_AUTHENTICATION_FAILED, $request));
throw OAuthServerException::invalidClient(); throw OAuthServerException::invalidClient($request);
} else { } else {
$redirectUri = is_array($client->getRedirectUri()) $redirectUri = is_array($client->getRedirectUri())
? $client->getRedirectUri()[0] ? $client->getRedirectUri()[0]

View File

@ -0,0 +1,66 @@
<?php
use PHPUnit\Framework\TestCase;
use League\OAuth2\Server\Exception\OAuthServerException;
use League\OAuth2\Server\Grant\AbstractGrant;
use League\OAuth2\Server\Repositories\ClientRepositoryInterface;
use Zend\Diactoros\Response;
use Zend\Diactoros\ServerRequest;
class OAuthServerExceptionTest extends TestCase
{
public function testInvalidClientExceptionSetsAuthenticateHeader()
{
$serverRequest = (new ServerRequest())
->withParsedBody([
'client_id' => 'foo',
])
->withAddedHeader('Authorization', 'Basic fakeauthdetails');
try {
$this->issueInvalidClientException($serverRequest);
} catch (OAuthServerException $e) {
$response = $e->generateHttpResponse(new Response());
$this->assertTrue($response->hasHeader('WWW-Authenticate'));
}
}
public function testInvalidClientExceptionOmitsAuthenticateHeader()
{
$serverRequest = (new ServerRequest())
->withParsedBody([
'client_id' => 'foo',
]);
try {
$this->issueInvalidClientException($serverRequest);
} catch (OAuthServerException $e) {
$response = $e->generateHttpResponse(new Response());
$this->assertFalse($response->hasHeader('WWW-Authenticate'));
}
}
/**
* Issue an invalid client exception
*
* @return void
* @throws OAuthServerException
*/
private function issueInvalidClientException($serverRequest)
{
$clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
$clientRepositoryMock->method('getClientEntity')->willReturn(false);
$grantMock = $this->getMockForAbstractClass(AbstractGrant::class);
$grantMock->setClientRepository($clientRepositoryMock);
$abstractGrantReflection = new ReflectionClass($grantMock);
$validateClientMethod = $abstractGrantReflection->getMethod('validateClient');
$validateClientMethod->setAccessible(true);
$validateClientMethod->invoke($grantMock, $serverRequest);
}
}

View File

@ -122,7 +122,7 @@ class AbstractGrantTest extends TestCase
$validateClientMethod = $abstractGrantReflection->getMethod('validateClient'); $validateClientMethod = $abstractGrantReflection->getMethod('validateClient');
$validateClientMethod->setAccessible(true); $validateClientMethod->setAccessible(true);
$result = $validateClientMethod->invoke($grantMock, $serverRequest, true, true); $result = $validateClientMethod->invoke($grantMock, $serverRequest);
$this->assertEquals($client, $result); $this->assertEquals($client, $result);
} }