Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Wim Leers created an issue. See original summary.

Wim Leers’s picture

Status: Active » Needs review
FileSize
20.26 KB

Done.

Wim Leers’s picture

Doing so made me touch code where I was wondering whether the Entity Access API was already being used for relationships/includes. AFAICT it is not. This implies that already the JSON API module is violating the Entity Access API. It's currently only checking it for accessing individual entities, and it's checking field access when modifying a relationship. But it's not checking entity access when following relationships.

It's \Drupal\jsonapi\Normalizer\EntityNormalizer::serializeField() that generates an EntityCollection object, which is what will be used later to comply with ?include=… instructions. It does this:

    $access = $field->access('view', $context['account'], TRUE);
    if ($field instanceof AccessibleInterface && !$access->isAllowed()) {
      return (new NullFieldNormalizerValue())->addCacheableDependency($access);
    }

This is indeed fine to determine whether a field is viewable. But in the case of an entity reference field, you need both reference field access and access to the referenced entity to be allowed. See e.g. \Drupal\Core\Field\Plugin\Field\FieldFormatter\EntityReferenceLabelFormatter, it calls \Drupal\Core\Field\Plugin\Field\FieldFormatter\EntityReferenceFormatterBase::getEntitiesToView(), which does the entity access checking.

So, opened an issue for that: #2838646: Relationships violate Entity Access API.

Status: Needs review » Needs work

The last submitted patch, 2: enabled-2838630-2.patch, failed testing.

Wim Leers’s picture

Title: Remove the concept of "enabledness" from the JSON API module, rely on the Entity Access API instead » [PP-1] Remove the concept of "enabledness" from the JSON API module, rely on the Entity Access API instead
Status: Needs work » Postponed
Wim Leers’s picture

Title: [PP-1] Remove the concept of "enabledness" from the JSON API module, rely on the Entity Access API instead » Remove the concept of "enabledness" from the JSON API module, rely on the Entity Access API instead
Status: Postponed » Needs review

And e0ipso just committed that! Unblocked, re-testing.

klausi’s picture

From a security point of view this is a bad idea. We had a horrible security issue with RESTWS at https://www.drupal.org/node/2765567 (remote code execution) because it exposed any entity type.

If a developer gets the entity access controller wrong for an entity type you immediately open up a vulnerability over the JSON API for that entity type.

Wim Leers’s picture

#7:

  1. It's already enabled by default. i.e. it's opt-out, not opt-in.
  2. If you get it wrong in your entity access handler, then the same vulnerability is likely exposed elsewhere on the site.
  3. If you get it wrong in your entity access handler, you're completely missing test coverage for something critical to security. We shouldn't babysit broken code.
  4. The only alternative to what you suggest is to require developers to manually enable/expose every single entity type/bundle: opt-in instead of opt-out. Which is what the core REST module does. Which is a very frustrating process.

The whole point of the JSON API module is that it makes it easy to follow relationships. Requiring every entity type to be manually enabled completely nullifies that. If we'd do that, then I don't think there'd be much of a point to the JSON API module.

Wim Leers’s picture

Status: Needs review » Needs work
Wim Leers’s picture

Status: Needs work » Needs review
FileSize
20.18 KB
7.65 KB
e0ipso’s picture

Status: Needs review » Needs work

One minor change:

  1. +++ b/src/Normalizer/RelationshipItemNormalizer.php
    @@ -73,7 +73,7 @@ class RelationshipItemNormalizer extends FieldItemNormalizer implements UuidRefe
    +    // TODO Only include if the target entity is accessible.
    
    +++ b/src/Normalizer/RelationshipNormalizer.php
    @@ -75,10 +75,7 @@ class RelationshipNormalizer extends NormalizerBase {
    +      // @todo Ignore inaccessible relationship items?
    

    Since we don't know the reason of the inaccessibility we should not omit anything.

    «Leave the code in to win 403 error on access denied!»

    We should delete those TODO for now.

  2. +++ b/tests/src/Unit/Routing/RoutesTest.php
    @@ -96,7 +94,14 @@ class RoutesTest extends UnitTestCase {
    +    $route = $iterator->offsetGet('jsonapi.resource_type_2.collection');
    +    $this->assertSame('/jsonapi/entity_type_2/bundle_path_2', $route->getPath());
    +    $this->assertSame('entity_type_2', $route->getRequirement('_entity_type'));
    +    $this->assertSame('bundle_2_2', $route->getRequirement('_bundle'));
    +    $this->assertSame(['lorem', 'ipsum'], $route->getOption('_auth'));
    +    $this->assertEquals(['GET', 'POST'], $route->getMethods());
    +    $this->assertSame('MyCustomController', $route->getDefault(RouteObjectInterface::CONTROLLER_NAME));
    +    $this->assertSame('Drupal\jsonapi\Resource\JsonApiDocumentTopLevel', $route->getOption('serialization_class'));
    

    Maybe we should just remove the tests for /jsonapi/entity_type_2/bundle_path_2 since they are duplicating /jsonapi/entity_type_1/bundle_path_1.

e0ipso’s picture

Assigned: Wim Leers » e0ipso

Stealing this to be able to merge it.

e0ipso’s picture

Status: Needs work » Needs review
FileSize
16.14 KB

re-rolled and addressed own feedback from #11.

  • e0ipso committed 295c66d on 8.x-1.x authored by Wim Leers
    feat(Routing) Remove ability to disable resources (#2838630 by Wim Leers...
e0ipso’s picture

Status: Needs review » Fixed

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.