Issue #2054187 by juampy: Restrict authentication provider for REST resources.
parent
4ca797aa8c
commit
2cfbc1835d
|
@ -14,3 +14,13 @@ resources:
|
||||||
# GET:
|
# GET:
|
||||||
# supported_formats:
|
# supported_formats:
|
||||||
# - json
|
# - json
|
||||||
|
#
|
||||||
|
# To enable only specific authentication methods for an operation, list them
|
||||||
|
# at supported_auth.
|
||||||
|
# For example, the following config only allows Basic HTTP authenticated
|
||||||
|
# requests for the POST method on the node entity.
|
||||||
|
# resources:
|
||||||
|
# entity:node:
|
||||||
|
# POST:
|
||||||
|
# supported_auth:
|
||||||
|
# - http_basic
|
||||||
|
|
|
@ -72,6 +72,11 @@ class RouteSubscriber implements EventSubscriberInterface {
|
||||||
$collection->add("rest.$name", $route);
|
$collection->add("rest.$name", $route);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
// Check if there are authentication provider restrictions in the
|
||||||
|
// configuration and apply them to the route.
|
||||||
|
if (is_array($enabled_methods[$method]['supported_auth']) && !empty($enabled_methods[$method]['supported_auth'])) {
|
||||||
|
$route->setOption('_auth', $enabled_methods[$method]['supported_auth']);
|
||||||
|
}
|
||||||
// If there is no format requirement or if it matches the
|
// If there is no format requirement or if it matches the
|
||||||
// configuration also add the route.
|
// configuration also add the route.
|
||||||
$format_requirement = $route->getRequirement('_format');
|
$format_requirement = $route->getRequirement('_format');
|
||||||
|
|
|
@ -0,0 +1,107 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* Definition of Drupal\rest\test\AuthTest.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Drupal\rest\Tests;
|
||||||
|
|
||||||
|
use Drupal\rest\Tests\RESTTestBase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests authenticated operations on test entities.
|
||||||
|
*/
|
||||||
|
class AuthTest extends RESTTestBase {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modules to enable.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
public static $modules = array('hal', 'rest', 'entity_test');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public static function getInfo() {
|
||||||
|
return array(
|
||||||
|
'name' => 'Resource authentication',
|
||||||
|
'description' => 'Tests authentication provider restrictions.',
|
||||||
|
'group' => 'REST',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests reading from an authenticated resource.
|
||||||
|
*/
|
||||||
|
public function testRead() {
|
||||||
|
$entity_type = 'entity_test';
|
||||||
|
|
||||||
|
// Enable a test resource through GET method and basic HTTP authentication.
|
||||||
|
$this->enableService('entity:' . $entity_type, 'GET', NULL, array('http_basic'));
|
||||||
|
|
||||||
|
// Create an entity programmatically.
|
||||||
|
$entity = $this->entityCreate($entity_type);
|
||||||
|
$entity->save();
|
||||||
|
|
||||||
|
// Try to read the resource as an anonymous user, which should not work.
|
||||||
|
$response = $this->httpRequest('entity/' . $entity_type . '/' . $entity->id(), 'GET', NULL, $this->defaultMimeType);
|
||||||
|
$this->assertResponse('401', 'HTTP response code is 401 when the request is not authenticated and the user is anonymous.');
|
||||||
|
$this->assertText('A fatal error occurred: No authentication credentials provided.');
|
||||||
|
|
||||||
|
// Create a user account that has the required permissions to read
|
||||||
|
// resources via the REST API, but the request is authenticated
|
||||||
|
// with session cookies.
|
||||||
|
$permissions = $this->entityPermissions($entity_type, 'view');
|
||||||
|
$permissions[] = 'restful get entity:' . $entity_type;
|
||||||
|
$account = $this->drupalCreateUser($permissions);
|
||||||
|
$this->drupalLogin($account);
|
||||||
|
|
||||||
|
// Try to read the resource with session cookie authentication, which is
|
||||||
|
// not enabled and should not work.
|
||||||
|
$response = $this->httpRequest('entity/' . $entity_type . '/' . $entity->id(), 'GET', NULL, $this->defaultMimeType);
|
||||||
|
$this->assertResponse('403', 'HTTP response code is 403 when the request is authenticated but not authorized.');
|
||||||
|
$this->drupalLogout();
|
||||||
|
|
||||||
|
// Now read it with the Basic authentication which is enabled and should
|
||||||
|
// work.
|
||||||
|
$response = $this->basicAuthGet('entity/' . $entity_type . '/' . $entity->id(), $account->getUsername(), $account->pass_raw);
|
||||||
|
$this->assertResponse('200', 'HTTP response code is 200 for successfuly authorized requests.');
|
||||||
|
$this->curlClose();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs a HTTP request with Basic authentication.
|
||||||
|
*
|
||||||
|
* 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 .
|
||||||
|
'<hr />' . $out);
|
||||||
|
|
||||||
|
return $out;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -192,8 +192,10 @@ abstract class RESTTestBase extends WebTestBase {
|
||||||
* The HTTP method to enable, e.g. GET, POST etc.
|
* The HTTP method to enable, e.g. GET, POST etc.
|
||||||
* @param string $format
|
* @param string $format
|
||||||
* (Optional) The serialization format, e.g. hal_json.
|
* (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.
|
// Enable REST API for this entity type.
|
||||||
$config = config('rest.settings');
|
$config = config('rest.settings');
|
||||||
$settings = array();
|
$settings = array();
|
||||||
|
@ -205,6 +207,10 @@ abstract class RESTTestBase extends WebTestBase {
|
||||||
$settings[$resource_type][$method] = array();
|
$settings[$resource_type][$method] = array();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (is_array($auth) && !empty($auth)) {
|
||||||
|
$settings[$resource_type][$method]['supported_auth'] = $auth;
|
||||||
|
}
|
||||||
|
|
||||||
$config->set('resources', $settings);
|
$config->set('resources', $settings);
|
||||||
$config->save();
|
$config->save();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue