src/Core/Framework/Api/OAuth/ClientRepository.php line 68

  1. <?php declare(strict_types=1);
  2. namespace Shopware\Core\Framework\Api\OAuth;
  3. use Doctrine\DBAL\Connection;
  4. use League\OAuth2\Server\Entities\ClientEntityInterface;
  5. use League\OAuth2\Server\Exception\OAuthServerException;
  6. use League\OAuth2\Server\Repositories\ClientRepositoryInterface;
  7. use Shopware\Core\Framework\Api\OAuth\Client\ApiClient;
  8. use Shopware\Core\Framework\Api\Util\AccessKeyHelper;
  9. use Shopware\Core\Framework\Log\Package;
  10. use Shopware\Core\Framework\Uuid\Uuid;
  11. #[Package('core')]
  12. class ClientRepository implements ClientRepositoryInterface
  13. {
  14.     /**
  15.      * @internal
  16.      */
  17.     public function __construct(private readonly Connection $connection)
  18.     {
  19.     }
  20.     public function validateClient($clientIdentifier$clientSecret$grantType): bool
  21.     {
  22.         if (($grantType === 'password' || $grantType === 'refresh_token') && $clientIdentifier === 'administration') {
  23.             return true;
  24.         }
  25.         if ($grantType === 'client_credentials' && $clientSecret !== null) {
  26.             $values $this->getByAccessKey($clientIdentifier);
  27.             if (!$values) {
  28.                 return false;
  29.             }
  30.             return password_verify($clientSecret, (string) $values['secret_access_key']);
  31.         }
  32.         // @codeCoverageIgnoreStart
  33.         throw OAuthServerException::unsupportedGrantType();
  34.         // @codeCoverageIgnoreEnd
  35.     }
  36.     public function getClientEntity($clientIdentifier): ?ClientEntityInterface
  37.     {
  38.         if ($clientIdentifier === 'administration') {
  39.             return new ApiClient('administration'true);
  40.         }
  41.         $values $this->getByAccessKey($clientIdentifier);
  42.         if (!$values) {
  43.             return null;
  44.         }
  45.         return new ApiClient($clientIdentifiertrue$values['label'] ?? Uuid::fromBytesToHex($values['user_id']));
  46.     }
  47.     private function getByAccessKey(string $clientIdentifier): ?array
  48.     {
  49.         $origin AccessKeyHelper::getOrigin($clientIdentifier);
  50.         if ($origin === 'user') {
  51.             return $this->getUserByAccessKey($clientIdentifier);
  52.         }
  53.         if ($origin === 'integration') {
  54.             return $this->getIntegrationByAccessKey($clientIdentifier);
  55.         }
  56.         return null;
  57.     }
  58.     private function getUserByAccessKey(string $clientIdentifier): ?array
  59.     {
  60.         $key $this->connection->createQueryBuilder()
  61.             ->select(['user_id''secret_access_key'])
  62.             ->from('user_access_key')
  63.             ->where('access_key = :accessKey')
  64.             ->setParameter('accessKey'$clientIdentifier)
  65.             ->execute()
  66.             ->fetch();
  67.         if (!$key) {
  68.             return null;
  69.         }
  70.         return $key;
  71.     }
  72.     private function getIntegrationByAccessKey(string $clientIdentifier): ?array
  73.     {
  74.         $key $this->connection->createQueryBuilder()
  75.             ->select(['integration.id AS id''label''secret_access_key''app.active as active'])
  76.             ->from('integration')
  77.             ->leftJoin('integration''app''app''app.integration_id = integration.id')
  78.             ->where('access_key = :accessKey')
  79.             ->setParameter('accessKey'$clientIdentifier)
  80.             ->execute()
  81.             ->fetch();
  82.         if (!$key) {
  83.             return null;
  84.         }
  85.         // inactive apps cannot access the api
  86.         // if the integration is not associated to an app `active` will be null
  87.         if ($key['active'] === '0') {
  88.             return null;
  89.         }
  90.         return $key;
  91.     }
  92. }