%PDF- %PDF-
Direktori : /home/graphicd/public_html/vebto/vendor/kreait/firebase-php/src/Firebase/Auth/ |
Current File : /home/graphicd/public_html/vebto/vendor/kreait/firebase-php/src/Firebase/Auth/IdTokenVerifier.php |
<?php declare(strict_types=1); namespace Kreait\Firebase\Auth; use DateTimeImmutable; use Firebase\Auth\Token\Domain\Verifier; use Firebase\Auth\Token\Exception\ExpiredToken; use Firebase\Auth\Token\Exception\InvalidSignature; use Firebase\Auth\Token\Exception\InvalidToken; use Firebase\Auth\Token\Exception\IssuedInTheFuture; use Firebase\Auth\Token\Exception\UnknownKey; use Kreait\Clock; use Kreait\Firebase\Exception\InvalidArgumentException; use Lcobucci\JWT\Configuration; use Lcobucci\JWT\Token; use Throwable; final class IdTokenVerifier implements Verifier { /** @var Verifier */ private $verifier; /** @var Clock */ private $clock; /** @var int */ private $leewayInSeconds = 0; /** @var Configuration */ private $config; public function __construct(Verifier $verifier, Clock $clock) { $this->verifier = $verifier; $this->clock = $clock; $this->config = Configuration::forUnsecuredSigner(); } public function withLeewayInSeconds(int $leewayInSeconds): self { $verifier = new self($this->verifier, $this->clock); $verifier->leewayInSeconds = $leewayInSeconds; return $verifier; } public function verifyIdToken($token): Token { // We get $now now™ so that it doesn't change while processing $now = $this->clock->now(); $token = $this->ensureToken($token); // @codeCoverageIgnoreStart if (!($token instanceof Token\Plain)) { throw new InvalidArgumentException('The given token could not be decrypted'); } // @codeCoverageIgnoreEnd try { $verifiedToken = $this->verifier->verifyIdToken($token); // @codeCoverageIgnoreStart if (!($verifiedToken instanceof Token\Plain)) { throw new InvalidToken($token, 'The token could not be decrypted'); } // @codeCoverageIgnoreEnd if (!($verifiedToken->claims()->get('sub'))) { throw new InvalidToken($token, 'The token has no "sub" claim'); } return $token; } catch (UnknownKey | InvalidSignature $e) { throw $e; } catch (ExpiredToken $e) { // Re-check expiry with the clock if ($this->isNotExpired($token, $now)) { return $token; } throw $e; } catch (IssuedInTheFuture $e) { // Re-check expiry with the clock if ($this->isIssuedInThePast($token, $now)) { return $token; } throw $e; } catch (InvalidToken $e) { $isAuthTimeProblem = \mb_stripos($e->getMessage(), 'authentication time') !== false; if ($isAuthTimeProblem && $this->isAuthenticatedInThePast($token, $now)) { return $token; } throw $e; } catch (Throwable $e) { throw new InvalidToken($token, $e->getMessage(), $e->getCode(), $e); } } private function isNotExpired(Token $token, DateTimeImmutable $now): bool { return !$token->isExpired($now->modify('-'.($this->leewayInSeconds + 1).' seconds')); } private function isIssuedInThePast(Token $token, DateTimeImmutable $now): bool { return $token->hasBeenIssuedBefore($now->modify('+'.($this->leewayInSeconds + 1).' seconds')); } private function isAuthenticatedInThePast(Token $token, DateTimeImmutable $now): bool { if (!($token instanceof Token\Plain)) { return false; } $issuedAt = $token->claims()->get('auth_time'); // We add another second to account for possible microseconds that could be in $now, but not in $authenticatedAt $check = $now->modify('+'.($this->leewayInSeconds + 1).' seconds'); $authenticatedAt = $now->setTimestamp((int) $issuedAt); return $authenticatedAt < $check; } /** * @param Token|object|string $token */ private function ensureToken($token): Token { if ($token instanceof Token) { return $token; } if (\is_object($token) && !\method_exists($token, '__toString')) { throw new InvalidArgumentException('The given token is an object and cannot be cast to a string'); } try { return $this->config->parser()->parse((string) $token); } catch (Throwable $e) { throw new InvalidArgumentException('The given token could not be parsed: '.$e->getMessage()); } } }