src/Core/Framework/Api/OAuth/RefreshTokenRepository.php line 110

  1. <?php declare(strict_types=1);
  2. namespace Shopware\Core\Framework\Api\OAuth;
  3. use Doctrine\DBAL\Connection;
  4. use League\OAuth2\Server\Entities\RefreshTokenEntityInterface;
  5. use League\OAuth2\Server\Repositories\RefreshTokenRepositoryInterface;
  6. use Shopware\Core\Defaults;
  7. use Shopware\Core\Framework\Log\Package;
  8. use Shopware\Core\Framework\Uuid\Uuid;
  9. #[Package('core')]
  10. class RefreshTokenRepository implements RefreshTokenRepositoryInterface
  11. {
  12.     /**
  13.      * @internal
  14.      */
  15.     public function __construct(private readonly Connection $connection)
  16.     {
  17.     }
  18.     /**
  19.      * {@inheritdoc}
  20.      */
  21.     public function getNewRefreshToken(): RefreshTokenEntityInterface
  22.     {
  23.         return new RefreshToken();
  24.     }
  25.     /**
  26.      * {@inheritdoc}
  27.      */
  28.     public function persistNewRefreshToken(RefreshTokenEntityInterface $refreshTokenEntity): void
  29.     {
  30.         $this->connection->createQueryBuilder()
  31.             ->insert('refresh_token')
  32.             ->values([
  33.                 'id' => ':id',
  34.                 'user_id' => ':userId',
  35.                 'token_id' => ':tokenId',
  36.                 'issued_at' => ':issuedAt',
  37.                 'expires_at' => ':expiresAt',
  38.             ])
  39.             ->setParameters([
  40.                 'id' => Uuid::randomBytes(),
  41.                 'userId' => Uuid::fromHexToBytes($refreshTokenEntity->getAccessToken()->getUserIdentifier()),
  42.                 'tokenId' => $refreshTokenEntity->getIdentifier(),
  43.                 'issuedAt' => (new \DateTime())->format(Defaults::STORAGE_DATE_TIME_FORMAT),
  44.                 'expiresAt' => $refreshTokenEntity->getExpiryDateTime()->format(Defaults::STORAGE_DATE_TIME_FORMAT),
  45.             ])
  46.             ->execute();
  47.         $this->cleanUpExpiredRefreshTokens();
  48.     }
  49.     /**
  50.      * {@inheritdoc}
  51.      */
  52.     public function revokeRefreshToken($tokenId): void
  53.     {
  54.         $this->connection->createQueryBuilder()
  55.             ->delete('refresh_token')
  56.             ->where('token_id = :tokenId')
  57.             ->setParameter('tokenId'$tokenId)
  58.             ->execute();
  59.         $this->cleanUpExpiredRefreshTokens();
  60.     }
  61.     /**
  62.      * {@inheritdoc}
  63.      */
  64.     public function isRefreshTokenRevoked($tokenId): bool
  65.     {
  66.         $refreshToken $this->connection->createQueryBuilder()
  67.             ->select(['token_id'])
  68.             ->from('refresh_token')
  69.             ->where('token_id = :tokenId')
  70.             ->setParameter('tokenId'$tokenId)
  71.             ->execute()
  72.             ->fetch();
  73.         $this->cleanUpExpiredRefreshTokens();
  74.         // no token found, token is invalid
  75.         if (!$refreshToken) {
  76.             return true;
  77.         }
  78.         return false;
  79.     }
  80.     public function revokeRefreshTokensForUser(string $userId): void
  81.     {
  82.         $this->connection->createQueryBuilder()
  83.             ->delete('refresh_token')
  84.             ->where('user_id = UNHEX(:userId)')
  85.             ->setParameter('userId'$userId)
  86.             ->execute();
  87.     }
  88.     private function cleanUpExpiredRefreshTokens(): void
  89.     {
  90.         $now = (new \DateTime())->format(Defaults::STORAGE_DATE_TIME_FORMAT);
  91.         $this->connection->createQueryBuilder()
  92.             ->delete('refresh_token')
  93.             ->where('expires_at < :now')
  94.             ->setParameter('now'$now)
  95.             ->execute();
  96.     }
  97. }