diff --git a/masquerade.services.yml b/masquerade.services.yml
index f869a1e..f23f065 100644
--- a/masquerade.services.yml
+++ b/masquerade.services.yml
@@ -14,3 +14,8 @@ services:
     arguments: ['@masquerade']
     tags:
       - { name: access_check, applies_to: _user_is_masquerading }
+  cache_context.is_masquerading:
+    class: Drupal\masquerade\Cache\MasqueradeCacheContext
+    arguments: ['@request_stack']
+    tags:
+      - { name: cache.context }
diff --git a/src/Access/UnmasqueradeAccessCheck.php b/src/Access/UnmasqueradeAccessCheck.php
index 5444b7d..83ae118 100644
--- a/src/Access/UnmasqueradeAccessCheck.php
+++ b/src/Access/UnmasqueradeAccessCheck.php
@@ -40,7 +40,7 @@ class UnmasqueradeAccessCheck implements AccessInterface {
    */
   public function access() {
     return AccessResult::allowedIf($this->masquerade->isMasquerading())
-      ->setCacheMaxAge(0);
+      ->addCacheContexts(['is_masquerading']);
   }
 
 }
diff --git a/src/Cache/MasqueradeCacheContext.php b/src/Cache/MasqueradeCacheContext.php
new file mode 100644
index 0000000..6d1aae6
--- /dev/null
+++ b/src/Cache/MasqueradeCacheContext.php
@@ -0,0 +1,46 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\masquerade\Cache\MasqueradeCacheContext.
+ */
+
+namespace Drupal\masquerade\Cache;
+
+use Drupal\Core\Cache\CacheableMetadata;
+use Drupal\Core\Cache\Context\CacheContextInterface;
+use Drupal\Core\Cache\Context\RequestStackCacheContextBase;
+use Drupal\Core\StringTranslation\TranslatableMarkup;
+
+/**
+ * Defines the MasqueradeCacheContext service, for "masquerade" caching.
+ *
+ * Cache context ID: 'is_masquerading'.
+ */
+class MasqueradeCacheContext extends RequestStackCacheContextBase implements CacheContextInterface {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getLabel() {
+    return new TranslatableMarkup('User is masquerading');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getContext() {
+    return $this->requestStack
+      ->getCurrentRequest()
+      ->getSession()
+      ->has('masquerading');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getCacheableMetadata() {
+    return new CacheableMetadata();
+  }
+
+}
diff --git a/src/Plugin/Block/MasqueradeBlock.php b/src/Plugin/Block/MasqueradeBlock.php
index 97716f2..4100b0a 100644
--- a/src/Plugin/Block/MasqueradeBlock.php
+++ b/src/Plugin/Block/MasqueradeBlock.php
@@ -9,10 +9,12 @@ namespace Drupal\masquerade\Plugin\Block;
 
 use Drupal\Core\Access\AccessResult;
 use Drupal\Core\Block\BlockBase;
+use Drupal\Core\Cache\Cache;
 use Drupal\Core\Form\FormBuilderInterface;
 use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
 use Drupal\Core\Session\AccountInterface;
 use Drupal\masquerade\Masquerade;
+use Drupal\user\PermissionHandlerInterface;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
@@ -34,6 +36,13 @@ class MasqueradeBlock extends BlockBase implements ContainerFactoryPluginInterfa
   protected $formBuilder;
 
   /**
+   * The permission handler.
+   *
+   * @var \Drupal\user\PermissionHandlerInterface
+   */
+  protected $permissionHandler;
+
+  /**
    * The masquerade service.
    *
    * @var \Drupal\masquerade\Masquerade
@@ -51,13 +60,16 @@ class MasqueradeBlock extends BlockBase implements ContainerFactoryPluginInterfa
    *   The plugin implementation definition.
    * @param \Drupal\Core\Form\FormBuilderInterface $form_builder
    *   The form builder service.
+   * @param \Drupal\user\PermissionHandlerInterface $permission_handler
+   *   The permission handler.
    * @param \Drupal\masquerade\Masquerade $masquerade
    *   The masquerade service.
    */
-  public function __construct(array $configuration, $plugin_id, $plugin_definition, FormBuilderInterface $form_builder, Masquerade $masquerade) {
+  public function __construct(array $configuration, $plugin_id, $plugin_definition, FormBuilderInterface $form_builder, PermissionHandlerInterface $permission_handler, Masquerade $masquerade) {
     parent::__construct($configuration, $plugin_id, $plugin_definition);
 
     $this->formBuilder = $form_builder;
+    $this->permissionHandler = $permission_handler;
     $this->masquerade = $masquerade;
   }
 
@@ -70,6 +82,7 @@ class MasqueradeBlock extends BlockBase implements ContainerFactoryPluginInterfa
       $plugin_id,
       $plugin_definition,
       $container->get('form_builder'),
+      $container->get('user.permissions'),
       $container->get('masquerade')
     );
   }
@@ -78,16 +91,25 @@ class MasqueradeBlock extends BlockBase implements ContainerFactoryPluginInterfa
    * {@inheritdoc}
    */
   protected function blockAccess(AccountInterface $account) {
-    $allowed = $account->hasPermission('masquerade as any user') && !$this->masquerade->isMasquerading();
-    return AccessResult::allowedIf($allowed);
+    if ($this->masquerade->isMasquerading()) {
+      return AccessResult::forbidden()->addCacheContexts(['is_masquerading']);
+    }
+    $permissions = [];
+    foreach ($this->permissionHandler->getPermissions() as $name => $permission) {
+      if ($permission['provider'] === 'masquerade') {
+        // Filter only module's permissions.
+        $permissions[] = $name;
+      }
+    }
+    // Display block for all users that has any of masquerade permissions.
+    return AccessResult::allowedIfHasPermissions($account, $permissions, 'OR');
   }
 
   /**
    * {@inheritdoc}
    */
-  public function getCacheMaxAge() {
-    // @todo Fix caching https://www.drupal.org/node/2448699.
-    return 0;
+  public function getCacheContexts() {
+    return Cache::mergeContexts(parent::getCacheContexts(), ['is_masquerading']);
   }
 
   /**
