Issue #2054187 by juampy: Restrict authentication provider for REST resources.
parent
4ca797aa8c
commit
2cfbc1835d
|
@ -14,3 +14,13 @@ resources:
|
|||
# GET:
|
||||
# supported_formats:
|
||||
# - 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);
|
||||
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
|
||||
// configuration also add the route.
|
||||
$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.
|
||||
* @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();
|
||||
|
@ -205,6 +207,10 @@ abstract class RESTTestBase extends WebTestBase {
|
|||
$settings[$resource_type][$method] = array();
|
||||
}
|
||||
}
|
||||
if (is_array($auth) && !empty($auth)) {
|
||||
$settings[$resource_type][$method]['supported_auth'] = $auth;
|
||||
}
|
||||
|
||||
$config->set('resources', $settings);
|
||||
$config->save();
|
||||
|
||||
|
|
Loading…
Reference in New Issue