Upgrading from 3.x to 4.x: migrating ValidationData with $currentTime #813
-
Hello! I'm migrating code written by another developer, and I can see several validation calls, which look like this: $validationData = new ValidationData($this->getNowTime() + self::TTL_TIME_LIMIT);
if (!$token->validate($validationData)) {
// ...
}
$validationData = new ValidationData($this->getNowTime());
if (!$token->validate($validationData)) {
// ...
} From the upgrading steps I can see that validation is now done like this: !$this->configuration->validator()->validate($token, ...$this->configuration->validationConstraints()) But I can not see how can I pass the $currentTime argument with new API. And as you can see, in the old code it's not always an actual current time as in the first call (as I understand it's done to see if token will be expired during the next hour). Any solution for smooth migration in this case? |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
@hast sorry about our delay here... I converted your issue into a discussion to make it easier for other people to find it.
That's the suggested approach for simple validation, you can make do all sorts of things here... The v3.x behaviour is similar to what we implemented in the Your code would look like this (this is just a sample, sure): use Lcobucci\Clock\Clock;
use Lcobucci\Clock\SystemClock;
use Lcobucci\JWT\Validation\Constraint\LooseValidAt;
$clock = SystemClock::fromUTC();
$validOnTheNextHour = new LooseValidAt(
new class ($clock) implements Clock {
public function __construct(private Clock $decorated) {}
public function now(): DateTimeImmutable
{
return $this->decorated->now()->modify('+1 hour');
}
}
);
$validator = $this->configuration->validator();
if (! $validator->validate($token, $validOnTheNextHour)) {
// ...
}
if (! $validator->validate($token, new LooseValidAt($clock)) {
// ...
} Depending on what's inside the ifs, you maybe have a single call (the order matters here): $validator = $this->configuration->validator();
if (! $validator->validate($token, $validOnTheNextHour, new LooseValidAt($clock))) {
// ...
} Alternatively, you can build your constraint to perform the two checks: use DateInterval;
use DateTimeInterface;
use Lcobucci\Clock\Clock;
use Lcobucci\JWT\Token;
use Lcobucci\JWT\Validation\Constraint;
use Lcobucci\JWT\Validation\ConstraintViolation;
final class MyCustomConstraintForLooselyValidatingTheTimeClaims implements Constraint
{
public function __construct(private Clock $clock) {}
public function assert(Token $token): void
{
$now = $this->clock->now();
if ($token->isExpired($now->modify('+1 hour')) {
// do something fancy but not necessarily blocking
}
if (! $token->hasBeenIssuedBefore($now)) {
throw new ConstraintViolation('The token was issued in the future');
}
if (! $token->isMinimumTimeBefore($now)) {
throw new ConstraintViolation('The token cannot be used yet');
}
if ($token->isExpired($now)) {
throw new ConstraintViolation('The token is expired');
}
}
}
// Then you'd do:
$validator = $this->configuration->validator();
if (! $validator->validate($token, new MyCustomConstraintForLooselyValidatingTheTimeClaims($clock))) {
// ...
} I hope this gives you enough clarity on how to move forward! |
Beta Was this translation helpful? Give feedback.
@hast sorry about our delay here... I converted your issue into a discussion to make it easier for other people to find it.
That's the suggested approach for simple validation, you can make do all sorts of things here...
The v3.x behaviour is similar to what we implemented in the
LooseValidAt
constraint.The difference is that we use a clock instead of an integer to perform the validation.
Your code would look like this (this is just a sample, sure):