Merge branch 'master' of github.com:erickjth/oauth2-server into fix-pkce-implementation

# Conflicts:
#	src/Grant/AuthCodeGrant.php
This commit is contained in:
Erick Torres 2017-09-07 17:24:48 -05:00
commit 4270f5bac1
10 changed files with 50 additions and 26 deletions

View File

@ -1,5 +1,17 @@
# Changelog # Changelog
## 6.0.2 (released 2017-08-03)
* An invalid refresh token that can't be decrypted now returns a HTTP 401 error instead of HTTP 400 (Issue #759)
* Removed chmod from CryptKey and add toggle to disable checking (Issue #776)
* Fixes invalid code challenge method payload key name (Issue #777)
## 6.0.1 (released 2017-07-19)
To address feedback from the security release the following change has been made:
* If an RSA key cannot be chmod'ed to 600 then it will now throw a E_USER_NOTICE instead of an exception.
## 6.0.0 (released 2017-07-01) ## 6.0.0 (released 2017-07-01)
* Breaking change: The `AuthorizationServer` constructor now expects an encryption key string instead of a public key * Breaking change: The `AuthorizationServer` constructor now expects an encryption key string instead of a public key

View File

@ -1,7 +1,7 @@
Thanks for contributing to this project. Thanks for contributing to this project.
**Please submit your pull request against the `develop` branch only.** **Please submit your pull request against the `master` branch only.**
Please ensure that you run `phpunit` from the project root after you've made any changes. Please ensure that you run `phpunit` from the project root after you've made any changes.

View File

@ -29,8 +29,9 @@ class CryptKey
/** /**
* @param string $keyPath * @param string $keyPath
* @param null|string $passPhrase * @param null|string $passPhrase
* @param bool $keyPermissionsCheck
*/ */
public function __construct($keyPath, $passPhrase = null) public function __construct($keyPath, $passPhrase = null, $keyPermissionsCheck = true)
{ {
if (preg_match(self::RSA_KEY_PATTERN, $keyPath)) { if (preg_match(self::RSA_KEY_PATTERN, $keyPath)) {
$keyPath = $this->saveKeyToFile($keyPath); $keyPath = $this->saveKeyToFile($keyPath);
@ -44,20 +45,15 @@ class CryptKey
throw new \LogicException(sprintf('Key path "%s" does not exist or is not readable', $keyPath)); throw new \LogicException(sprintf('Key path "%s" does not exist or is not readable', $keyPath));
} }
// Verify the permissions of the key if ($keyPermissionsCheck === true) {
$keyPathPerms = decoct(fileperms($keyPath) & 0777); // Verify the permissions of the key
if ($keyPathPerms !== '600') { $keyPathPerms = decoct(fileperms($keyPath) & 0777);
// Attempt to correct the permissions if (in_array($keyPathPerms, ['600', '660'], true) === false) {
if (chmod($keyPath, 0600) === false) { trigger_error(sprintf(
// @codeCoverageIgnoreStart 'Key file "%s" permissions are not correct, should be 600 or 660 instead of %s',
throw new \LogicException( $keyPath,
sprintf( $keyPathPerms
'Key file "%s" permissions are not correct, should be 600 instead of %s, unable to automatically resolve the issue', ), E_USER_NOTICE);
$keyPath,
$keyPathPerms
)
);
// @codeCoverageIgnoreEnd
} }
} }

View File

@ -152,7 +152,7 @@ class OAuthServerException extends \Exception
*/ */
public static function invalidRefreshToken($hint = null) public static function invalidRefreshToken($hint = null)
{ {
return new static('The refresh token is invalid.', 8, 'invalid_request', 400, $hint); return new static('The refresh token is invalid.', 8, 'invalid_request', 401, $hint);
} }
/** /**

View File

@ -323,14 +323,14 @@ class AuthCodeGrant extends AbstractAuthorizeGrant
); );
$payload = [ $payload = [
'client_id' => $authCode->getClient()->getIdentifier(), 'client_id' => $authCode->getClient()->getIdentifier(),
'redirect_uri' => $authCode->getRedirectUri(), 'redirect_uri' => $authCode->getRedirectUri(),
'auth_code_id' => $authCode->getIdentifier(), 'auth_code_id' => $authCode->getIdentifier(),
'scopes' => $authCode->getScopes(), 'scopes' => $authCode->getScopes(),
'user_id' => $authCode->getUserIdentifier(), 'user_id' => $authCode->getUserIdentifier(),
'expire_time' => (new \DateTime())->add($this->authCodeTTL)->format('U'), 'expire_time' => (new \DateTime())->add($this->authCodeTTL)->format('U'),
'code_challenge' => $authorizationRequest->getCodeChallenge(), 'code_challenge' => $authorizationRequest->getCodeChallenge(),
'code_challenge_method' => $authorizationRequest->getCodeChallengeMethod(), 'code_challenge_method' => $authorizationRequest->getCodeChallengeMethod(),
]; ];
$response = new RedirectResponse(); $response = new RedirectResponse();

View File

@ -200,7 +200,7 @@ class ImplicitGrant extends AbstractAuthorizeGrant
$finalRedirectUri, $finalRedirectUri,
[ [
'access_token' => (string) $accessToken->convertToJWT($this->privateKey), 'access_token' => (string) $accessToken->convertToJWT($this->privateKey),
'token_type' => 'bearer', 'token_type' => 'Bearer',
'expires_in' => $accessToken->getExpiryDateTime()->getTimestamp() - (new \DateTime())->getTimestamp(), 'expires_in' => $accessToken->getExpiryDateTime()->getTimestamp() - (new \DateTime())->getTimestamp(),
'state' => $authorizationRequest->getState(), 'state' => $authorizationRequest->getState(),
], ],

View File

@ -12,6 +12,7 @@ namespace League\OAuth2\Server\Repositories;
use League\OAuth2\Server\Entities\AccessTokenEntityInterface; use League\OAuth2\Server\Entities\AccessTokenEntityInterface;
use League\OAuth2\Server\Entities\ClientEntityInterface; use League\OAuth2\Server\Entities\ClientEntityInterface;
use League\OAuth2\Server\Entities\ScopeEntityInterface; use League\OAuth2\Server\Entities\ScopeEntityInterface;
use League\OAuth2\Server\Exception\UniqueTokenIdentifierConstraintViolationException;
/** /**
* Access token interface. * Access token interface.
@ -33,6 +34,8 @@ interface AccessTokenRepositoryInterface extends RepositoryInterface
* Persists a new access token to permanent storage. * Persists a new access token to permanent storage.
* *
* @param AccessTokenEntityInterface $accessTokenEntity * @param AccessTokenEntityInterface $accessTokenEntity
*
* @throws UniqueTokenIdentifierConstraintViolationException
*/ */
public function persistNewAccessToken(AccessTokenEntityInterface $accessTokenEntity); public function persistNewAccessToken(AccessTokenEntityInterface $accessTokenEntity);

View File

@ -10,6 +10,7 @@
namespace League\OAuth2\Server\Repositories; namespace League\OAuth2\Server\Repositories;
use League\OAuth2\Server\Entities\AuthCodeEntityInterface; use League\OAuth2\Server\Entities\AuthCodeEntityInterface;
use League\OAuth2\Server\Exception\UniqueTokenIdentifierConstraintViolationException;
/** /**
* Auth code storage interface. * Auth code storage interface.
@ -27,6 +28,8 @@ interface AuthCodeRepositoryInterface extends RepositoryInterface
* Persists a new auth code to permanent storage. * Persists a new auth code to permanent storage.
* *
* @param AuthCodeEntityInterface $authCodeEntity * @param AuthCodeEntityInterface $authCodeEntity
*
* @throws UniqueTokenIdentifierConstraintViolationException
*/ */
public function persistNewAuthCode(AuthCodeEntityInterface $authCodeEntity); public function persistNewAuthCode(AuthCodeEntityInterface $authCodeEntity);

View File

@ -10,6 +10,7 @@
namespace League\OAuth2\Server\Repositories; namespace League\OAuth2\Server\Repositories;
use League\OAuth2\Server\Entities\RefreshTokenEntityInterface; use League\OAuth2\Server\Entities\RefreshTokenEntityInterface;
use League\OAuth2\Server\Exception\UniqueTokenIdentifierConstraintViolationException;
/** /**
* Refresh token interface. * Refresh token interface.
@ -27,6 +28,8 @@ interface RefreshTokenRepositoryInterface extends RepositoryInterface
* Create a new refresh token_name. * Create a new refresh token_name.
* *
* @param RefreshTokenEntityInterface $refreshTokenEntity * @param RefreshTokenEntityInterface $refreshTokenEntity
*
* @throws UniqueTokenIdentifierConstraintViolationException
*/ */
public function persistNewRefreshToken(RefreshTokenEntityInterface $refreshTokenEntity); public function persistNewRefreshToken(RefreshTokenEntityInterface $refreshTokenEntity);

View File

@ -26,6 +26,13 @@ use Zend\Diactoros\ServerRequestFactory;
class AuthorizationServerTest extends \PHPUnit_Framework_TestCase class AuthorizationServerTest extends \PHPUnit_Framework_TestCase
{ {
public function setUp()
{
// Make sure the keys have the correct permissions.
chmod(__DIR__ . '/Stubs/private.key', 0600);
chmod(__DIR__ . '/Stubs/public.key', 0600);
}
public function testRespondToRequestInvalidGrantType() public function testRespondToRequestInvalidGrantType()
{ {
$server = new AuthorizationServer( $server = new AuthorizationServer(