src/Core/Framework/Api/OAuth/BearerTokenValidator.php line 56

  1. <?php declare(strict_types=1);
  2. namespace Shopware\Core\Framework\Api\OAuth;
  3. use Doctrine\DBAL\Connection;
  4. use Lcobucci\JWT\Configuration;
  5. use Lcobucci\JWT\UnencryptedToken;
  6. use League\OAuth2\Server\AuthorizationValidators\AuthorizationValidatorInterface;
  7. use League\OAuth2\Server\Exception\OAuthServerException;
  8. use Psr\Http\Message\ServerRequestInterface;
  9. use Shopware\Core\Framework\Log\Package;
  10. use Shopware\Core\Framework\Uuid\Uuid;
  11. use Shopware\Core\PlatformRequest;
  12. #[Package('core')]
  13. class BearerTokenValidator implements AuthorizationValidatorInterface
  14. {
  15.     /**
  16.      * @internal
  17.      */
  18.     public function __construct(private readonly AuthorizationValidatorInterface $decorated, private readonly Connection $connection, private readonly Configuration $configuration)
  19.     {
  20.     }
  21.     /**
  22.      * @return ServerRequestInterface
  23.      */
  24.     public function validateAuthorization(ServerRequestInterface $request)
  25.     {
  26.         $request $this->decorated->validateAuthorization($request);
  27.         $header $request->getHeader('authorization');
  28.         $jwt trim(preg_replace('/^(?:\s+)?Bearer\s/'''$header[0]) ?? '');
  29.         /** @var UnencryptedToken $token */
  30.         $token $this->configuration->parser()->parse($jwt);
  31.         if ($userId $request->getAttribute(PlatformRequest::ATTRIBUTE_OAUTH_USER_ID)) {
  32.             $this->validateAccessTokenIssuedAt($token->claims()->get('iat'0), $userId);
  33.         }
  34.         return $request;
  35.     }
  36.     /**
  37.      * @throws OAuthServerException
  38.      */
  39.     private function validateAccessTokenIssuedAt(\DateTimeImmutable $tokenIssuedAtstring $userId): void
  40.     {
  41.         $lastUpdatedPasswordAt $this->connection->createQueryBuilder()
  42.             ->select(['last_updated_password_at'])
  43.             ->from('user')
  44.             ->where('id = :userId')
  45.             ->setParameter('userId'Uuid::fromHexToBytes($userId))
  46.             ->executeQuery()
  47.             ->fetchOne();
  48.         if ($lastUpdatedPasswordAt === false) {
  49.             throw OAuthServerException::accessDenied('Access token is invalid');
  50.         }
  51.         if ($lastUpdatedPasswordAt === null) {
  52.             return;
  53.         }
  54.         $lastUpdatedPasswordAt strtotime((string) $lastUpdatedPasswordAt);
  55.         if ($tokenIssuedAt->getTimestamp() <= $lastUpdatedPasswordAt) {
  56.             throw OAuthServerException::accessDenied('Access token is expired');
  57.         }
  58.     }
  59. }