Skip to content

Commit

Permalink
Track constraint on violations
Browse files Browse the repository at this point in the history
This provides more information to users, which is useful when debugging
a violations list.

Signed-off-by: Luís Cobucci <[email protected]>
  • Loading branch information
lcobucci committed Aug 17, 2022
1 parent 587cb9b commit 8f7f2c2
Show file tree
Hide file tree
Showing 28 changed files with 107 additions and 26 deletions.
9 changes: 6 additions & 3 deletions src/Validation/Constraint/HasClaimWithValue.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,17 +31,20 @@ public function __construct(string $claim, $expectedValue)
public function assert(Token $token): void
{
if (! $token instanceof UnencryptedToken) {
throw new ConstraintViolation('You should pass a plain token');
throw ConstraintViolation::error('You should pass a plain token', $this);
}

$claims = $token->claims();

if (! $claims->has($this->claim)) {
throw new ConstraintViolation('The token does not have the claim "' . $this->claim . '"');
throw ConstraintViolation::error('The token does not have the claim "' . $this->claim . '"', $this);
}

if ($claims->get($this->claim) !== $this->expectedValue) {
throw new ConstraintViolation('The claim "' . $this->claim . '" does not have the expected value');
throw ConstraintViolation::error(
'The claim "' . $this->claim . '" does not have the expected value',
$this
);
}
}
}
5 changes: 3 additions & 2 deletions src/Validation/Constraint/IdentifiedBy.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@ public function __construct(string $id)
public function assert(Token $token): void
{
if (! $token->isIdentifiedBy($this->id)) {
throw new ConstraintViolation(
'The token is not identified with the expected ID'
throw ConstraintViolation::error(
'The token is not identified with the expected ID',
$this
);
}
}
Expand Down
5 changes: 3 additions & 2 deletions src/Validation/Constraint/IssuedBy.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@ public function __construct(string ...$issuers)
public function assert(Token $token): void
{
if (! $token->hasBeenIssuedBy(...$this->issuers)) {
throw new ConstraintViolation(
'The token was not issued by the given issuers'
throw ConstraintViolation::error(
'The token was not issued by the given issuers',
$this
);
}
}
Expand Down
6 changes: 3 additions & 3 deletions src/Validation/Constraint/LooseValidAt.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,23 +47,23 @@ public function assert(Token $token): void
private function assertExpiration(Token $token, DateTimeInterface $now): void
{
if ($token->isExpired($now)) {
throw new ConstraintViolation('The token is expired');
throw ConstraintViolation::error('The token is expired', $this);
}
}

/** @throws ConstraintViolation */
private function assertMinimumTime(Token $token, DateTimeInterface $now): void
{
if (! $token->isMinimumTimeBefore($now)) {
throw new ConstraintViolation('The token cannot be used yet');
throw ConstraintViolation::error('The token cannot be used yet', $this);
}
}

/** @throws ConstraintViolation */
private function assertIssueTime(Token $token, DateTimeInterface $now): void
{
if (! $token->hasBeenIssuedBefore($now)) {
throw new ConstraintViolation('The token was issued in the future');
throw ConstraintViolation::error('The token was issued in the future', $this);
}
}
}
5 changes: 3 additions & 2 deletions src/Validation/Constraint/PermittedFor.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@ public function __construct(string $audience)
public function assert(Token $token): void
{
if (! $token->isPermittedFor($this->audience)) {
throw new ConstraintViolation(
'The token is not allowed to be used by this audience'
throw ConstraintViolation::error(
'The token is not allowed to be used by this audience',
$this
);
}
}
Expand Down
5 changes: 3 additions & 2 deletions src/Validation/Constraint/RelatedTo.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@ public function __construct(string $subject)
public function assert(Token $token): void
{
if (! $token->isRelatedTo($this->subject)) {
throw new ConstraintViolation(
'The token is not related to the expected subject'
throw ConstraintViolation::error(
'The token is not related to the expected subject',
$this
);
}
}
Expand Down
6 changes: 3 additions & 3 deletions src/Validation/Constraint/SignedWith.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,15 @@ public function __construct(Signer $signer, Signer\Key $key)
public function assert(Token $token): void
{
if (! $token instanceof UnencryptedToken) {
throw new ConstraintViolation('You should pass a plain token');
throw ConstraintViolation::error('You should pass a plain token', $this);
}

if ($token->headers()->get('alg') !== $this->signer->algorithmId()) {
throw new ConstraintViolation('Token signer mismatch');
throw ConstraintViolation::error('Token signer mismatch', $this);
}

if (! $this->signer->verify($token->signature()->hash(), $token->payload(), $this->key)) {
throw new ConstraintViolation('Token signature mismatch');
throw ConstraintViolation::error('Token signature mismatch', $this);
}
}
}
14 changes: 7 additions & 7 deletions src/Validation/Constraint/StrictValidAt.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ private function guardLeeway(?DateInterval $leeway): DateInterval
public function assert(Token $token): void
{
if (! $token instanceof UnencryptedToken) {
throw new ConstraintViolation('You should pass a plain token');
throw ConstraintViolation::error('You should pass a plain token', $this);
}

$now = $this->clock->now();
Expand All @@ -52,35 +52,35 @@ public function assert(Token $token): void
private function assertExpiration(UnencryptedToken $token, DateTimeInterface $now): void
{
if (! $token->claims()->has(Token\RegisteredClaims::EXPIRATION_TIME)) {
throw new ConstraintViolation('"Expiration Time" claim missing');
throw ConstraintViolation::error('"Expiration Time" claim missing', $this);
}

if ($token->isExpired($now)) {
throw new ConstraintViolation('The token is expired');
throw ConstraintViolation::error('The token is expired', $this);
}
}

/** @throws ConstraintViolation */
private function assertMinimumTime(UnencryptedToken $token, DateTimeInterface $now): void
{
if (! $token->claims()->has(Token\RegisteredClaims::NOT_BEFORE)) {
throw new ConstraintViolation('"Not Before" claim missing');
throw ConstraintViolation::error('"Not Before" claim missing', $this);
}

if (! $token->isMinimumTimeBefore($now)) {
throw new ConstraintViolation('The token cannot be used yet');
throw ConstraintViolation::error('The token cannot be used yet', $this);
}
}

/** @throws ConstraintViolation */
private function assertIssueTime(UnencryptedToken $token, DateTimeInterface $now): void
{
if (! $token->claims()->has(Token\RegisteredClaims::ISSUED_AT)) {
throw new ConstraintViolation('"Issued At" claim missing');
throw ConstraintViolation::error('"Issued At" claim missing', $this);
}

if (! $token->hasBeenIssuedBefore($now)) {
throw new ConstraintViolation('The token was issued in the future');
throw ConstraintViolation::error('The token was issued in the future', $this);
}
}
}
15 changes: 15 additions & 0 deletions src/Validation/ConstraintViolation.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,21 @@
use Lcobucci\JWT\Exception;
use RuntimeException;

use function get_class;

final class ConstraintViolation extends RuntimeException implements Exception
{
/**
* @readonly
* @var class-string<Constraint>|null
*/
public ?string $constraint = null;

public static function error(string $message, Constraint $constraint): self
{
$exception = new self($message);
$exception->constraint = get_class($constraint);

return $exception;
}
}
1 change: 1 addition & 0 deletions test/functional/ES512TokenTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
* @covers \Lcobucci\JWT\Signer\OpenSSL
* @covers \Lcobucci\JWT\SodiumBase64Polyfill
* @covers \Lcobucci\JWT\Validation\Validator
* @covers \Lcobucci\JWT\Validation\ConstraintViolation
* @covers \Lcobucci\JWT\Validation\RequiredConstraintsViolated
* @covers \Lcobucci\JWT\Validation\Constraint\SignedWith
*/
Expand Down
3 changes: 1 addition & 2 deletions test/functional/EcdsaTokenTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,9 @@
* @covers \Lcobucci\JWT\Signer\OpenSSL
* @covers \Lcobucci\JWT\SodiumBase64Polyfill
* @covers \Lcobucci\JWT\Validation\Validator
* @covers \Lcobucci\JWT\Validation\ConstraintViolation
* @covers \Lcobucci\JWT\Validation\Constraint\SignedWith
* @covers \Lcobucci\JWT\Validation\Validator
* @covers \Lcobucci\JWT\Validation\RequiredConstraintsViolated
* @covers \Lcobucci\JWT\Validation\Constraint\SignedWith
*/
class EcdsaTokenTest extends TestCase
{
Expand Down
1 change: 1 addition & 0 deletions test/functional/EddsaTokenTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
* @covers \Lcobucci\JWT\Validation\Validator
* @covers \Lcobucci\JWT\Validation\Constraint\SignedWith
* @covers \Lcobucci\JWT\Validation\Validator
* @covers \Lcobucci\JWT\Validation\ConstraintViolation
* @covers \Lcobucci\JWT\Validation\RequiredConstraintsViolated
* @covers \Lcobucci\JWT\Validation\Constraint\SignedWith
*/
Expand Down
1 change: 1 addition & 0 deletions test/functional/HmacTokenTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
* @covers \Lcobucci\JWT\Signer\Hmac\UnsafeSha256
* @covers \Lcobucci\JWT\SodiumBase64Polyfill
* @covers \Lcobucci\JWT\Validation\Validator
* @covers \Lcobucci\JWT\Validation\ConstraintViolation
* @covers \Lcobucci\JWT\Validation\RequiredConstraintsViolated
* @covers \Lcobucci\JWT\Validation\Constraint\SignedWith
*/
Expand Down
1 change: 1 addition & 0 deletions test/functional/MaliciousTamperingPreventionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ public function createConfiguration(): void
* @covers \Lcobucci\JWT\Signer\Hmac\Sha256
* @covers \Lcobucci\JWT\Signer\Hmac\Sha512
* @covers \Lcobucci\JWT\SodiumBase64Polyfill
* @covers \Lcobucci\JWT\Validation\ConstraintViolation
* @covers \Lcobucci\JWT\Validation\Constraint\SignedWith
* @covers \Lcobucci\JWT\Validation\Validator
*/
Expand Down
1 change: 1 addition & 0 deletions test/functional/RsaTokenTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
* @covers \Lcobucci\JWT\Signer\Rsa\Sha512
* @covers \Lcobucci\JWT\SodiumBase64Polyfill
* @covers \Lcobucci\JWT\Validation\Validator
* @covers \Lcobucci\JWT\Validation\ConstraintViolation
* @covers \Lcobucci\JWT\Validation\RequiredConstraintsViolated
* @covers \Lcobucci\JWT\Validation\Constraint\SignedWith
*/
Expand Down
1 change: 1 addition & 0 deletions test/functional/TimeFractionPrecisionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
* @covers \Lcobucci\JWT\Signer\Key\InMemory
* @covers \Lcobucci\JWT\Signer\None
* @covers \Lcobucci\JWT\Validation\Validator
* @covers \Lcobucci\JWT\Validation\ConstraintViolation
* @covers \Lcobucci\JWT\Validation\RequiredConstraintsViolated
* @covers \Lcobucci\JWT\Validation\Constraint\SignedWith
*/
Expand Down
1 change: 1 addition & 0 deletions test/functional/UnsignedTokenTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
* @covers \Lcobucci\JWT\Signer\None
* @covers \Lcobucci\JWT\Signer\Key\InMemory
* @covers \Lcobucci\JWT\SodiumBase64Polyfill
* @covers \Lcobucci\JWT\Validation\ConstraintViolation
* @covers \Lcobucci\JWT\Validation\RequiredConstraintsViolated
* @covers \Lcobucci\JWT\Validation\Validator
* @covers \Lcobucci\JWT\Validation\Constraint\IssuedBy
Expand Down
1 change: 1 addition & 0 deletions test/unit/JwtFacadeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
* @uses \Lcobucci\JWT\Validation\Constraint\IssuedBy
* @uses \Lcobucci\JWT\Validation\Constraint\SignedWith
* @uses \Lcobucci\JWT\Validation\Constraint\StrictValidAt
* @uses \Lcobucci\JWT\Validation\ConstraintViolation
* @uses \Lcobucci\JWT\Validation\RequiredConstraintsViolated
*/
final class JwtFacadeTest extends TestCase
Expand Down
3 changes: 3 additions & 0 deletions test/unit/Validation/Constraint/HasClaimWithValueTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ public function registeredClaims(): iterable
*
* @covers ::__construct
* @covers ::assert
* @covers \Lcobucci\JWT\Validation\ConstraintViolation
*
* @uses \Lcobucci\JWT\Token\DataSet
* @uses \Lcobucci\JWT\Token\Plain
Expand All @@ -58,6 +59,7 @@ public function assertShouldRaiseExceptionWhenClaimIsNotSet(): void
*
* @covers ::__construct
* @covers ::assert
* @covers \Lcobucci\JWT\Validation\ConstraintViolation
*
* @uses \Lcobucci\JWT\Token\DataSet
* @uses \Lcobucci\JWT\Token\Plain
Expand All @@ -77,6 +79,7 @@ public function assertShouldRaiseExceptionWhenClaimValueDoesNotMatch(): void
*
* @covers ::__construct
* @covers ::assert
* @covers \Lcobucci\JWT\Validation\ConstraintViolation
*
* @uses \Lcobucci\JWT\Token\DataSet
* @uses \Lcobucci\JWT\Token\Plain
Expand Down
3 changes: 3 additions & 0 deletions test/unit/Validation/Constraint/IdentifiedByTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ final class IdentifiedByTest extends ConstraintTestCase
*
* @covers ::__construct
* @covers ::assert
* @covers \Lcobucci\JWT\Validation\ConstraintViolation
*
* @uses \Lcobucci\JWT\Token\DataSet
* @uses \Lcobucci\JWT\Token\Plain
Expand All @@ -33,6 +34,7 @@ public function assertShouldRaiseExceptionWhenIdIsNotSet(): void
*
* @covers ::__construct
* @covers ::assert
* @covers \Lcobucci\JWT\Validation\ConstraintViolation
*
* @uses \Lcobucci\JWT\Token\DataSet
* @uses \Lcobucci\JWT\Token\Plain
Expand All @@ -52,6 +54,7 @@ public function assertShouldRaiseExceptionWhenIdDoesNotMatch(): void
*
* @covers ::__construct
* @covers ::assert
* @covers \Lcobucci\JWT\Validation\ConstraintViolation
*
* @uses \Lcobucci\JWT\Token\DataSet
* @uses \Lcobucci\JWT\Token\Plain
Expand Down
3 changes: 3 additions & 0 deletions test/unit/Validation/Constraint/IssuedByTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ final class IssuedByTest extends ConstraintTestCase
*
* @covers ::__construct
* @covers ::assert
* @covers \Lcobucci\JWT\Validation\ConstraintViolation
*
* @uses \Lcobucci\JWT\Token\DataSet
* @uses \Lcobucci\JWT\Token\Plain
Expand All @@ -33,6 +34,7 @@ public function assertShouldRaiseExceptionWhenIssuerIsNotSet(): void
*
* @covers ::__construct
* @covers ::assert
* @covers \Lcobucci\JWT\Validation\ConstraintViolation
*
* @uses \Lcobucci\JWT\Token\DataSet
* @uses \Lcobucci\JWT\Token\Plain
Expand All @@ -52,6 +54,7 @@ public function assertShouldRaiseExceptionWhenIssuerValueDoesNotMatch(): void
*
* @covers ::__construct
* @covers ::assert
* @covers \Lcobucci\JWT\Validation\ConstraintViolation
*
* @uses \Lcobucci\JWT\Token\DataSet
* @uses \Lcobucci\JWT\Token\Plain
Expand Down
3 changes: 3 additions & 0 deletions test/unit/Validation/Constraint/PermittedForTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ final class PermittedForTest extends ConstraintTestCase
*
* @covers ::__construct
* @covers ::assert
* @covers \Lcobucci\JWT\Validation\ConstraintViolation
*
* @uses \Lcobucci\JWT\Token\DataSet
* @uses \Lcobucci\JWT\Token\Plain
Expand All @@ -33,6 +34,7 @@ public function assertShouldRaiseExceptionWhenAudienceIsNotSet(): void
*
* @covers ::__construct
* @covers ::assert
* @covers \Lcobucci\JWT\Validation\ConstraintViolation
*
* @uses \Lcobucci\JWT\Token\DataSet
* @uses \Lcobucci\JWT\Token\Plain
Expand All @@ -52,6 +54,7 @@ public function assertShouldRaiseExceptionWhenAudienceValueDoesNotMatch(): void
*
* @covers ::__construct
* @covers ::assert
* @covers \Lcobucci\JWT\Validation\ConstraintViolation
*
* @uses \Lcobucci\JWT\Token\DataSet
* @uses \Lcobucci\JWT\Token\Plain
Expand Down
2 changes: 2 additions & 0 deletions test/unit/Validation/Constraint/RelatedToTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ final class RelatedToTest extends ConstraintTestCase
*
* @covers ::__construct
* @covers ::assert
* @covers \Lcobucci\JWT\Validation\ConstraintViolation
*
* @uses \Lcobucci\JWT\Token\DataSet
* @uses \Lcobucci\JWT\Token\Plain
Expand All @@ -33,6 +34,7 @@ public function assertShouldRaiseExceptionWhenSubjectIsNotSet(): void
*
* @covers ::__construct
* @covers ::assert
* @covers \Lcobucci\JWT\Validation\ConstraintViolation
*
* @uses \Lcobucci\JWT\Token\DataSet
* @uses \Lcobucci\JWT\Token\Plain
Expand Down
Loading

0 comments on commit 8f7f2c2

Please sign in to comment.