Permalink
Browse files

Add leeway to ValidAt constraint

To address clock skew issues.

More info:

- #191
- #248
  • Loading branch information...
lcobucci committed Oct 14, 2018
1 parent 008a9e7 commit 222811d1e24e81aa8e014fcb1c9c02c8fe4c66df
Showing with 77 additions and 5 deletions.
  1. +26 −5 src/Validation/Constraint/ValidAt.php
  2. +51 −0 test/unit/Validation/Constraint/ValidAtTest.php
@@ -3,7 +3,9 @@
namespace Lcobucci\JWT\Validation\Constraint;
use DateInterval;
use DateTimeInterface;
use InvalidArgumentException;
use Lcobucci\Clock\Clock;
use Lcobucci\JWT\Token;
use Lcobucci\JWT\Validation\Constraint;
@@ -16,9 +18,28 @@
*/
private $clock;
public function __construct(Clock $clock)
/**
* @var DateInterval
*/
private $leeway;
public function __construct(Clock $clock, ?DateInterval $leeway = null)
{
$this->clock = $clock;
$this->leeway = $this->guardLeeway($leeway);
}
private function guardLeeway(?DateInterval $leeway): DateInterval
{
$this->clock = $clock;
if ($leeway === null) {
return new DateInterval('PT0S');
}
if ($leeway->invert === 1) {
throw new InvalidArgumentException('Leeway cannot be negative');
}
return $leeway;
}
/**
@@ -28,9 +49,9 @@ public function assert(Token $token): void
{
$now = $this->clock->now();
$this->assertIssueTime($token, $now);
$this->assertMinimumTime($token, $now);
$this->assertExpiration($token, $now);
$this->assertIssueTime($token, $now->add($this->leeway));
$this->assertMinimumTime($token, $now->add($this->leeway));
$this->assertExpiration($token, $now->sub($this->leeway));
}
/**
@@ -3,6 +3,7 @@
namespace Lcobucci\JWT\Validation\Constraint;
use DateInterval;
use DateTimeImmutable;
use Lcobucci\Clock\Clock;
use Lcobucci\Clock\FrozenClock;
@@ -23,12 +24,29 @@ public function createDependencies(): void
$this->clock = new FrozenClock(new DateTimeImmutable());
}
/**
* @test
*
* @expectedException \InvalidArgumentException
*
* @covers \Lcobucci\JWT\Validation\Constraint\ValidAt::__construct
* @covers \Lcobucci\JWT\Validation\Constraint\ValidAt::guardLeeway
*/
public function constructShouldRaiseExceptionOnNegativeLeeway(): void
{
$leeway = new DateInterval('PT30S');
$leeway->invert = 1;
new ValidAt($this->clock, $leeway);
}
/**
* @test
*
* @expectedException \Lcobucci\JWT\Validation\ConstraintViolation
*
* @covers \Lcobucci\JWT\Validation\Constraint\ValidAt::__construct
* @covers \Lcobucci\JWT\Validation\Constraint\ValidAt::guardLeeway
* @covers \Lcobucci\JWT\Validation\Constraint\ValidAt::assert
* @covers \Lcobucci\JWT\Validation\Constraint\ValidAt::assertExpiration
* @covers \Lcobucci\JWT\Validation\Constraint\ValidAt::assertIssueTime
@@ -58,6 +76,7 @@ public function assertShouldRaiseExceptionWhenTokenIsExpired(): void
* @expectedException \Lcobucci\JWT\Validation\ConstraintViolation
*
* @covers \Lcobucci\JWT\Validation\Constraint\ValidAt::__construct
* @covers \Lcobucci\JWT\Validation\Constraint\ValidAt::guardLeeway
* @covers \Lcobucci\JWT\Validation\Constraint\ValidAt::assert
* @covers \Lcobucci\JWT\Validation\Constraint\ValidAt::assertExpiration
* @covers \Lcobucci\JWT\Validation\Constraint\ValidAt::assertIssueTime
@@ -87,6 +106,7 @@ public function assertShouldRaiseExceptionWhenMinimumTimeIsNotMet(): void
* @expectedException \Lcobucci\JWT\Validation\ConstraintViolation
*
* @covers \Lcobucci\JWT\Validation\Constraint\ValidAt::__construct
* @covers \Lcobucci\JWT\Validation\Constraint\ValidAt::guardLeeway
* @covers \Lcobucci\JWT\Validation\Constraint\ValidAt::assert
* @covers \Lcobucci\JWT\Validation\Constraint\ValidAt::assertExpiration
* @covers \Lcobucci\JWT\Validation\Constraint\ValidAt::assertIssueTime
@@ -114,6 +134,36 @@ public function assertShouldRaiseExceptionWhenTokenWasIssuedInTheFuture(): void
* @doesNotPerformAssertions
*
* @covers \Lcobucci\JWT\Validation\Constraint\ValidAt::__construct
* @covers \Lcobucci\JWT\Validation\Constraint\ValidAt::guardLeeway
* @covers \Lcobucci\JWT\Validation\Constraint\ValidAt::assert
* @covers \Lcobucci\JWT\Validation\Constraint\ValidAt::assertExpiration
* @covers \Lcobucci\JWT\Validation\Constraint\ValidAt::assertIssueTime
* @covers \Lcobucci\JWT\Validation\Constraint\ValidAt::assertMinimumTime
*
* @uses \Lcobucci\JWT\Token\DataSet
* @uses \Lcobucci\JWT\Token\Plain
* @uses \Lcobucci\JWT\Token\Signature
*/
public function assertShouldNotRaiseExceptionWhenLeewayIsUsed(): void
{
$now = $this->clock->now();
$claims = [
RegisteredClaims::ISSUED_AT => $now->modify('+5 seconds'),
RegisteredClaims::NOT_BEFORE => $now->modify('+5 seconds'),
RegisteredClaims::EXPIRATION_TIME => $now->modify('-5 seconds'),
];
$constraint = new ValidAt($this->clock, new DateInterval('PT5S'));
$constraint->assert($this->buildToken($claims));
}
/**
* @test
* @doesNotPerformAssertions
*
* @covers \Lcobucci\JWT\Validation\Constraint\ValidAt::__construct
* @covers \Lcobucci\JWT\Validation\Constraint\ValidAt::guardLeeway
* @covers \Lcobucci\JWT\Validation\Constraint\ValidAt::assert
* @covers \Lcobucci\JWT\Validation\Constraint\ValidAt::assertExpiration
* @covers \Lcobucci\JWT\Validation\Constraint\ValidAt::assertIssueTime
@@ -154,6 +204,7 @@ public function assertShouldNotRaiseExceptionWhenTokenIsUsedInTheRightMoment():
* @doesNotPerformAssertions
*
* @covers \Lcobucci\JWT\Validation\Constraint\ValidAt::__construct
* @covers \Lcobucci\JWT\Validation\Constraint\ValidAt::guardLeeway
* @covers \Lcobucci\JWT\Validation\Constraint\ValidAt::assert
* @covers \Lcobucci\JWT\Validation\Constraint\ValidAt::assertExpiration
* @covers \Lcobucci\JWT\Validation\Constraint\ValidAt::assertIssueTime

0 comments on commit 222811d

Please sign in to comment.