mirror of
https://github.com/elyby/oauth2-server.git
synced 2024-12-22 13:09:44 +05:30
Merge remote-tracking branch 'upstream/8.0.0' into access-token-jwt
This commit is contained in:
commit
4aeb92aa98
13
CHANGELOG.md
13
CHANGELOG.md
@ -6,6 +6,14 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- The `invalidClient()` function accepts a PSR-7 compliant `$serverRequest` argument to avoid accessing the `$_SERVER` global variable and improve testing (PR #899)
|
||||||
|
|
||||||
|
## [7.1.1] - released 2018-05-21
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- No longer set a WWW-Authenticate header for invalid clients if the client did not send an Authorization header in the original request (PR #902)
|
||||||
|
|
||||||
## [7.1.0] - released 2018-04-22
|
## [7.1.0] - released 2018-04-22
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
@ -76,8 +84,6 @@ To address feedback from the security release the following change has been made
|
|||||||
|
|
||||||
## [5.1.4] - 2017-07-01
|
## [5.1.4] - 2017-07-01
|
||||||
|
|
||||||
- Fixed multiple security vulnerabilities as a result of a security audit paid for by the [Mozilla Secure Open Source Fund](https://wiki.mozilla.org/MOSS/Secure_Open_Source). All users of this library are encouraged to update as soon as possible to this version or version 6.0 or greater.
|
|
||||||
- It is recommended on each `AuthorizationServer` instance you set the `setEncryptionKey()`. This will result in stronger encryption being used. If this method is not set messages will be sent to the defined error handling routines (using `error_log`). Please see the examples and documentation for examples.
|
|
||||||
- TravisCI now tests PHP 7.1 (Issue #671)
|
- TravisCI now tests PHP 7.1 (Issue #671)
|
||||||
- Fix middleware example fatal error (Issue #682)
|
- Fix middleware example fatal error (Issue #682)
|
||||||
- Fix typo in the first README sentence (Issue #690)
|
- Fix typo in the first README sentence (Issue #690)
|
||||||
@ -385,6 +391,7 @@ Version 5 is a complete code rewrite.
|
|||||||
- First major release
|
- First major release
|
||||||
|
|
||||||
[Unreleased]: https://github.com/thephpleague/oauth2-server/compare/7.0.0...HEAD
|
[Unreleased]: https://github.com/thephpleague/oauth2-server/compare/7.0.0...HEAD
|
||||||
|
[7.1.1]: https://github.com/thephpleague/oauth2-server/compare/7.1.0...7.1.1
|
||||||
[7.1.0]: https://github.com/thephpleague/oauth2-server/compare/7.0.0...7.1.0
|
[7.1.0]: https://github.com/thephpleague/oauth2-server/compare/7.0.0...7.1.0
|
||||||
[7.0.0]: https://github.com/thephpleague/oauth2-server/compare/6.1.1...7.0.0
|
[7.0.0]: https://github.com/thephpleague/oauth2-server/compare/6.1.1...7.0.0
|
||||||
[6.1.1]: https://github.com/thephpleague/oauth2-server/compare/6.0.0...6.1.1
|
[6.1.1]: https://github.com/thephpleague/oauth2-server/compare/6.0.0...6.1.1
|
||||||
@ -423,6 +430,8 @@ Version 5 is a complete code rewrite.
|
|||||||
[3.0.0]: https://github.com/thephpleague/oauth2-server/compare/2.1.1...3.0.0
|
[3.0.0]: https://github.com/thephpleague/oauth2-server/compare/2.1.1...3.0.0
|
||||||
[2.1.1]: https://github.com/thephpleague/oauth2-server/compare/2.1.0...2.1.1
|
[2.1.1]: https://github.com/thephpleague/oauth2-server/compare/2.1.0...2.1.1
|
||||||
[2.1.0]: https://github.com/thephpleague/oauth2-server/compare/2.0.5...2.1.0
|
[2.1.0]: https://github.com/thephpleague/oauth2-server/compare/2.0.5...2.1.0
|
||||||
|
[2.1.1]: https://github.com/thephpleague/oauth2-server/compare/2.1.0...2.1.1
|
||||||
|
[2.1.0]: https://github.com/thephpleague/oauth2-server/compare/2.0.5...2.1.0
|
||||||
[2.0.5]: https://github.com/thephpleague/oauth2-server/compare/2.0.4...2.0.5
|
[2.0.5]: https://github.com/thephpleague/oauth2-server/compare/2.0.4...2.0.5
|
||||||
[2.0.4]: https://github.com/thephpleague/oauth2-server/compare/2.0.3...2.0.4
|
[2.0.4]: https://github.com/thephpleague/oauth2-server/compare/2.0.3...2.0.4
|
||||||
[2.0.3]: https://github.com/thephpleague/oauth2-server/compare/2.0.2...2.0.3
|
[2.0.3]: https://github.com/thephpleague/oauth2-server/compare/2.0.2...2.0.3
|
||||||
|
@ -37,6 +37,8 @@ The following versions of PHP are supported:
|
|||||||
|
|
||||||
The `openssl` extension is also required.
|
The `openssl` extension is also required.
|
||||||
|
|
||||||
|
All HTTP messages passed to the server should be [PSR-7 compliant](https://www.php-fig.org/psr/psr-7/). This ensures interoperability between other packages and frameworks.
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
```
|
```
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
namespace League\OAuth2\Server\Exception;
|
namespace League\OAuth2\Server\Exception;
|
||||||
|
|
||||||
use Psr\Http\Message\ResponseInterface;
|
use Psr\Http\Message\ResponseInterface;
|
||||||
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
|
|
||||||
class OAuthServerException extends \Exception
|
class OAuthServerException extends \Exception
|
||||||
{
|
{
|
||||||
@ -38,6 +39,11 @@ class OAuthServerException extends \Exception
|
|||||||
*/
|
*/
|
||||||
private $payload;
|
private $payload;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var ServerRequestInterface
|
||||||
|
*/
|
||||||
|
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
|
||||||
|
*
|
||||||
|
* @param ServerRequestInterface $serverRequest
|
||||||
|
*/
|
||||||
|
public function setServerRequest($serverRequest)
|
||||||
|
{
|
||||||
|
$this->serverRequest = $serverRequest;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unsupported grant type error.
|
* Unsupported grant type error.
|
||||||
*
|
*
|
||||||
@ -117,13 +133,17 @@ class OAuthServerException extends \Exception
|
|||||||
/**
|
/**
|
||||||
* Invalid client error.
|
* Invalid client error.
|
||||||
*
|
*
|
||||||
|
* @param ServerRequestInterface $serverRequest
|
||||||
|
*
|
||||||
* @return static
|
* @return static
|
||||||
*/
|
*/
|
||||||
public static function invalidClient()
|
public static function invalidClient($serverRequest)
|
||||||
{
|
{
|
||||||
$errorMessage = 'Client authentication failed';
|
$exception = new static('Client authentication failed', 4, 'invalid_client', 401);
|
||||||
|
|
||||||
return new static($errorMessage, 4, 'invalid_client', 401);
|
$exception->setServerRequest($serverRequest);
|
||||||
|
|
||||||
|
return $exception;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -294,13 +314,9 @@ 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') {
|
if ($this->errorType === 'invalid_client' && $this->serverRequest->hasHeader('Authorization') === true) {
|
||||||
$authScheme = 'Basic';
|
$authScheme = strpos($this->serverRequest->getHeader('Authorization')[0], 'Bearer') === 0 ? 'Bearer' : 'Basic';
|
||||||
if (array_key_exists('HTTP_AUTHORIZATION', $_SERVER) !== false
|
|
||||||
&& strpos($_SERVER['HTTP_AUTHORIZATION'], 'Bearer') === 0
|
|
||||||
) {
|
|
||||||
$authScheme = 'Bearer';
|
|
||||||
}
|
|
||||||
$headers['WWW-Authenticate'] = $authScheme . ' realm="OAuth"';
|
$headers['WWW-Authenticate'] = $authScheme . ' realm="OAuth"';
|
||||||
}
|
}
|
||||||
// @codeCoverageIgnoreEnd
|
// @codeCoverageIgnoreEnd
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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]
|
||||||
|
@ -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]
|
||||||
|
67
tests/Exception/OAuthServerExceptionTest.php
Normal file
67
tests/Exception/OAuthServerExceptionTest.php
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace LeagueTests\Exception;
|
||||||
|
|
||||||
|
use League\OAuth2\Server\Exception\OAuthServerException;
|
||||||
|
use League\OAuth2\Server\Grant\AbstractGrant;
|
||||||
|
use League\OAuth2\Server\Repositories\ClientRepositoryInterface;
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
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
|
||||||
|
*
|
||||||
|
* @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);
|
||||||
|
}
|
||||||
|
}
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user