diff --git a/entity.module b/entity.module
index 546f322..5bdac48 100644
--- a/entity.module
+++ b/entity.module
@@ -5,11 +5,18 @@
  * Provides expanded entity APIs.
  */
 
+use Drupal\Core\Access\AccessResult;
 use Drupal\Core\Database\Query\SelectInterface;
+use Drupal\Core\Entity\EntityPublishedInterface;
 use Drupal\Core\Entity\EntityTypeInterface;
+use Drupal\Core\Session\AccountInterface;
 use Drupal\entity\BundlePlugin\BundlePluginHandler;
+use Drupal\entity\EntityAccessControlHandler;
+use Drupal\entity\EntityAccessControlHandlerBase;
+use Drupal\entity\UncacheableEntityAccessControlHandler;
 use Drupal\entity\QueryAccess\EntityQueryAlter;
 use Drupal\entity\QueryAccess\ViewsQueryAlter;
+use Drupal\user\EntityOwnerInterface;
 use Drupal\views\Plugin\views\query\QueryPluginBase;
 use Drupal\views\Plugin\views\query\Sql;
 use Drupal\views\ViewExecutable;
@@ -118,3 +125,93 @@ function entity_views_query_alter(ViewExecutable $view, QueryPluginBase $query)
       ->alter($query, $view);
   }
 }
+
+/**
+ * Implements hook_jsonapi_entity_filter_access().
+ *
+ * Allow JSON:API filtering for entity types that exclusively use the "view"
+ * access control implementations that this module provides.
+ */
+function entity_jsonapi_entity_filter_access(EntityTypeInterface $entity_type, AccountInterface $account) {
+  $access_class = $entity_type->getAccessControlClass();
+
+  // This module provides standardized entity access control logic in
+  // EntityAccessControlHandlerBase::checkAccess(). If an entity type uses an
+  // access control handler that doesn't derive from this base class, or that
+  // overrides this method, then we have no opinion to return.
+  if (!is_a($access_class, EntityAccessControlHandlerBase::class, TRUE)) {
+    return;
+  }
+  $reflector = new ReflectionMethod($access_class, 'checkAccess');
+  if ($reflector->getDeclaringClass()->getName() !== EntityAccessControlHandlerBase::class) {
+    return;
+  }
+
+  // We only check the per-entity-type permissions. JSON:API can filter
+  // cross-bundle, and there is no API yet for communicating per-bundle
+  // conditions to JSON:API, so users with only bundle-level permissions
+  // can't use JSON:API filters yet.
+  $view = AccessResult::allowedIfHasPermission($account, 'view ' . $entity_type->id());
+  $view_any = AccessResult::allowedIfHasPermission($account, 'view any ' . $entity_type->id());
+  $view_own = AccessResult::allowedIfHasPermission($account, 'view own ' . $entity_type->id());
+  $view_own_unpublished = AccessResult::allowedIfHasPermission($account, 'view own unpublished ' . $entity_type->id());
+
+  // EntityAccessControlHandlerBase::checkAccess() branches based on if the
+  // entity class implements EntityOwnerInterface.
+  if ($entity_type->entityClassImplements(EntityOwnerInterface::class)) {
+    // For entity classes that implement EntityOwnerInterface,
+    // checkEntityOwnerPermissions() is called. This module provides 3
+    // different implementations of that.
+    $reflector = new ReflectionMethod($access_class, 'checkEntityOwnerPermissions');
+    $declaring_class = $reflector->getDeclaringClass()->getName();
+    if ($declaring_class === EntityAccessControlHandlerBase::class) {
+      // @see EntityAccessControlHandlerBase::checkEntityOwnerPermissions()
+      return ([
+        JSONAPI_FILTER_AMONG_ALL => $view_any,
+        JSONAPI_FILTER_AMONG_OWN => $view_own,
+      ]);
+    }
+    elseif ($declaring_class === EntityAccessControlHandler::class) {
+      // @see EntityAccessControlHandler::checkEntityOwnerPermissions()
+      if ($entity_type->entityClassImplements(EntityPublishedInterface::class)) {
+        return ([
+          JSONAPI_FILTER_AMONG_PUBLISHED => $view,
+          JSONAPI_FILTER_AMONG_OWN => $view->andIf($view_own_unpublished),
+        ]);
+      }
+      else {
+        return ([
+          JSONAPI_FILTER_AMONG_ALL => $view,
+        ]);
+      }
+    }
+    elseif ($declaring_class === UncacheableEntityAccessControlHandler::class) {
+      // @see UncacheableEntityAccessControlHandler::checkEntityOwnerPermissions()
+      if ($entity_type->entityClassImplements(EntityPublishedInterface::class)) {
+        return ([
+          JSONAPI_FILTER_AMONG_PUBLISHED => $view_any,
+          JSONAPI_FILTER_AMONG_OWN => $view_own->andIf($view_own_unpublished),
+        ]);
+      }
+      else {
+        return ([
+          JSONAPI_FILTER_AMONG_ALL => $view_any,
+          JSONAPI_FILTER_AMONG_OWN => $view_own,
+        ]);
+      }
+    }
+  }
+  else {
+    // For entity classes that don't implement EntityOwnerInterface,
+    // checkEntityPermissions() is called. This module provides only a single
+    // implementation of that.
+    $reflector = new ReflectionMethod($access_class, 'checkEntityPermissions');
+    if ($reflector->getDeclaringClass()->getName() !== EntityAccessControlHandlerBase::class) {
+      return;
+    }
+    // @see EntityAccessControlHandlerBase::checkEntityPermissions()
+    return ([
+      JSONAPI_FILTER_AMONG_ALL => $view,
+    ]);
+  }
+}
