account instanceof Account) { throw new InvalidConfigException('This validator must be instantiated with the account param'); } if (empty($this->account->otp_secret)) { throw new InvalidConfigException('account should have not empty otp_secret'); } $this->clock = FactoryImmutable::getDefaultInstance(); } public function setClock(ClockInterface $clock): void { $this->clock = $clock; } protected function validateValue($value): ?array { try { // @phpstan-ignore argument.type (it is non empty, its checked in the init method) $totp = TOTP::create($this->account->otp_secret); // @phpstan-ignore argument.type,argument.type,argument.type (all types are fine, they're just not declared well) if (!$totp->verify((string)$value, $this->clock->now()->getTimestamp(), $totp->getPeriod() - 1)) { return [E::TOTP_INCORRECT, []]; } } catch (RangeException) { return [E::TOTP_INCORRECT, []]; } return null; } }