I added a custom access check to a JSON API endpoint so that only users who provide a token can POST/PATCH updates on a media endpoint. I followed this documentation in order to alter an existing route using RouteSubscriber:alterRoutes() and a custom access check.

Everything is working properly with my custom access check. I have a custom condition which will either forbid or allow access based on a condition:

public function access() {
   $valid = $this->validateToken($token);

   if ($valid) {
     $access = AccessResult::allowed()
   } else {
     $access = AccessResult::forbidden('The access token is invalid');

   return $access;

If the user does not fulfill the appropriate condition, then access is denied through my custom access check.

However, if the custom access check allows access, the default entity permissions are still being applied. I get a 403 Forbidden error saying:

The current user is not permitted to upload a file for this field. The following permissions are required: 'administer media' OR 'create media' OR 'create [machine_name] media'

When I allow access, I want whichever user who provided the correct token to be able to create a particular entity (including anonymous users). How do I override the entity permission system so that whoever fulfills the condition has access to create the entity?

Can I dynamically add the permission to this user to create this particular entity for just this request?

Right now in my alterRoutes() function I am setting a requirement for my _custom_access. Do I also need to set an additional requirement for _entity_access or _entity_create_access?


1 Answer 1


Drupal uses both route access and entity access. You need to add your access check in hook_entity_access() because the media entity module is denying create access. Use route access for non entity pages.

  • I probably should have been more specific in my example (I will update it), but I'm restricting access to API calls to /jsonapi/ endpoints. Those endpoints are allowing me to GET, POST, and PATCH entities. In this particular case, I'm updating Media entities.
    – neuquen
    Jan 21, 2020 at 22:48
  • That's fine. Entities have access handlers that manage the create, view, update and delete operations. The access handlers include hook_entity_access and hook_entity_create_access to determine if operations should be allowed. You need to inform the entity access handler that access is allowed if the token is present. The add form route already checks _entity_create_access on line 172 of DefaultHtmlRouteProvider. Jan 21, 2020 at 23:08
  • 1
    Also, use AccessResult::neutral() instead of AccessResult::forbidden() unless you never want anyone through any end point to be able to create an entity without a token. Jan 21, 2020 at 23:12
  • Thanks for the input. I was hoping that I could somehow control entity access through the route access checker, but it sounds like I will have to add the same token check to both functions. I'll give it a try to see if it works.
    – neuquen
    Jan 22, 2020 at 0:07
  • 1
    The route should be using _entity_create_access. If you can inspect it in the route collection, you should be able to see that as one of its requirements. You don't need to do both. Just do hook_entity_create_access. Jan 22, 2020 at 7:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.