diff --git a/core/modules/rest/lib/Drupal/rest/EventSubscriber/RouteSubscriber.php b/core/modules/rest/lib/Drupal/rest/EventSubscriber/RouteSubscriber.php index b1bcb7c..701d259 100644 --- a/core/modules/rest/lib/Drupal/rest/EventSubscriber/RouteSubscriber.php +++ b/core/modules/rest/lib/Drupal/rest/EventSubscriber/RouteSubscriber.php @@ -72,6 +72,10 @@ public function dynamicRoutes(RouteBuildEvent $event) { $collection->add("rest.$name", $route); continue; } + // Check authentication. + if (is_array($enabled_methods[$method]['options']['_auth']) && !empty($enabled_methods[$method]['options']['_auth'])) { + $route->setOption('_auth', $enabled_methods[$method]['options']['_auth']); + } // If there is no format requirement or if it matches the // configuration also add the route. $format_requirement = $route->getRequirement('_format'); diff --git a/core/modules/rest/lib/Drupal/rest/Tests/AuthTest.php b/core/modules/rest/lib/Drupal/rest/Tests/AuthTest.php new file mode 100644 index 0000000..d2afe66 --- /dev/null +++ b/core/modules/rest/lib/Drupal/rest/Tests/AuthTest.php @@ -0,0 +1,95 @@ + 'Resource authentication', + 'description' => 'Tests access to authenticated resources.', + 'group' => 'REST', + ); + } + + /** + * Tests reading from an authenticated resource. + */ + public function testRead() { + // @todo once EntityNG is implemented for other entity types expand this at + // least to nodes and users. + // Define the entity types we want to test. + $entity_types = array('entity_test'); + foreach ($entity_types as $entity_type) { + $this->enableService('entity:' . $entity_type, 'GET', NULL, array('http_basic')); + //$this->enableService('entity:' . $entity_type, 'GET'); + // Create a user account that has the required permissions to read + // resources via the REST API, but the request is not authenticated. + $permissions = $this->entityPermissions($entity_type, 'view'); + $permissions[] = 'restful get entity:' . $entity_type; + $account = $this->drupalCreateUser($permissions); + $this->drupalLogin($account); + + // Create an entity programmatically. + $entity = $this->entityCreate($entity_type); + $entity->save(); + + // Attempt to read it over the REST API. + $response = $this->httpRequest('entity/' . $entity_type . '/' . $entity->id(), 'GET', NULL, $this->defaultMimeType); + $this->assertResponse('403', 'HTTP response code is 403 when the request is not authenticated.'); + // Now read it authenticating the request. + $response = $this->basicAuthGet('entity/' . $entity_type . '/' . $entity->id(), $account->getUsername(), $account->pass_raw); + $this->assertResponse('200', 'HTTP response code is 200 for successfuly authenticated requests.'); + } + } + + /** + * Does HTTP basic auth request. + * + * We do not use \Drupal\simpletest\WebTestBase::drupalGet because we need to + * set curl settings for basic authentication. + * + * @param string $path + * The request path. + * @param string $username + * The user name to authenticate with. + * @param string $password + * The password. + * + * @return string + * Curl output. + */ + protected function basicAuthGet($path, $username, $password) { + $out = $this->curlExec( + array( + CURLOPT_HTTPGET => TRUE, + CURLOPT_URL => url($path, array('absolute' => TRUE)), + CURLOPT_NOBODY => FALSE, + CURLOPT_HTTPAUTH => CURLAUTH_BASIC, + CURLOPT_USERPWD => $username . ':' . $password, + ) + ); + + $this->verbose('GET request to: ' . $path . + '
' . $out); + + return $out; + } +} diff --git a/core/modules/rest/lib/Drupal/rest/Tests/RESTTestBase.php b/core/modules/rest/lib/Drupal/rest/Tests/RESTTestBase.php index b49bf5c..8290d8a 100644 --- a/core/modules/rest/lib/Drupal/rest/Tests/RESTTestBase.php +++ b/core/modules/rest/lib/Drupal/rest/Tests/RESTTestBase.php @@ -189,8 +189,10 @@ protected function entityValues($entity_type) { * The HTTP method to enable, e.g. GET, POST etc. * @param string $format * (Optional) The serialization format, e.g. hal_json. + * @param array $auth + * (Optional) The list of valid authentication methods. */ - protected function enableService($resource_type, $method = 'GET', $format = NULL) { + protected function enableService($resource_type, $method = 'GET', $format = NULL, $auth = array()) { // Enable REST API for this entity type. $config = config('rest.settings'); $settings = array(); @@ -202,6 +204,10 @@ protected function enableService($resource_type, $method = 'GET', $format = NULL $settings[$resource_type][$method] = array(); } } + if (is_array($auth) && !empty($auth)) { + $settings[$resource_type][$method]['options']['_auth'] = $auth; + } + $config->set('resources', $settings); $config->save();