diff --git a/modules/block/block.module b/modules/block/block.module
index 1ab1c43..27969bf 100644
--- a/modules/block/block.module
+++ b/modules/block/block.module
@@ -884,7 +884,7 @@ function _block_get_cache_id($block) {
   // it brings too many chances of having unwanted output get in the cache
   // and later be served to other users. We therefore exclude user 1 from
   // block caching.
-  if (variable_get('block_cache', FALSE) && !in_array($block->cache, array(DRUPAL_NO_CACHE, DRUPAL_CACHE_CUSTOM)) && $user->uid != 1) {
+  if (variable_get('block_cache', FALSE) && $block->cache != DRUPAL_NO_CACHE && $block->cache != DRUPAL_CACHE_CUSTOM && $user->uid != 1) {
     // Start with common sub-patterns: block identification, theme, language.
     $cid_parts[] = $block->module;
     $cid_parts[] = $block->delta;
diff --git a/modules/contextual/contextual.module b/modules/contextual/contextual.module
index 0d6b625..907a727 100644
--- a/modules/contextual/contextual.module
+++ b/modules/contextual/contextual.module
@@ -170,3 +170,19 @@ function contextual_pre_render_links($element) {
   return $element;
 }
 
+/**
+ * Implements hook_block_info_alter().
+ */
+function contextual_block_info_alter(&$blocks) {
+  foreach ($blocks as &$module_blocks) {
+    foreach ($module_blocks as &$block) {
+      // Blocks that may be cached need to be cached at least per role.
+      // @see _block_get_cache_id()
+      // @see drupal_render_cid_parts()
+      if (isset($block->cache) && $block->cache != DRUPAL_NO_CACHE && $block->cache != DRUPAL_CACHE_CUSTOM) {
+        $block->cache |= DRUPAL_CACHE_PER_ROLE;
+      }
+    }
+  }
+}
+
diff --git a/modules/forum/forum.module b/modules/forum/forum.module
index f2ac5ac..789f948 100644
--- a/modules/forum/forum.module
+++ b/modules/forum/forum.module
@@ -671,8 +671,11 @@ function forum_block_view($delta = '') {
   }
 
   $block['subject'] = $title;
-  // Cache based on the altered query. Enables us to cache with node access enabled.
-  $block['content'] = drupal_render_cache_by_query($query, 'forum_block_view');
+  // Cache based on the altered query. Enables us to cache with node access
+  // enabled. However, contextual links on the block need to be cached at least
+  // per role.
+  // @see contextual_block_info_alter()
+  $block['content'] = drupal_render_cache_by_query($query, 'forum_block_view', CACHE_TEMPORARY, DRUPAL_CACHE_PER_ROLE);
   $block['content']['#access'] = user_access('access content');
   return $block;
 }
