graphql_core_schema-1.0.x-dev/modules/graphql_security/src/Routing/GraphqlSecurityAccessCheck.php

modules/graphql_security/src/Routing/GraphqlSecurityAccessCheck.php
<?php

declare(strict_types=1);

namespace Drupal\graphql_security\Routing;

use Drupal\Core\Access\AccessResult;
use Drupal\Core\Routing\Access\AccessInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Site\Settings;
use Symfony\Component\HttpFoundation\RequestStack;

/**
 * Custom access check for accessing the /graphql route.
 *
 * Anonymous users don't have the "execute graphql requests" permission and
 * therefore are not allowed to make queries. This is to prevent anyone from
 * making any GraphQL requests, since they can become quite complex and
 * therefore a performance issue.
 *
 * Since the frontend doesn't directly make any GraphQL requests, we can allow
 * nuxt-graphql-middleware in the frontend to do requests. It performs
 * GraphQL requests server side and passes the response to the frontend. It's
 * like a proxy between Drupal and browser.
 * It sends the secret token in the request header and we check for the
 * presence of it in this access check.
 *
 * One would think we could create an "api" account and give it the permission
 * to make requests and then authenticate ourselves from the nuxt server side,
 * which would have the same results. But unfortunately that would result in
 * annoying Drupal cache behavior because then every anonymous user would
 * actually be logged in.
 *
 * The restricted access is just for performance reasons, since no sensitive
 * information is available via GraphQL anyway, as entity access checks are
 * still performed in the queries and anonymous users don't have permission to
 * access other users information for example.
 */
class GraphqlSecurityAccessCheck implements AccessInterface {

  /**
   * The header key to check to token.
   *
   * @var string
   */
  const HEADER = 'x-drupal-graphql-token';

  /**
   * Constructs a GraphqlAccessCheck instance.
   *
   * @param \Symfony\Component\HttpFoundation\RequestStack $requestStack
   *   The request stack.
   */
  public function __construct(
    protected RequestStack $requestStack,
  ) {
  }

  /**
   * Checks access.
   *
   * @param \Drupal\Core\Session\AccountInterface $account
   *   The currently logged in account.
   *
   * @return \Drupal\Core\Access\AccessResultInterface
   *   The access result.
   */
  public function access(AccountInterface $account) {
    // First check if the user has the permission to execute requests.
    // Anonymous users don't have this permission.
    if ($account->hasPermission('execute graphql_compose_server arbitrary graphql requests')) {
      return AccessResult::allowed();
    }

    $request = $this->requestStack->getCurrentRequest();

    $token = Settings::get('access_graphql.token');
    $tokenHeader = $request->headers->get(self::HEADER);

    // Check if the request is coming from nuxt-graphql-middleware.
    if ($token && $tokenHeader && hash_equals($token, $tokenHeader)) {
      return AccessResult::allowed();
    }

    // Denied.
    return AccessResult::forbidden();
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc