You are here

CsrfTest.php in Zircon Profile 8

Same filename and directory in other branches
  1. 8.0 core/modules/rest/src/Tests/CsrfTest.php

Namespace

Drupal\rest\Tests

File

core/modules/rest/src/Tests/CsrfTest.php
View source
<?php

/**
 * @file
 * Contains \Drupal\rest\Tests\CsrfTest.
 */
namespace Drupal\rest\Tests;

use Drupal\Core\Url;

/**
 * Tests the CSRF protection.
 *
 * @group rest
 */
class CsrfTest extends RESTTestBase {

  /**
   * Modules to install.
   *
   * @var array
   */
  public static $modules = array(
    'hal',
    'rest',
    'entity_test',
    'basic_auth',
  );

  /**
   * A testing user account.
   *
   * @var \Drupal\user\Entity\User
   */
  protected $account;

  /**
   * The serialized entity.
   *
   * @var string
   */
  protected $serialized;

  /**
   * {@inheritdoc}
   */
  protected function setUp() {
    parent::setUp();
    $this
      ->enableService('entity:' . $this->testEntityType, 'POST', 'hal_json', array(
      'basic_auth',
      'cookie',
    ));

    // Create a user account that has the required permissions to create
    // resources via the REST API.
    $permissions = $this
      ->entityPermissions($this->testEntityType, 'create');
    $permissions[] = 'restful post entity:' . $this->testEntityType;
    $this->account = $this
      ->drupalCreateUser($permissions);

    // Serialize an entity to a string to use in the content body of the POST
    // request.
    $serializer = $this->container
      ->get('serializer');
    $entity_values = $this
      ->entityValues($this->testEntityType);
    $entity = entity_create($this->testEntityType, $entity_values);
    $this->serialized = $serializer
      ->serialize($entity, $this->defaultFormat);
  }

  /**
   * Tests that CSRF check is not triggered for Basic Auth requests.
   */
  public function testBasicAuth() {
    $curl_options = $this
      ->getCurlOptions();
    $curl_options[CURLOPT_HTTPAUTH] = CURLAUTH_BASIC;
    $curl_options[CURLOPT_USERPWD] = $this->account
      ->getUsername() . ':' . $this->account->pass_raw;
    $this
      ->curlExec($curl_options);
    $this
      ->assertResponse(201);

    // Ensure that the entity was created.
    $loaded_entity = $this
      ->loadEntityFromLocationHeader($this
      ->drupalGetHeader('location'));
    $this
      ->assertTrue($loaded_entity, 'An entity was created in the database');
  }

  /**
   * Tests that CSRF check is triggered for Cookie Auth requests.
   */
  public function testCookieAuth() {
    $this
      ->drupalLogin($this->account);
    $curl_options = $this
      ->getCurlOptions();

    // Try to create an entity without the CSRF token.
    // Note: this will fail with PHP 5.6 when always_populate_raw_post_data is
    // set to something other than -1. See https://www.drupal.org/node/2456025.
    $this
      ->curlExec($curl_options);
    $this
      ->assertResponse(403);

    // Ensure that the entity was not created.
    $this
      ->assertFalse(entity_load_multiple($this->testEntityType, NULL, TRUE), 'No entity has been created in the database.');

    // Create an entity with the CSRF token.
    $token = $this
      ->drupalGet('rest/session/token');
    $curl_options[CURLOPT_HTTPHEADER][] = "X-CSRF-Token: {$token}";
    $this
      ->curlExec($curl_options);
    $this
      ->assertResponse(201);

    // Ensure that the entity was created.
    $loaded_entity = $this
      ->loadEntityFromLocationHeader($this
      ->drupalGetHeader('location'));
    $this
      ->assertTrue($loaded_entity, 'An entity was created in the database');
  }

  /**
   * Gets the cURL options to create an entity with POST.
   *
   * @return array
   *   The array of cURL options.
   */
  protected function getCurlOptions() {
    return array(
      CURLOPT_HTTPGET => FALSE,
      CURLOPT_POST => TRUE,
      CURLOPT_POSTFIELDS => $this->serialized,
      CURLOPT_URL => Url::fromRoute('rest.entity.' . $this->testEntityType . '.POST')
        ->setAbsolute()
        ->toString(),
      CURLOPT_NOBODY => FALSE,
      CURLOPT_HTTPHEADER => array(
        "Content-Type: {$this->defaultMimeType}",
      ),
    );
  }

}

Classes

Namesort descending Description
CsrfTest Tests the CSRF protection.