NoExpiredValidConstraint.php 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. <?php
  2. namespace App\Repositories\JwtConstraints;
  3. use Lcobucci\Clock\Clock;
  4. use Lcobucci\JWT\Token;
  5. use Lcobucci\JWT\UnencryptedToken;
  6. use Lcobucci\JWT\Validation\Constraint;
  7. use Lcobucci\JWT\Validation\Constraint\LeewayCannotBeNegative;
  8. use Lcobucci\JWT\Validation\ConstraintViolation;
  9. use DateInterval;
  10. use DateTimeInterface;
  11. class NoExpiredValidConstraint implements Constraint
  12. {
  13. private Clock $clock;
  14. private DateInterval $leeway;
  15. public function __construct(Clock $clock, ?DateInterval $leeway = null)
  16. {
  17. $this->clock = $clock;
  18. $this->leeway = $this->guardLeeway($leeway);
  19. }
  20. private function guardLeeway(?DateInterval $leeway): DateInterval
  21. {
  22. if ($leeway === null) {
  23. return new DateInterval('PT0S');
  24. }
  25. if ($leeway->invert === 1) {
  26. throw LeewayCannotBeNegative::create();
  27. }
  28. return $leeway;
  29. }
  30. public function assert(Token $token): void
  31. {
  32. if (!$token instanceof UnencryptedToken) {
  33. throw new ConstraintViolation('You should pass a plain token');
  34. }
  35. $now = $this->clock->now();
  36. $this->assertIssueTime($token, $now->add($this->leeway));
  37. $this->assertMinimumTime($token, $now->add($this->leeway));
  38. $this->assertHasExpiration($token, $now->sub($this->leeway));
  39. }
  40. /** @throws ConstraintViolation */
  41. private function assertHasExpiration(UnencryptedToken $token, DateTimeInterface $now): void
  42. {
  43. if (!$token->claims()->has(Token\RegisteredClaims::EXPIRATION_TIME)) {
  44. throw new ConstraintViolation('"Expiration Time" claim missing');
  45. }
  46. }
  47. /** @throws ConstraintViolation */
  48. private function assertMinimumTime(UnencryptedToken $token, DateTimeInterface $now): void
  49. {
  50. if (!$token->claims()->has(Token\RegisteredClaims::NOT_BEFORE)) {
  51. throw new ConstraintViolation('"Not Before" claim missing');
  52. }
  53. if (!$token->isMinimumTimeBefore($now)) {
  54. throw new ConstraintViolation('The token cannot be used yet');
  55. }
  56. }
  57. /** @throws ConstraintViolation */
  58. private function assertIssueTime(UnencryptedToken $token, DateTimeInterface $now): void
  59. {
  60. if (!$token->claims()->has(Token\RegisteredClaims::ISSUED_AT)) {
  61. throw new ConstraintViolation('"Issued At" claim missing');
  62. }
  63. if (!$token->hasBeenIssuedBefore($now)) {
  64. throw new ConstraintViolation('The token was issued in the future');
  65. }
  66. }
  67. }