diff --git a/includes/processor_node_access.inc b/includes/processor_node_access.inc
new file mode 100644
index 0000000..580bd5d
--- /dev/null
+++ b/includes/processor_node_access.inc
@@ -0,0 +1,115 @@
+<?php
+/**
+ * @file
+ * Processor for applying node access to a query.
+ */
+// @TODO:
+// It might make sense to use query instead of
+// altering the query
+// @see SearchApiHtmlFilter::@todo
+class SearchApiNodeAccess extends SearchApiAbstractProcessor {
+  /**
+   * Override the configuration form of the default processfor.
+   */
+  public function configurationForm() {
+    return array();
+  }
+
+  public function preprocessIndexItems(array &$items) {
+    parent::preprocessIndexItems($items);
+
+    static $account;
+
+    if (!isset($account)) {
+      // Load the anonymous user.
+      $account = drupal_anonymous_user();
+    }
+
+    if ($this->index->item_type == 'node') {
+      // Load all notes as once.
+      foreach ($items as $nid => &$item) {
+        $nids[$nid] = $nid;
+      }
+      $nodes = node_load_multiple($nids);
+
+      foreach ($nodes as $nid => $node) {
+        // Check whether all users have access to the node.
+        if (!node_access('view', $node, $account)) {
+          // Get node access grants.
+          $result = db_query('SELECT * FROM {node_access} WHERE (nid = 0 OR nid = :nid) AND grant_view = 1', array(':nid' => $node->nid));
+
+          // Store all grants together with it's realms in the item.
+          foreach ($result as $grant) {
+            if (!isset($item['access_node'])) {
+              $items[$nid]['access_node'] = array(
+                'name' => 'access_node',
+                'value' => array(),
+                'type' => 'list<string>',
+                'original' => 'list<string>',
+              );
+            }
+
+            $items[$nid]['access_node'][] = "node_access_$grant->{realm}:$graint->{gid}";;
+          }
+        }
+        else {
+          // Add the generic view grant if we are not using
+          // node access or the node is viewable by anonymous users.
+          // We assume we'll never have an entity with the name '_all'.
+          $items[$nid]['access_node'] = array(
+            'name' => 'access_node',
+            'value' => array('node_access__all'),
+            'type' => 'list<string>',
+            'original' => 'list<string>',
+          );
+        }
+      }
+    }
+  }
+
+  /**
+   * Alter search query to add filters for node access.
+   */
+  public function preprocessSearchQuery(SearchApiQuery $query) {
+    parent::preprocessSearchQuery($query);
+
+    $account = $GLOBALS['user'];
+
+    if ($query->index->item_type == 'node') {
+      try {
+        $accessQuery = $this->buildAccessQuery($account);
+        if ($accessQuery) {
+          $query->filter($accessQuery);
+        }
+      }
+      catch (SearchApiException $e) {
+        watchdog("search_api", 'User %name (UID:!uid) cannot search: @message', array('%name' => $account->name, '!uid' => $account->uid, '@message' => $e->getMessage()));
+      }
+    }
+  }
+
+  /**
+   * Build a node access subquery.
+   *
+   * @return SearchApiQueryFilter
+   */
+  function buildAccessQuery($account) {
+    if (!user_access('access content', $account)) {
+      throw new SearchApiException(t('The current user has no node access, uid: @uid', array('@uid' => $account->uid)));
+    }
+
+    // Only filter for user which don't have full node access.
+    if (!user_access('bypass node access', $account)) {
+      $nodeAccessQuery = new SearchApiQueryFilter('OR');
+        // Get node access grants.
+      $grants = node_access_grants('view', $account);
+      foreach ($grants as $realm => $gids) {
+        foreach ($gids as $gid) {
+          $nodeAccessQuery->condition('access_node', "node_access_$realm:$gid");
+        }
+      }
+      return $nodeAccessQuery;
+    }
+  }
+}
+
diff --git a/search_api.info b/search_api.info
index 7d3b55b..fdc0681 100644
--- a/search_api.info
+++ b/search_api.info
@@ -20,6 +20,7 @@ files[] = includes/index_entity.inc
 files[] = includes/processor.inc
 files[] = includes/processor_html_filter.inc
 files[] = includes/processor_ignore_case.inc
+files[] = includes/processor_node_access.inc
 files[] = includes/processor_stopwords.inc
 files[] = includes/processor_tokenizer.inc
 files[] = includes/query.inc
diff --git a/search_api.module b/search_api.module
index 249298b..18617b4 100644
--- a/search_api.module
+++ b/search_api.module
@@ -765,6 +765,14 @@ function search_api_search_api_processor_info() {
     'class' => 'SearchApiStopWords',
     'weight' => 30,
   );
+  $processors['search_api_node_access'] = array(
+    'name' => t('Node access'),
+    // @TODO: This description sucks.
+    'description' => t('This processor adds node access
+    to node indexes by retrieving some information from the node module.'),
+    'class' => 'SearchApiNodeAccess',
+    'weight' => 40,
+  );
 
   return $processors;
 }
