Merge pull request #965 from ceeram/add-previous

Include previous exception in catch and throw
This commit is contained in:
Andrew Millington 2018-11-13 12:44:43 +00:00 committed by GitHub
commit efa8ef6fce
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 46 additions and 21 deletions

View File

@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
### Added ### Added
- Added a ScopeTrait to provide an implementation for jsonSerialize (PR #952) - Added a ScopeTrait to provide an implementation for jsonSerialize (PR #952)
- Ability to nest exceptions (PR #965)
### Fixed ### Fixed
- Fix issue where AuthorizationServer is not stateless as ResponseType could store state of a previous request (PR #960) - Fix issue where AuthorizationServer is not stateless as ResponseType could store state of a previous request (PR #960)

View File

@ -73,7 +73,7 @@ class BearerTokenValidator implements AuthorizationValidatorInterface
throw OAuthServerException::accessDenied('Access token could not be verified'); throw OAuthServerException::accessDenied('Access token could not be verified');
} }
} catch (BadMethodCallException $exception) { } catch (BadMethodCallException $exception) {
throw OAuthServerException::accessDenied('Access token is not signed'); throw OAuthServerException::accessDenied('Access token is not signed', null, $exception);
} }
// Ensure access token hasn't expired // Ensure access token hasn't expired
@ -97,10 +97,10 @@ class BearerTokenValidator implements AuthorizationValidatorInterface
->withAttribute('oauth_scopes', $token->getClaim('scopes')); ->withAttribute('oauth_scopes', $token->getClaim('scopes'));
} catch (InvalidArgumentException $exception) { } catch (InvalidArgumentException $exception) {
// JWT couldn't be parsed so return the request as is // JWT couldn't be parsed so return the request as is
throw OAuthServerException::accessDenied($exception->getMessage()); throw OAuthServerException::accessDenied($exception->getMessage(), null, $exception);
} catch (RuntimeException $exception) { } catch (RuntimeException $exception) {
//JWR couldn't be parsed so return the request as is //JWR couldn't be parsed so return the request as is
throw OAuthServerException::accessDenied('Error while decoding to JSON'); throw OAuthServerException::accessDenied('Error while decoding to JSON', null, $exception);
} }
} }
} }

View File

@ -41,7 +41,7 @@ trait CryptTrait
return Crypto::encryptWithPassword($unencryptedData, $this->encryptionKey); return Crypto::encryptWithPassword($unencryptedData, $this->encryptionKey);
} catch (Exception $e) { } catch (Exception $e) {
throw new LogicException($e->getMessage()); throw new LogicException($e->getMessage(), null, $e);
} }
} }
@ -63,7 +63,7 @@ trait CryptTrait
return Crypto::decryptWithPassword($encryptedData, $this->encryptionKey); return Crypto::decryptWithPassword($encryptedData, $this->encryptionKey);
} catch (Exception $e) { } catch (Exception $e) {
throw new LogicException($e->getMessage()); throw new LogicException($e->getMessage(), null, $e);
} }
} }

View File

@ -11,6 +11,7 @@ namespace League\OAuth2\Server\Exception;
use Exception; use Exception;
use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ResponseInterface;
use Throwable;
class OAuthServerException extends Exception class OAuthServerException extends Exception
{ {
@ -48,10 +49,11 @@ class OAuthServerException extends Exception
* @param int $httpStatusCode HTTP status code to send (default = 400) * @param int $httpStatusCode HTTP status code to send (default = 400)
* @param null|string $hint A helper hint * @param null|string $hint A helper hint
* @param null|string $redirectUri A HTTP URI to redirect the user back to * @param null|string $redirectUri A HTTP URI to redirect the user back to
* @param Throwable $previous Previous exception
*/ */
public function __construct($message, $code, $errorType, $httpStatusCode = 400, $hint = null, $redirectUri = null) public function __construct($message, $code, $errorType, $httpStatusCode = 400, $hint = null, $redirectUri = null, Throwable $previous = null)
{ {
parent::__construct($message, $code); parent::__construct($message, $code, $previous);
$this->httpStatusCode = $httpStatusCode; $this->httpStatusCode = $httpStatusCode;
$this->errorType = $errorType; $this->errorType = $errorType;
$this->hint = $hint; $this->hint = $hint;
@ -103,16 +105,17 @@ class OAuthServerException extends Exception
* *
* @param string $parameter The invalid parameter * @param string $parameter The invalid parameter
* @param null|string $hint * @param null|string $hint
* @param Throwable $previous Previous exception
* *
* @return static * @return static
*/ */
public static function invalidRequest($parameter, $hint = null) public static function invalidRequest($parameter, $hint = null, Throwable $previous = null)
{ {
$errorMessage = 'The request is missing a required parameter, includes an invalid parameter value, ' . $errorMessage = 'The request is missing a required parameter, includes an invalid parameter value, ' .
'includes a parameter more than once, or is otherwise malformed.'; 'includes a parameter more than once, or is otherwise malformed.';
$hint = ($hint === null) ? sprintf('Check the `%s` parameter', $parameter) : $hint; $hint = ($hint === null) ? sprintf('Check the `%s` parameter', $parameter) : $hint;
return new static($errorMessage, 3, 'invalid_request', 400, $hint); return new static($errorMessage, 3, 'invalid_request', 400, $hint, null, $previous);
} }
/** /**
@ -165,19 +168,21 @@ class OAuthServerException extends Exception
* Server error. * Server error.
* *
* @param string $hint * @param string $hint
* @param Throwable $previous
* *
* @return static * @return static
* *
* @codeCoverageIgnore * @codeCoverageIgnore
*/ */
public static function serverError($hint) public static function serverError($hint, Throwable $previous = null)
{ {
return new static( return new static(
'The authorization server encountered an unexpected condition which prevented it from fulfilling' 'The authorization server encountered an unexpected condition which prevented it from fulfilling'
. ' the request: ' . $hint, . ' the request: ' . $hint,
7, 7,
'server_error', 'server_error',
500 500,
$previous
); );
} }
@ -185,12 +190,13 @@ class OAuthServerException extends Exception
* Invalid refresh token. * Invalid refresh token.
* *
* @param null|string $hint * @param null|string $hint
* @param Throwable $previous
* *
* @return static * @return static
*/ */
public static function invalidRefreshToken($hint = null) public static function invalidRefreshToken($hint = null, Throwable $previous = null)
{ {
return new static('The refresh token is invalid.', 8, 'invalid_request', 401, $hint); return new static('The refresh token is invalid.', 8, 'invalid_request', 401, $hint, null, $previous);
} }
/** /**
@ -198,10 +204,11 @@ class OAuthServerException extends Exception
* *
* @param null|string $hint * @param null|string $hint
* @param null|string $redirectUri * @param null|string $redirectUri
* @param Throwable $previous
* *
* @return static * @return static
*/ */
public static function accessDenied($hint = null, $redirectUri = null) public static function accessDenied($hint = null, $redirectUri = null, Throwable $previous = null)
{ {
return new static( return new static(
'The resource owner or authorization server denied the request.', 'The resource owner or authorization server denied the request.',
@ -209,7 +216,8 @@ class OAuthServerException extends Exception
'access_denied', 'access_denied',
401, 401,
$hint, $hint,
$redirectUri $redirectUri,
$previous
); );
} }

View File

@ -511,12 +511,12 @@ abstract class AbstractGrant implements GrantTypeInterface
return bin2hex(random_bytes($length)); return bin2hex(random_bytes($length));
// @codeCoverageIgnoreStart // @codeCoverageIgnoreStart
} catch (TypeError $e) { } catch (TypeError $e) {
throw OAuthServerException::serverError('An unexpected error has occurred'); throw OAuthServerException::serverError('An unexpected error has occurred', $e);
} catch (Error $e) { } catch (Error $e) {
throw OAuthServerException::serverError('An unexpected error has occurred'); throw OAuthServerException::serverError('An unexpected error has occurred', $e);
} catch (Exception $e) { } catch (Exception $e) {
// If you get this message, the CSPRNG failed hard. // If you get this message, the CSPRNG failed hard.
throw OAuthServerException::serverError('Could not generate a random string'); throw OAuthServerException::serverError('Could not generate a random string', $e);
} }
// @codeCoverageIgnoreEnd // @codeCoverageIgnoreEnd
} }

View File

@ -96,7 +96,7 @@ class AuthCodeGrant extends AbstractAuthorizeGrant
$authCodePayload->user_id $authCodePayload->user_id
); );
} catch (LogicException $e) { } catch (LogicException $e) {
throw OAuthServerException::invalidRequest('code', 'Cannot decrypt the authorization code'); throw OAuthServerException::invalidRequest('code', 'Cannot decrypt the authorization code', $e);
} }
// Validate code challenge // Validate code challenge

View File

@ -97,7 +97,7 @@ class RefreshTokenGrant extends AbstractGrant
try { try {
$refreshToken = $this->decrypt($encryptedRefreshToken); $refreshToken = $this->decrypt($encryptedRefreshToken);
} catch (Exception $e) { } catch (Exception $e) {
throw OAuthServerException::invalidRefreshToken('Cannot decrypt the refresh token'); throw OAuthServerException::invalidRefreshToken('Cannot decrypt the refresh token', $e);
} }
$refreshTokenData = json_decode($refreshToken, true); $refreshTokenData = json_decode($refreshToken, true);

View File

@ -2,6 +2,7 @@
namespace LeagueTests\Exception; namespace LeagueTests\Exception;
use Exception;
use League\OAuth2\Server\Exception\OAuthServerException; use League\OAuth2\Server\Exception\OAuthServerException;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
@ -20,4 +21,19 @@ class OAuthServerExceptionTest extends TestCase
$this->assertFalse($exceptionWithoutRedirect->hasRedirect()); $this->assertFalse($exceptionWithoutRedirect->hasRedirect());
} }
public function testHasPrevious()
{
$previous = new Exception('This is the previous');
$exceptionWithPrevious = OAuthServerException::accessDenied(null, null, $previous);
$this->assertSame('This is the previous', $exceptionWithPrevious->getPrevious()->getMessage());
}
public function testDoesNotHavePrevious()
{
$exceptionWithoutPrevious = OAuthServerException::accessDenied();
$this->assertNull($exceptionWithoutPrevious->getPrevious());
}
} }