diff --git a/src/Authorization/AuthorizationDataMuxer.php b/src/Authorization/AuthorizationDataMuxer.php
index f3e0673d17a8546d78808017b3bbf81eec135030..3cf2865d70dd4536c805b65f17935477524b87b0 100644
--- a/src/Authorization/AuthorizationDataMuxer.php
+++ b/src/Authorization/AuthorizationDataMuxer.php
@@ -113,7 +113,7 @@ class AuthorizationDataMuxer
         }
 
         $wasFound = false;
-        $value = null;
+        $value = $defaultValue;
         foreach ($this->authorizationDataProviders as $authorizationDataProvider) {
             $availableAttributes = $this->getProviderAvailableAttributes($authorizationDataProvider);
             if (!in_array($attributeName, $availableAttributes, true)) {
@@ -124,15 +124,11 @@ class AuthorizationDataMuxer
                 continue;
             }
             $value = $userAttributes[$attributeName];
-            $wasFound = true;
             break;
         }
 
-        $event = new GetAttributeEvent($this, $attributeName, $userIdentifier);
-
-        if ($wasFound) {
-            $event->setValue($value);
-        }
+        $event = new GetAttributeEvent($this, $attributeName, $value, $userIdentifier);
+        $event->setAttributeValue($value);
 
         // Avoid endless recursions by only emitting an event for each attribtue only once
         if (!in_array($attributeName, $this->attributeStack, true)) {
@@ -141,6 +137,6 @@ class AuthorizationDataMuxer
             array_pop($this->attributeStack);
         }
 
-        return $event->getValue($defaultValue);
+        return $event->getAttributeValue();
     }
 }
diff --git a/src/Authorization/Event/GetAttributeEvent.php b/src/Authorization/Event/GetAttributeEvent.php
index d825d5236a2755b2558b1b886a58c6bdf64687f0..b00f66911e4b1cb0a59c149b343232bd0f791074 100644
--- a/src/Authorization/Event/GetAttributeEvent.php
+++ b/src/Authorization/Event/GetAttributeEvent.php
@@ -29,24 +29,22 @@ class GetAttributeEvent extends Event
     /**
      * @var string
      */
-    private $name;
+    private $attributeName;
 
     /**
      * @var mixed
      */
-    private $value;
+    private $attributeValue;
 
     /**
-     * @var bool
+     * @param mixed $attributeValue
      */
-    private $hasValue;
-
-    public function __construct(AuthorizationDataMuxer $mux, string $name, ?string $userIdentifier)
+    public function __construct(AuthorizationDataMuxer $mux, string $attributeName, $attributeValue, ?string $userIdentifier)
     {
         $this->mux = $mux;
         $this->userIdentifier = $userIdentifier;
-        $this->name = $name;
-        $this->hasValue = false;
+        $this->attributeName = $attributeName;
+        $this->attributeValue = $attributeValue;
     }
 
     /**
@@ -61,29 +59,27 @@ class GetAttributeEvent extends Event
 
     public function getAttributeName(): string
     {
-        return $this->name;
+        return $this->attributeName;
     }
 
     /**
-     * @param mixed $value
+     * @param mixed $attributeValue
      */
-    public function setValue($value): void
+    public function setAttributeValue($attributeValue): void
     {
-        $this->value = $value;
-        $this->hasValue = true;
+        $this->attributeValue = $attributeValue;
     }
 
     /**
-     * @param mixed $default
-     *
      * @return mixed
      */
-    public function getValue($default = null)
+    public function getAttributeValue()
     {
-        if (!$this->hasValue) {
-            return $default;
-        }
+        return $this->attributeValue;
+    }
 
-        return $this->value;
+    public function getUserIdentifier(): ?string
+    {
+        return $this->userIdentifier;
     }
 }
diff --git a/src/Authorization/Event/GetAvailableAttributesEvent.php b/src/Authorization/Event/GetAvailableAttributesEvent.php
index 58010126c882abc52e3241189e19748a87f5adcf..660c1d0723040d2b6fc6255e2d36250cf679fbfc 100644
--- a/src/Authorization/Event/GetAvailableAttributesEvent.php
+++ b/src/Authorization/Event/GetAvailableAttributesEvent.php
@@ -27,23 +27,18 @@ class GetAvailableAttributesEvent extends Event
     }
 
     /**
-     * @return string[]
+     * @param string[] $attributes
      */
-    public function getAttributes(): array
+    public function addAttributes(array $attributes): void
     {
-        return $this->attributes;
+        $this->attributes = array_merge($this->attributes, $attributes);
     }
 
     /**
-     * @param string[] $attributes
+     * @return string[]
      */
-    public function setAttributes(array $attributes): void
-    {
-        $this->attributes = $attributes;
-    }
-
-    public function addAttribute(string $name): void
+    public function getAttributes(): array
     {
-        $this->attributes[] = $name;
+        return $this->attributes;
     }
 }
diff --git a/src/Authorization/EventSubscriber/AbstractGetAttributeSubscriber.php b/src/Authorization/EventSubscriber/AbstractGetAttributeSubscriber.php
new file mode 100644
index 0000000000000000000000000000000000000000..2b30bd60e7b28834e4fbef93f22ff247f9472099
--- /dev/null
+++ b/src/Authorization/EventSubscriber/AbstractGetAttributeSubscriber.php
@@ -0,0 +1,64 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Dbp\Relay\CoreBundle\Authorization\EventSubscriber;
+
+use Dbp\Relay\CoreBundle\Authorization\Event\GetAttributeEvent;
+use Dbp\Relay\CoreBundle\Authorization\Event\GetAvailableAttributesEvent;
+use Symfony\Component\EventDispatcher\EventSubscriberInterface;
+
+abstract class AbstractGetAttributeSubscriber implements EventSubscriberInterface
+{
+    /** @var GetAttributeEvent|null */
+    private $event;
+
+    public static function getSubscribedEvents(): array
+    {
+        return [
+            GetAvailableAttributesEvent::class => 'onGetAvailableAttributes',
+            GetAttributeEvent::class => 'onGetAttributeEvent',
+        ];
+    }
+
+    public function onGetAvailableAttributes(GetAvailableAttributesEvent $event)
+    {
+        $event->addAttributes($this->getAvailableAttributes());
+    }
+
+    public function onGetAttributeEvent(GetAttributeEvent $event)
+    {
+        try {
+            $this->event = $event;
+
+            $attributeName = $event->getAttributeName();
+            if (in_array($attributeName, $this->getAvailableAttributes(), true)) {
+                $event->setAttributeValue($this->getUserAttributeValue($event->getUserIdentifier(), $attributeName, $event->getAttributeValue()));
+            }
+        } finally {
+            $this->event = null;
+        }
+    }
+
+    /**
+     * @param mixed|null $defaultValue
+     *
+     * @return mixed|null
+     */
+    public function getAttribute(string $attributeName, $defaultValue = null)
+    {
+        return $this->event->getAttribute($attributeName, $defaultValue);
+    }
+
+    /*
+     * @return string[]
+     */
+    abstract protected function getAvailableAttributes(): array;
+
+    /**
+     * @param mixed|null $attributeValue
+     *
+     * @return mixed|null
+     */
+    abstract protected function getUserAttributeValue(?string $userIdentifier, string $attributeName, $attributeValue);
+}