Problem/Motivation
After the security update on the 27th of August, entities that use the default query_access handler "EventOnlyQueryAccessHandler" but don't implement hooks now can no longer be filtered via the JSON API.
In the update, the below statement was removed from the entity_jsonapi_entity_filter_access function
if ($conditions->count() === 0) {
$result[JsonApiFilter::AMONG_ALL] = $allowed;
}
This results in applications who choose to rely on Drupal's methods for access control instead of the entity modules query_access handlers will have all JSON:API filtering broken.
For our use case, we use an in house module that derives from node_realm_access module without the node specifics. This means our access is handled at a query_alter and entity_access level instead of a query_access handler. This was done so we can ensure the same grants style access can be used in all access checks and we found the query_access was not suitable for this.
I am trying to understand the point of removing this AMONG_ALL access check.
From my perspective, when users have zero conditions from the query_access, if they aren't meant to have access to the dataset, the $conditions->isAlwaysFalse() should return true and short circuit the filter_access hook which would leave the existing AMONG_ALL check that many sites rely on.
With the existing issue "entity_jsonapi_entity_filter_access provides insufficient AccessResults" talking about the issues in this very hook, I also believe refactoring this hook should be a higher priority.
This version of the module is unsuitable for us to upgrade to as of now
Steps to reproduce
1. Define an entity without a query_access handler, the default will be assigned (EventOnlyQueryAccessHandler)
2. As a user who can view the entities, attempt to fetch data from the JSON:API for that entity with some kind of filter
3. Observe no results for an entity they have access to view.
Comments
Comment #2
rhovlandThis is a case of your integrations relying on site behavior that were causing an access bypass.
See the definition of AMONG_ALL
Granting AMONG_ALL is only appropriate for accounts that have entity admin permission. A hook in the jsonapi module does that for all entities.
With AMONG_ALL permission you can use filters to view information about [redacted]. That is why it was removed.
The entity module cannot know what the permission model of the entity is. It is up to the module that implements the entity to declare what can and can't be filtered/shown via a query.
The JSON:API module still provides a feature that grants AMONG_ALL if the user has permission to administer the entity. That is why admin permission restores the ability to use filters.
Example from the JSON:API module itself in Drupal core. Here it's granting AMONG_ALL for users with administer comments and AMONG_PUBLISHED for users with access comments permissions.
So for your module you could write a hook that grants AMONG_PUBLISHED or AMONG_ENABLED if your entity has a simple access model. If it's more complex then you need to define a query_access key in the entity:
In this example, the entity is using the access handler provided by the Entity API module for more complex permissions setups. If the entity uses one of the Entity API provided permissions frameworks you can use the respective query access handler to automatically handle it appropriately. Then it you add a hook in the module that provides the entity:
You can also see an example of a custom handler in the Commerce module:
Drupal\commerce_order\OrderQueryAccessHandler