Compare commits

..

20 Commits

Author SHA1 Message Date
Andrew Millington
4ab302a969 Fix capitalisation of inheritdoc 2019-08-31 19:10:59 +01:00
Andrew Millington
d40a37570c Add inherit docblocks to CryptKey 2019-08-31 19:06:05 +01:00
Andrew Millington
01d652ab29 Remove type hinting 2019-08-31 19:02:39 +01:00
Andrew Millington
f604109168 Update changelog 2019-08-31 18:59:03 +01:00
ErickSkrauch
7db4cdb875 Fix CS 2019-08-18 00:04:53 +03:00
ErickSkrauch
4673e7de89 Abstract CryptKey public methods to the CryptKeyInterface 2019-08-17 23:51:23 +03:00
Andrew Millington
0b0b43d433 Merge pull request #1035 from matt-allan/prevent-public-client-confidential-grant
Prevent public clients from using the client_credentials grant type
2019-07-25 19:20:11 +01:00
Andrew Millington
cd8742f630 Reword changelog 2019-07-25 19:14:08 +01:00
Andrew Millington
2097edd6eb Update changelog 2019-07-25 19:12:33 +01:00
Andrew Millington
705120c974 Add blank space to keep formatting consistent 2019-07-25 19:09:47 +01:00
Andrew Millington
8a78e00a2e Add blank line above throw 2019-07-25 19:04:44 +01:00
Matt Allan
3413c20590 Prevent public clients from using the client_credentials grant type
See https://tools.ietf.org/html/rfc6749#section-4.4.2
2019-07-22 18:21:29 -04:00
Andrew Millington
e1dc4d708c Update changelog for release of version 8 2019-07-13 19:58:26 +01:00
Andrew Millington
18dabd36e3 Remove branch 8.0.0 from travis checks 2019-07-13 19:56:44 +01:00
Andrew Millington
1a3107b4fc Merge pull request #1033 from thephpleague/8.0.0
8.0.0
2019-07-13 19:46:10 +01:00
Andrew Millington
1d9ca35fec Merge pull request #1032 from thephpleague/update-examples-for-version-8
Update Examples for Version 8
2019-07-13 19:39:38 +01:00
Andrew Millington
c7f998ee02 Add PR number for JTI PR to changelog 2019-07-13 18:03:24 +01:00
Andrew Millington
4b1c9ed503 Merge pull request #1031 from Sephster/remove-jti-from-header
Remove JTI Claim From JWT Header
2019-07-13 17:50:20 +01:00
Andrew Millington
dc3c74601a Update changelog 2019-07-13 17:52:35 +01:00
Andrew Millington
f5e910e6ec Remove jti replication from JWT Header 2019-07-13 17:51:56 +01:00
16 changed files with 90 additions and 44 deletions

View File

@@ -30,4 +30,3 @@ after_script:
branches:
only:
- master
- 8.0.0

View File

@@ -6,6 +6,15 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
## [Unreleased]
### Added (v9)
- A CryptKeyInterface to allow developers to change the CryptKey implementation with greater ease (PR #1044)
### Fixed
- Clients are now explicitly prevented from using the Client Credentials grant unless they are confidential to conform
with the OAuth2 spec (PR #1035)
## [8.0.0] - released 2019-07-13
### Added
- Flag, `requireCodeChallengeForPublicClients`, used to reject public clients that do not provide a code challenge for the Auth Code Grant; use AuthCodeGrant::disableRequireCodeCallengeForPublicClients() to turn off this requirement (PR #938)
- Public clients can now use the Auth Code Grant (PR #938)
@@ -25,6 +34,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
### Removed
- `enableCodeExchangeProof` flag (PR #938)
- Support for PHP 7.0 (PR #1014)
- Remove JTI claim from JWT header (PR #1031)
## [7.4.0] - released 2019-05-05
@@ -465,7 +475,8 @@ Version 5 is a complete code rewrite.
- First major release
[Unreleased]: https://github.com/thephpleague/oauth2-server/compare/7.4.0...HEAD
[Unreleased]: https://github.com/thephpleague/oauth2-server/compare/8.0.0...HEAD
[8.0.0]: https://github.com/thephpleague/oauth2-server/compare/7.4.0...8.0.0
[7.4.0]: https://github.com/thephpleague/oauth2-server/compare/7.3.3...7.4.0
[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

View File

@@ -40,12 +40,12 @@ class AuthorizationServer implements EmitterAwareInterface
protected $grantTypeAccessTokenTTL = [];
/**
* @var CryptKey
* @var CryptKeyInterface
*/
protected $privateKey;
/**
* @var CryptKey
* @var CryptKeyInterface
*/
protected $publicKey;
@@ -85,7 +85,7 @@ class AuthorizationServer implements EmitterAwareInterface
* @param ClientRepositoryInterface $clientRepository
* @param AccessTokenRepositoryInterface $accessTokenRepository
* @param ScopeRepositoryInterface $scopeRepository
* @param CryptKey|string $privateKey
* @param CryptKeyInterface|string $privateKey
* @param string|Key $encryptionKey
* @param null|ResponseTypeInterface $responseType
*/
@@ -101,7 +101,7 @@ class AuthorizationServer implements EmitterAwareInterface
$this->accessTokenRepository = $accessTokenRepository;
$this->scopeRepository = $scopeRepository;
if ($privateKey instanceof CryptKey === false) {
if ($privateKey instanceof CryptKeyInterface === false) {
$privateKey = new CryptKey($privateKey);
}

View File

@@ -14,7 +14,7 @@ use InvalidArgumentException;
use Lcobucci\JWT\Parser;
use Lcobucci\JWT\Signer\Rsa\Sha256;
use Lcobucci\JWT\ValidationData;
use League\OAuth2\Server\CryptKey;
use League\OAuth2\Server\CryptKeyInterface;
use League\OAuth2\Server\CryptTrait;
use League\OAuth2\Server\Exception\OAuthServerException;
use League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface;
@@ -31,7 +31,7 @@ class BearerTokenValidator implements AuthorizationValidatorInterface
private $accessTokenRepository;
/**
* @var CryptKey
* @var CryptKeyInterface
*/
protected $publicKey;
@@ -46,9 +46,9 @@ class BearerTokenValidator implements AuthorizationValidatorInterface
/**
* Set the public key
*
* @param CryptKey $key
* @param CryptKeyInterface $key
*/
public function setPublicKey(CryptKey $key)
public function setPublicKey(CryptKeyInterface $key)
{
$this->publicKey = $key;
}

View File

@@ -14,7 +14,7 @@ namespace League\OAuth2\Server;
use LogicException;
use RuntimeException;
class CryptKey
class CryptKey implements CryptKeyInterface
{
const RSA_KEY_PATTERN =
'/^(-----BEGIN (RSA )?(PUBLIC|PRIVATE) KEY-----)\R.*(-----END (RSA )?(PUBLIC|PRIVATE) KEY-----)\R?$/s';
@@ -102,9 +102,7 @@ class CryptKey
}
/**
* Retrieve key path.
*
* @return string
* {@inheritdoc}
*/
public function getKeyPath()
{
@@ -112,9 +110,7 @@ class CryptKey
}
/**
* Retrieve key pass phrase.
*
* @return null|string
* {@inheritdoc}
*/
public function getPassPhrase()
{

20
src/CryptKeyInterface.php Normal file
View File

@@ -0,0 +1,20 @@
<?php
namespace League\OAuth2\Server;
interface CryptKeyInterface
{
/**
* Retrieve key path.
*
* @return string
*/
public function getKeyPath();
/**
* Retrieve key pass phrase.
*
* @return null|string
*/
public function getPassPhrase();
}

View File

@@ -9,14 +9,14 @@
namespace League\OAuth2\Server\Entities;
use League\OAuth2\Server\CryptKey;
use League\OAuth2\Server\CryptKeyInterface;
interface AccessTokenEntityInterface extends TokenInterface
{
/**
* Set a private key used to encrypt the access token.
*/
public function setPrivateKey(CryptKey $privateKey);
public function setPrivateKey(CryptKeyInterface $privateKey);
/**
* Generate a string representation of the access token.

View File

@@ -14,21 +14,21 @@ use Lcobucci\JWT\Builder;
use Lcobucci\JWT\Signer\Key;
use Lcobucci\JWT\Signer\Rsa\Sha256;
use Lcobucci\JWT\Token;
use League\OAuth2\Server\CryptKey;
use League\OAuth2\Server\CryptKeyInterface;
use League\OAuth2\Server\Entities\ClientEntityInterface;
use League\OAuth2\Server\Entities\ScopeEntityInterface;
trait AccessTokenTrait
{
/**
* @var CryptKey
* @var CryptKeyInterface
*/
private $privateKey;
/**
* Set the private key used to encrypt this access token.
*/
public function setPrivateKey(CryptKey $privateKey)
public function setPrivateKey(CryptKeyInterface $privateKey)
{
$this->privateKey = $privateKey;
}
@@ -36,15 +36,15 @@ trait AccessTokenTrait
/**
* Generate a JWT from the access token
*
* @param CryptKey $privateKey
* @param CryptKeyInterface $privateKey
*
* @return Token
*/
private function convertToJWT(CryptKey $privateKey)
private function convertToJWT(CryptKeyInterface $privateKey)
{
return (new Builder())
->setAudience($this->getClient()->getIdentifier())
->setId($this->getIdentifier(), true)
->setId($this->getIdentifier())
->setIssuedAt(time())
->setNotBefore(time())
->setExpiration($this->getExpiryDateTime()->getTimestamp())

View File

@@ -15,7 +15,7 @@ use DateTimeImmutable;
use Error;
use Exception;
use League\Event\EmitterAwareTrait;
use League\OAuth2\Server\CryptKey;
use League\OAuth2\Server\CryptKeyInterface;
use League\OAuth2\Server\CryptTrait;
use League\OAuth2\Server\Entities\AccessTokenEntityInterface;
use League\OAuth2\Server\Entities\AuthCodeEntityInterface;
@@ -83,7 +83,7 @@ abstract class AbstractGrant implements GrantTypeInterface
protected $refreshTokenTTL;
/**
* @var CryptKey
* @var CryptKeyInterface
*/
protected $privateKey;
@@ -151,9 +151,9 @@ abstract class AbstractGrant implements GrantTypeInterface
/**
* Set the private key
*
* @param CryptKey $key
* @param CryptKeyInterface $key
*/
public function setPrivateKey(CryptKey $key)
public function setPrivateKey(CryptKeyInterface $key)
{
$this->privateKey = $key;
}

View File

@@ -12,6 +12,7 @@
namespace League\OAuth2\Server\Grant;
use DateInterval;
use League\OAuth2\Server\Exception\OAuthServerException;
use League\OAuth2\Server\RequestEvent;
use League\OAuth2\Server\ResponseTypes\ResponseTypeInterface;
use Psr\Http\Message\ServerRequestInterface;
@@ -29,8 +30,19 @@ class ClientCredentialsGrant extends AbstractGrant
ResponseTypeInterface $responseType,
DateInterval $accessTokenTTL
) {
list($clientId) = $this->getClientCredentials($request);
$client = $this->getClientEntityOrFail($clientId, $request);
if (!$client->isConfidential()) {
$this->getEmitter()->emit(new RequestEvent(RequestEvent::CLIENT_AUTHENTICATION_FAILED, $request));
throw OAuthServerException::invalidClient($request);
}
// Validate request
$client = $this->validateClient($request);
$this->validateClient($request);
$scopes = $this->validateScopes($this->getRequestParameter('scope', $request, $this->defaultScope));
// Finalize the requested scopes

View File

@@ -14,7 +14,7 @@ namespace League\OAuth2\Server\Grant;
use DateInterval;
use Defuse\Crypto\Key;
use League\Event\EmitterAwareInterface;
use League\OAuth2\Server\CryptKey;
use League\OAuth2\Server\CryptKeyInterface;
use League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface;
use League\OAuth2\Server\Repositories\ClientRepositoryInterface;
use League\OAuth2\Server\Repositories\ScopeRepositoryInterface;
@@ -131,9 +131,9 @@ interface GrantTypeInterface extends EmitterAwareInterface
/**
* Set the path to the private key.
*
* @param CryptKey $privateKey
* @param CryptKeyInterface $privateKey
*/
public function setPrivateKey(CryptKey $privateKey);
public function setPrivateKey(CryptKeyInterface $privateKey);
/**
* Set the encryption key

View File

@@ -23,7 +23,7 @@ class ResourceServer
private $accessTokenRepository;
/**
* @var CryptKey
* @var CryptKeyInterface
*/
private $publicKey;
@@ -36,7 +36,7 @@ class ResourceServer
* New server instance.
*
* @param AccessTokenRepositoryInterface $accessTokenRepository
* @param CryptKey|string $publicKey
* @param CryptKeyInterface|string $publicKey
* @param null|AuthorizationValidatorInterface $authorizationValidator
*/
public function __construct(
@@ -46,7 +46,7 @@ class ResourceServer
) {
$this->accessTokenRepository = $accessTokenRepository;
if ($publicKey instanceof CryptKey === false) {
if ($publicKey instanceof CryptKeyInterface === false) {
$publicKey = new CryptKey($publicKey);
}
$this->publicKey = $publicKey;

View File

@@ -11,7 +11,7 @@
namespace League\OAuth2\Server\ResponseTypes;
use League\OAuth2\Server\CryptKey;
use League\OAuth2\Server\CryptKeyInterface;
use League\OAuth2\Server\CryptTrait;
use League\OAuth2\Server\Entities\AccessTokenEntityInterface;
use League\OAuth2\Server\Entities\RefreshTokenEntityInterface;
@@ -31,7 +31,7 @@ abstract class AbstractResponseType implements ResponseTypeInterface
protected $refreshToken;
/**
* @var CryptKey
* @var CryptKeyInterface
*/
protected $privateKey;
@@ -54,9 +54,9 @@ abstract class AbstractResponseType implements ResponseTypeInterface
/**
* Set the private key
*
* @param CryptKey $key
* @param CryptKeyInterface $key
*/
public function setPrivateKey(CryptKey $key)
public function setPrivateKey(CryptKeyInterface $key)
{
$this->privateKey = $key;
}

View File

@@ -4,7 +4,7 @@ namespace LeagueTests;
use DateInterval;
use League\OAuth2\Server\AuthorizationServer;
use League\OAuth2\Server\CryptKey;
use League\OAuth2\Server\CryptKeyInterface;
use League\OAuth2\Server\Exception\OAuthServerException;
use League\OAuth2\Server\Grant\AuthCodeGrant;
use League\OAuth2\Server\Grant\ClientCredentialsGrant;
@@ -62,8 +62,11 @@ class AuthorizationServerTest extends TestCase
public function testRespondToRequest()
{
$client = new ClientEntity();
$client->setConfidential();
$clientRepository = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
$clientRepository->method('getClientEntity')->willReturn(new ClientEntity());
$clientRepository->method('getClientEntity')->willReturn($client);
$scope = new ScopeEntity();
$scopeRepositoryMock = $this->getMockBuilder(ScopeRepositoryInterface::class)->getMock();
@@ -150,7 +153,7 @@ class AuthorizationServerTest extends TestCase
$encryptionKey = 'file://' . __DIR__ . '/Stubs/public.key';
$responseTypePrototype = new class extends BearerTokenResponse {
/* @return null|CryptKey */
/* @return null|CryptKeyInterface */
public function getPrivateKey()
{
return $this->privateKey;

View File

@@ -29,6 +29,8 @@ class ClientCredentialsGrantTest extends TestCase
public function testRespondToRequest()
{
$client = new ClientEntity();
$client->setConfidential();
$clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
$clientRepositoryMock->method('getClientEntity')->willReturn($client);

View File

@@ -24,8 +24,11 @@ class AuthorizationServerMiddlewareTest extends TestCase
public function testValidResponse()
{
$client = new ClientEntity();
$client->setConfidential();
$clientRepository = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
$clientRepository->method('getClientEntity')->willReturn(new ClientEntity());
$clientRepository->method('getClientEntity')->willReturn($client);
$scopeEntity = new ScopeEntity;
$scopeRepositoryMock = $this->getMockBuilder(ScopeRepositoryInterface::class)->getMock();