mirror of
https://github.com/elyby/oauth2-server.git
synced 2025-05-31 14:12:07 +05:30
Compare commits
19 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
c7f4998497 | ||
|
0a78236f17 | ||
|
a68f8001a4 | ||
|
b88198a9a4 | ||
|
0227f14b7b | ||
|
fad42a88fd | ||
|
2a16dbeb7f | ||
|
faa350792a | ||
|
dc3181bbb0 | ||
|
1e3a7adb19 | ||
|
b71f382cd7 | ||
|
9783388523 | ||
|
46493c461e | ||
|
8b421818f2 | ||
|
b09154af33 | ||
|
f1454cde36 | ||
|
f2cd3646ff | ||
|
7839a61170 | ||
|
443d7c485a |
@@ -15,6 +15,7 @@ php:
|
|||||||
- 7.0
|
- 7.0
|
||||||
- 7.1
|
- 7.1
|
||||||
- 7.2
|
- 7.2
|
||||||
|
- 7.3
|
||||||
|
|
||||||
install:
|
install:
|
||||||
- composer update --no-interaction --prefer-dist $DEPENDENCIES
|
- composer update --no-interaction --prefer-dist $DEPENDENCIES
|
||||||
|
22
CHANGELOG.md
22
CHANGELOG.md
@@ -6,6 +6,23 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
## [7.3.3] - released 2019-03-29
|
||||||
|
### Added
|
||||||
|
- Added `error_description` to the error payload to improve standards compliance. The contents of this are copied from the existing `message` value. (PR #1006)
|
||||||
|
|
||||||
|
### Deprecated
|
||||||
|
- Error payload will not issue `message` value in the next major release (PR #1006)
|
||||||
|
|
||||||
|
## [7.3.2] - released 2018-11-21
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Revert setting keys on response type to be inside `getResponseType()` function instead of AuthorizationServer constructor (PR #969)
|
||||||
|
|
||||||
|
## [7.3.1] - released 2018-11-15
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Fix issue with previous release where interface had changed for the AuthorizationServer. Reverted to the previous interface while maintaining functionality changes (PR #970)
|
||||||
|
|
||||||
## [7.3.0] - released 2018-11-13
|
## [7.3.0] - released 2018-11-13
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
@@ -422,7 +439,10 @@ Version 5 is a complete code rewrite.
|
|||||||
|
|
||||||
- First major release
|
- First major release
|
||||||
|
|
||||||
[Unreleased]: https://github.com/thephpleague/oauth2-server/compare/7.3.0...HEAD
|
[Unreleased]: https://github.com/thephpleague/oauth2-server/compare/7.3.3...HEAD
|
||||||
|
[7.3.3]: https://github.com/thephpleague/oauth2-server/compare/7.3.2...7.3.3
|
||||||
|
[7.3.2]: https://github.com/thephpleague/oauth2-server/compare/7.3.1...7.3.2
|
||||||
|
[7.3.1]: https://github.com/thephpleague/oauth2-server/compare/7.3.0...7.3.1
|
||||||
[7.3.0]: https://github.com/thephpleague/oauth2-server/compare/7.2.0...7.3.0
|
[7.3.0]: https://github.com/thephpleague/oauth2-server/compare/7.2.0...7.3.0
|
||||||
[7.2.0]: https://github.com/thephpleague/oauth2-server/compare/7.1.1...7.2.0
|
[7.2.0]: https://github.com/thephpleague/oauth2-server/compare/7.1.1...7.2.0
|
||||||
[7.1.1]: https://github.com/thephpleague/oauth2-server/compare/7.1.0...7.1.1
|
[7.1.1]: https://github.com/thephpleague/oauth2-server/compare/7.1.0...7.1.1
|
||||||
|
@@ -34,6 +34,7 @@ The following versions of PHP are supported:
|
|||||||
* PHP 7.0
|
* PHP 7.0
|
||||||
* PHP 7.1
|
* PHP 7.1
|
||||||
* PHP 7.2
|
* PHP 7.2
|
||||||
|
* PHP 7.3
|
||||||
|
|
||||||
The `openssl` extension is also required.
|
The `openssl` extension is also required.
|
||||||
|
|
||||||
@@ -69,6 +70,7 @@ We use [Travis CI](https://travis-ci.org/), [Scrutinizer](https://scrutinizer-ci
|
|||||||
* [Laravel Passport](https://github.com/laravel/passport)
|
* [Laravel Passport](https://github.com/laravel/passport)
|
||||||
* [OAuth 2 Server for CakePHP 3](https://github.com/uafrica/oauth-server)
|
* [OAuth 2 Server for CakePHP 3](https://github.com/uafrica/oauth-server)
|
||||||
* [OAuth 2 Server for Expressive](https://github.com/zendframework/zend-expressive-authentication-oauth2)
|
* [OAuth 2 Server for Expressive](https://github.com/zendframework/zend-expressive-authentication-oauth2)
|
||||||
|
* [Trikoder OAuth 2 Bundle (Symfony)](https://github.com/trikoder/oauth2-bundle)
|
||||||
|
|
||||||
## Changelog
|
## Changelog
|
||||||
|
|
||||||
|
@@ -52,7 +52,7 @@ class AuthorizationServer implements EmitterAwareInterface
|
|||||||
/**
|
/**
|
||||||
* @var ResponseTypeInterface
|
* @var ResponseTypeInterface
|
||||||
*/
|
*/
|
||||||
protected $responseTypePrototype;
|
protected $responseType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var ClientRepositoryInterface
|
* @var ClientRepositoryInterface
|
||||||
@@ -87,7 +87,7 @@ class AuthorizationServer implements EmitterAwareInterface
|
|||||||
* @param ScopeRepositoryInterface $scopeRepository
|
* @param ScopeRepositoryInterface $scopeRepository
|
||||||
* @param CryptKey|string $privateKey
|
* @param CryptKey|string $privateKey
|
||||||
* @param string|Key $encryptionKey
|
* @param string|Key $encryptionKey
|
||||||
* @param null|ResponseTypeInterface $responseTypePrototype
|
* @param null|ResponseTypeInterface $responseType
|
||||||
*/
|
*/
|
||||||
public function __construct(
|
public function __construct(
|
||||||
ClientRepositoryInterface $clientRepository,
|
ClientRepositoryInterface $clientRepository,
|
||||||
@@ -95,7 +95,7 @@ class AuthorizationServer implements EmitterAwareInterface
|
|||||||
ScopeRepositoryInterface $scopeRepository,
|
ScopeRepositoryInterface $scopeRepository,
|
||||||
$privateKey,
|
$privateKey,
|
||||||
$encryptionKey,
|
$encryptionKey,
|
||||||
ResponseTypeInterface $responseTypePrototype = null
|
ResponseTypeInterface $responseType = null
|
||||||
) {
|
) {
|
||||||
$this->clientRepository = $clientRepository;
|
$this->clientRepository = $clientRepository;
|
||||||
$this->accessTokenRepository = $accessTokenRepository;
|
$this->accessTokenRepository = $accessTokenRepository;
|
||||||
@@ -108,19 +108,13 @@ class AuthorizationServer implements EmitterAwareInterface
|
|||||||
$this->privateKey = $privateKey;
|
$this->privateKey = $privateKey;
|
||||||
$this->encryptionKey = $encryptionKey;
|
$this->encryptionKey = $encryptionKey;
|
||||||
|
|
||||||
if ($responseTypePrototype === null) {
|
if ($responseType === null) {
|
||||||
$responseTypePrototype = new BearerTokenResponse();
|
$responseType = new BearerTokenResponse();
|
||||||
} else {
|
} else {
|
||||||
$responseTypePrototype = clone $responseTypePrototype;
|
$responseType = clone $responseType;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($responseTypePrototype instanceof AbstractResponseType) {
|
$this->responseType = $responseType;
|
||||||
$responseTypePrototype->setPrivateKey($this->privateKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
$responseTypePrototype->setEncryptionKey($this->encryptionKey);
|
|
||||||
|
|
||||||
$this->responseTypePrototype = $responseTypePrototype;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -200,7 +194,7 @@ class AuthorizationServer implements EmitterAwareInterface
|
|||||||
}
|
}
|
||||||
$tokenResponse = $grantType->respondToAccessTokenRequest(
|
$tokenResponse = $grantType->respondToAccessTokenRequest(
|
||||||
$request,
|
$request,
|
||||||
$this->newResponseType(),
|
$this->getResponseType(),
|
||||||
$this->grantTypeAccessTokenTTL[$grantType->getIdentifier()]
|
$this->grantTypeAccessTokenTTL[$grantType->getIdentifier()]
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -217,9 +211,17 @@ class AuthorizationServer implements EmitterAwareInterface
|
|||||||
*
|
*
|
||||||
* @return ResponseTypeInterface
|
* @return ResponseTypeInterface
|
||||||
*/
|
*/
|
||||||
protected function newResponseType()
|
protected function getResponseType()
|
||||||
{
|
{
|
||||||
return clone $this->responseTypePrototype;
|
$responseType = clone $this->responseType;
|
||||||
|
|
||||||
|
if ($responseType instanceof AbstractResponseType) {
|
||||||
|
$responseType->setPrivateKey($this->privateKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
$responseType->setEncryptionKey($this->encryptionKey);
|
||||||
|
|
||||||
|
return $responseType;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -59,8 +59,8 @@ class OAuthServerException extends Exception
|
|||||||
$this->hint = $hint;
|
$this->hint = $hint;
|
||||||
$this->redirectUri = $redirectUri;
|
$this->redirectUri = $redirectUri;
|
||||||
$this->payload = [
|
$this->payload = [
|
||||||
'error' => $errorType,
|
'error' => $errorType,
|
||||||
'message' => $message,
|
'error_description' => $message,
|
||||||
];
|
];
|
||||||
if ($hint !== null) {
|
if ($hint !== null) {
|
||||||
$this->payload['hint'] = $hint;
|
$this->payload['hint'] = $hint;
|
||||||
@@ -74,7 +74,15 @@ class OAuthServerException extends Exception
|
|||||||
*/
|
*/
|
||||||
public function getPayload()
|
public function getPayload()
|
||||||
{
|
{
|
||||||
return $this->payload;
|
$payload = $this->payload;
|
||||||
|
|
||||||
|
// The "message" property is deprecated and replaced by "error_description"
|
||||||
|
// TODO: remove "message" property
|
||||||
|
if (isset($payload['error_description']) && !isset($payload['message'])) {
|
||||||
|
$payload['message'] = $payload['error_description'];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $payload;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -91,7 +91,7 @@ class AuthorizationServerTest extends TestCase
|
|||||||
$this->assertEquals(200, $response->getStatusCode());
|
$this->assertEquals(200, $response->getStatusCode());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testNewDefaultResponseType()
|
public function testGetResponseType()
|
||||||
{
|
{
|
||||||
$clientRepository = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
|
$clientRepository = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
|
||||||
|
|
||||||
@@ -104,17 +104,50 @@ class AuthorizationServerTest extends TestCase
|
|||||||
);
|
);
|
||||||
|
|
||||||
$abstractGrantReflection = new \ReflectionClass($server);
|
$abstractGrantReflection = new \ReflectionClass($server);
|
||||||
$method = $abstractGrantReflection->getMethod('newResponseType');
|
$method = $abstractGrantReflection->getMethod('getResponseType');
|
||||||
$method->setAccessible(true);
|
$method->setAccessible(true);
|
||||||
|
|
||||||
$responseTypeA = $method->invoke($server);
|
$this->assertInstanceOf(BearerTokenResponse::class, $method->invoke($server));
|
||||||
$responseTypeB = $method->invoke($server);
|
|
||||||
$this->assertInstanceOf(BearerTokenResponse::class, $responseTypeA);
|
|
||||||
$this->assertInstanceOf(BearerTokenResponse::class, $responseTypeB);
|
|
||||||
$this->assertNotSame($responseTypeA, $responseTypeB);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testNewResponseTypeFromPrototype()
|
public function testGetResponseTypeExtended()
|
||||||
|
{
|
||||||
|
$clientRepository = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
|
||||||
|
$privateKey = 'file://' . __DIR__ . '/Stubs/private.key';
|
||||||
|
$encryptionKey = 'file://' . __DIR__ . '/Stubs/public.key';
|
||||||
|
|
||||||
|
$server = new class($clientRepository, $this->getMockBuilder(AccessTokenRepositoryInterface::class)->getMock(), $this->getMockBuilder(ScopeRepositoryInterface::class)->getMock(), $privateKey, $encryptionKey) extends AuthorizationServer {
|
||||||
|
protected function getResponseType()
|
||||||
|
{
|
||||||
|
$this->responseType = new class extends BearerTokenResponse {
|
||||||
|
/* @return null|CryptKey */
|
||||||
|
public function getPrivateKey()
|
||||||
|
{
|
||||||
|
return $this->privateKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getEncryptionKey()
|
||||||
|
{
|
||||||
|
return $this->encryptionKey;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return parent::getResponseType();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
$abstractGrantReflection = new \ReflectionClass($server);
|
||||||
|
$method = $abstractGrantReflection->getMethod('getResponseType');
|
||||||
|
$method->setAccessible(true);
|
||||||
|
$responseType = $method->invoke($server);
|
||||||
|
|
||||||
|
$this->assertInstanceOf(BearerTokenResponse::class, $responseType);
|
||||||
|
// generated instances should have keys setup
|
||||||
|
$this->assertSame($privateKey, $responseType->getPrivateKey()->getKeyPath());
|
||||||
|
$this->assertSame($encryptionKey, $responseType->getEncryptionKey());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testMultipleRequestsGetDifferentResponseTypeInstances()
|
||||||
{
|
{
|
||||||
$privateKey = 'file://' . __DIR__ . '/Stubs/private.key';
|
$privateKey = 'file://' . __DIR__ . '/Stubs/private.key';
|
||||||
$encryptionKey = 'file://' . __DIR__ . '/Stubs/public.key';
|
$encryptionKey = 'file://' . __DIR__ . '/Stubs/public.key';
|
||||||
@@ -144,7 +177,7 @@ class AuthorizationServerTest extends TestCase
|
|||||||
);
|
);
|
||||||
|
|
||||||
$abstractGrantReflection = new \ReflectionClass($server);
|
$abstractGrantReflection = new \ReflectionClass($server);
|
||||||
$method = $abstractGrantReflection->getMethod('newResponseType');
|
$method = $abstractGrantReflection->getMethod('getResponseType');
|
||||||
$method->setAccessible(true);
|
$method->setAccessible(true);
|
||||||
|
|
||||||
$responseTypeA = $method->invoke($server);
|
$responseTypeA = $method->invoke($server);
|
||||||
|
@@ -285,7 +285,6 @@ class ImplicitGrantTest extends TestCase
|
|||||||
$accessTokenRepositoryMock->method('persistNewAccessToken')->willReturnSelf();
|
$accessTokenRepositoryMock->method('persistNewAccessToken')->willReturnSelf();
|
||||||
|
|
||||||
$scopeRepositoryMock = $this->getMockBuilder(ScopeRepositoryInterface::class)->getMock();
|
$scopeRepositoryMock = $this->getMockBuilder(ScopeRepositoryInterface::class)->getMock();
|
||||||
$scopeEntity = new ScopeEntity();
|
|
||||||
$scopeRepositoryMock->method('finalizeScopes')->willReturnArgument(0);
|
$scopeRepositoryMock->method('finalizeScopes')->willReturnArgument(0);
|
||||||
|
|
||||||
$grant = new ImplicitGrant(new \DateInterval('PT10M'));
|
$grant = new ImplicitGrant(new \DateInterval('PT10M'));
|
||||||
@@ -313,7 +312,6 @@ class ImplicitGrantTest extends TestCase
|
|||||||
$accessTokenRepositoryMock->method('persistNewAccessToken')->willReturnSelf();
|
$accessTokenRepositoryMock->method('persistNewAccessToken')->willReturnSelf();
|
||||||
|
|
||||||
$scopeRepositoryMock = $this->getMockBuilder(ScopeRepositoryInterface::class)->getMock();
|
$scopeRepositoryMock = $this->getMockBuilder(ScopeRepositoryInterface::class)->getMock();
|
||||||
$scopeEntity = new ScopeEntity();
|
|
||||||
$scopeRepositoryMock->method('finalizeScopes')->willReturnArgument(0);
|
$scopeRepositoryMock->method('finalizeScopes')->willReturnArgument(0);
|
||||||
|
|
||||||
$grant = new ImplicitGrant(new \DateInterval('PT10M'));
|
$grant = new ImplicitGrant(new \DateInterval('PT10M'));
|
||||||
@@ -339,7 +337,6 @@ class ImplicitGrantTest extends TestCase
|
|||||||
$accessTokenRepositoryMock->expects($this->at(1))->method('persistNewAccessToken')->willReturnSelf();
|
$accessTokenRepositoryMock->expects($this->at(1))->method('persistNewAccessToken')->willReturnSelf();
|
||||||
|
|
||||||
$scopeRepositoryMock = $this->getMockBuilder(ScopeRepositoryInterface::class)->getMock();
|
$scopeRepositoryMock = $this->getMockBuilder(ScopeRepositoryInterface::class)->getMock();
|
||||||
$scopeEntity = new ScopeEntity();
|
|
||||||
$scopeRepositoryMock->method('finalizeScopes')->willReturnArgument(0);
|
$scopeRepositoryMock->method('finalizeScopes')->willReturnArgument(0);
|
||||||
|
|
||||||
$grant = new ImplicitGrant(new \DateInterval('PT10M'));
|
$grant = new ImplicitGrant(new \DateInterval('PT10M'));
|
||||||
@@ -368,7 +365,6 @@ class ImplicitGrantTest extends TestCase
|
|||||||
$accessTokenRepositoryMock->method('persistNewAccessToken')->willThrowException(OAuthServerException::serverError('something bad happened'));
|
$accessTokenRepositoryMock->method('persistNewAccessToken')->willThrowException(OAuthServerException::serverError('something bad happened'));
|
||||||
|
|
||||||
$scopeRepositoryMock = $this->getMockBuilder(ScopeRepositoryInterface::class)->getMock();
|
$scopeRepositoryMock = $this->getMockBuilder(ScopeRepositoryInterface::class)->getMock();
|
||||||
$scopeEntity = new ScopeEntity();
|
|
||||||
$scopeRepositoryMock->method('finalizeScopes')->willReturnArgument(0);
|
$scopeRepositoryMock->method('finalizeScopes')->willReturnArgument(0);
|
||||||
|
|
||||||
$grant = new ImplicitGrant(new \DateInterval('PT10M'));
|
$grant = new ImplicitGrant(new \DateInterval('PT10M'));
|
||||||
@@ -397,7 +393,6 @@ class ImplicitGrantTest extends TestCase
|
|||||||
$accessTokenRepositoryMock->method('persistNewAccessToken')->willThrowException(UniqueTokenIdentifierConstraintViolationException::create());
|
$accessTokenRepositoryMock->method('persistNewAccessToken')->willThrowException(UniqueTokenIdentifierConstraintViolationException::create());
|
||||||
|
|
||||||
$scopeRepositoryMock = $this->getMockBuilder(ScopeRepositoryInterface::class)->getMock();
|
$scopeRepositoryMock = $this->getMockBuilder(ScopeRepositoryInterface::class)->getMock();
|
||||||
$scopeEntity = new ScopeEntity();
|
|
||||||
$scopeRepositoryMock->method('finalizeScopes')->willReturnArgument(0);
|
$scopeRepositoryMock->method('finalizeScopes')->willReturnArgument(0);
|
||||||
|
|
||||||
$grant = new ImplicitGrant(new \DateInterval('PT10M'));
|
$grant = new ImplicitGrant(new \DateInterval('PT10M'));
|
||||||
|
@@ -104,7 +104,7 @@ class AuthorizationServerMiddlewareTest extends TestCase
|
|||||||
$response = $exception->generateHttpResponse(new Response());
|
$response = $exception->generateHttpResponse(new Response());
|
||||||
|
|
||||||
$this->assertEquals(302, $response->getStatusCode());
|
$this->assertEquals(302, $response->getStatusCode());
|
||||||
$this->assertEquals('http://foo/bar?error=invalid_scope&message=The+requested+scope+is+invalid%2C+unknown%2C+or+malformed&hint=Check+the+%60test%60+scope',
|
$this->assertEquals('http://foo/bar?error=invalid_scope&error_description=The+requested+scope+is+invalid%2C+unknown%2C+or+malformed&hint=Check+the+%60test%60+scope&message=The+requested+scope+is+invalid%2C+unknown%2C+or+malformed',
|
||||||
$response->getHeader('location')[0]);
|
$response->getHeader('location')[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,7 +114,7 @@ class AuthorizationServerMiddlewareTest extends TestCase
|
|||||||
$response = $exception->generateHttpResponse(new Response(), true);
|
$response = $exception->generateHttpResponse(new Response(), true);
|
||||||
|
|
||||||
$this->assertEquals(302, $response->getStatusCode());
|
$this->assertEquals(302, $response->getStatusCode());
|
||||||
$this->assertEquals('http://foo/bar#error=invalid_scope&message=The+requested+scope+is+invalid%2C+unknown%2C+or+malformed&hint=Check+the+%60test%60+scope',
|
$this->assertEquals('http://foo/bar#error=invalid_scope&error_description=The+requested+scope+is+invalid%2C+unknown%2C+or+malformed&hint=Check+the+%60test%60+scope&message=The+requested+scope+is+invalid%2C+unknown%2C+or+malformed',
|
||||||
$response->getHeader('location')[0]);
|
$response->getHeader('location')[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user