diff --git a/src/Authorization/AuthorizationDataMuxer.php b/src/Authorization/AuthorizationDataMuxer.php
index e6e811af2d9462d93b249b178c6cd5efdee9206f..984580e8064838e172463404562d38aab2165225 100644
--- a/src/Authorization/AuthorizationDataMuxer.php
+++ b/src/Authorization/AuthorizationDataMuxer.php
@@ -16,10 +16,10 @@ class AuthorizationDataMuxer
     /** @var iterable<AuthorizationDataProviderInterface> */
     private $authorizationDataProviders;
 
-    /** @var array<string, array> */
+    /** @var array<int, array> */
     private $providerCache;
 
-    /** @var array<string, string[]> */
+    /** @var array<int, string[]> */
     private $availableCache;
 
     /** @var EventDispatcherInterface */
@@ -73,7 +73,7 @@ class AuthorizationDataMuxer
     private function getProviderAvailableAttributes(AuthorizationDataProviderInterface $prov): array
     {
         // Caches getAvailableAttributes for each provider
-        $provKey = get_class($prov);
+        $provKey = spl_object_id($prov);
         if (!array_key_exists($provKey, $this->availableCache)) {
             $this->availableCache[$provKey] = $prov->getAvailableAttributes();
         }
@@ -89,7 +89,7 @@ class AuthorizationDataMuxer
     private function getProviderUserAttributes(AuthorizationDataProviderInterface $prov, ?string $userIdentifier): array
     {
         // We cache the attributes for each provider, but only for the last userIdentifier
-        $provKey = get_class($prov);
+        $provKey = spl_object_id($prov);
         if (!array_key_exists($provKey, $this->providerCache) || $this->providerCache[$provKey][0] !== $userIdentifier) {
             $this->providerCache[$provKey] = [$userIdentifier, $prov->getUserAttributes($userIdentifier)];
         }
@@ -112,7 +112,7 @@ class AuthorizationDataMuxer
             throw new AuthorizationException(sprintf('attribute \'%s\' undefined', $attributeName), AuthorizationException::ATTRIBUTE_UNDEFINED);
         }
 
-        $value = $defaultValue;
+        $value = null;
         foreach ($this->authorizationDataProviders as $authorizationDataProvider) {
             $availableAttributes = $this->getProviderAvailableAttributes($authorizationDataProvider);
             if (!in_array($attributeName, $availableAttributes, true)) {
@@ -140,6 +140,6 @@ class AuthorizationDataMuxer
             array_pop($this->attributeStack);
         }
 
-        return $event->getAttributeValue();
+        return $event->getAttributeValue() ?? $defaultValue;
     }
 }
diff --git a/tests/Authorization/AuthorizationDataMuxerTest.php b/tests/Authorization/AuthorizationDataMuxerTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..53d938bdd76439559a4e491ac8900f5d3bd53317
--- /dev/null
+++ b/tests/Authorization/AuthorizationDataMuxerTest.php
@@ -0,0 +1,103 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Dbp\Relay\CoreBundle\Tests\Authorization;
+
+use Dbp\Relay\CoreBundle\Authorization\AuthorizationDataMuxer;
+use Dbp\Relay\CoreBundle\Authorization\AuthorizationDataProviderProvider;
+use Dbp\Relay\CoreBundle\Authorization\Event\GetAttributeEvent;
+use Dbp\Relay\CoreBundle\Authorization\Event\GetAvailableAttributesEvent;
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\EventDispatcher\EventDispatcher;
+
+class AuthorizationDataMuxerTest extends TestCase
+{
+    public function testBasics()
+    {
+        $dummy = new DummyAuthorizationDataProvider(['foo' => 42], ['foo', 'bar']);
+        $mux = new AuthorizationDataMuxer(new AuthorizationDataProviderProvider([$dummy]), new EventDispatcher());
+        $this->assertSame(['foo', 'bar'], $mux->getAvailableAttributes());
+        $this->assertSame(42, $mux->getAttribute(null, 'foo'));
+        $this->assertSame(24, $mux->getAttribute(null, 'bar', 24));
+    }
+
+    public function testMultiple()
+    {
+        $dummy = new DummyAuthorizationDataProvider(['foo' => 42], ['foo', 'qux']);
+        $dummy2 = new DummyAuthorizationDataProvider(['bar' => 24], ['bar', 'baz']);
+
+        $mux = new AuthorizationDataMuxer(new AuthorizationDataProviderProvider([$dummy, $dummy2]), new EventDispatcher());
+        $this->assertSame(['foo', 'qux', 'bar', 'baz'], $mux->getAvailableAttributes());
+        $this->assertSame(42, $mux->getAttribute(null, 'foo'));
+        $this->assertSame('default', $mux->getAttribute(null, 'qux', 'default'));
+        $this->assertSame(24, $mux->getAttribute(null, 'bar'));
+        $this->assertSame(12, $mux->getAttribute(null, 'baz', 12));
+        $this->assertNull($mux->getAttribute(null, 'baz'));
+    }
+
+    public function testAvailEvent()
+    {
+        $dummy = new DummyAuthorizationDataProvider(['foo' => 42], ['foo', 'bar']);
+        $dispatched = new EventDispatcher();
+        $getAvail = function (GetAvailableAttributesEvent $event) {
+            $this->assertSame(['foo', 'bar'], $event->getAttributes());
+            $event->addAttributes(['new']);
+        };
+        $dispatched->addListener(GetAvailableAttributesEvent::class, $getAvail);
+        $getAvail2 = function (GetAvailableAttributesEvent $event) {
+            $event->addAttributes(['new2']);
+        };
+        $dispatched->addListener(GetAvailableAttributesEvent::class, $getAvail2);
+        $mux = new AuthorizationDataMuxer(new AuthorizationDataProviderProvider([$dummy]), $dispatched);
+        $this->assertSame(['foo', 'bar', 'new', 'new2'], $mux->getAvailableAttributes());
+    }
+
+    public function testGetAttrEvent()
+    {
+        $dummy = new DummyAuthorizationDataProvider(['foo' => 42], ['foo', 'bar']);
+        $dispatched = new EventDispatcher();
+        $getAttr = function (GetAttributeEvent $event) {
+            $this->assertSame('myuser', $event->getUserIdentifier());
+            $this->assertSame('bar', $event->getAttributeName());
+            $this->assertNull($event->getAttributeValue());
+            $event->setAttributeValue('OK');
+        };
+        $dispatched->addListener(GetAttributeEvent::class, $getAttr);
+        $mux = new AuthorizationDataMuxer(new AuthorizationDataProviderProvider([$dummy]), $dispatched);
+        $this->assertSame('OK', $mux->getAttribute('myuser', 'bar'));
+    }
+
+    public function testGetAttrEventDefault()
+    {
+        $dummy = new DummyAuthorizationDataProvider([], []);
+        $dispatched = new EventDispatcher();
+        $getAvail = function (GetAvailableAttributesEvent $event) {
+            $event->addAttributes(['bar']);
+        };
+        $dispatched->addListener(GetAvailableAttributesEvent::class, $getAvail);
+        $getAttr = function (GetAttributeEvent $event) {
+            $this->assertNull($event->getAttributeValue());
+        };
+        $dispatched->addListener(GetAttributeEvent::class, $getAttr);
+        $mux = new AuthorizationDataMuxer(new AuthorizationDataProviderProvider([$dummy]), $dispatched);
+        $this->assertSame('Default', $mux->getAttribute('myuser', 'bar', 'Default'));
+    }
+
+    public function testGetAttrMultipleEvents()
+    {
+        $dummy = new DummyAuthorizationDataProvider(['foo' => 42], ['foo', 'bar']);
+        $dispatched = new EventDispatcher();
+        $getAttr = function (GetAttributeEvent $event) {
+            $event->setAttributeValue('OK');
+        };
+        $dispatched->addListener(GetAttributeEvent::class, $getAttr);
+        $getAttr2 = function (GetAttributeEvent $event) {
+            $this->assertSame('OK', $event->getAttributeValue());
+            $event->setAttributeValue('OK2');
+        };
+        $dispatched->addListener(GetAttributeEvent::class, $getAttr2);
+        $mux = new AuthorizationDataMuxer(new AuthorizationDataProviderProvider([$dummy]), $dispatched);
+        $this->assertSame('OK2', $mux->getAttribute('myuser', 'bar'));
+    }
+}
diff --git a/tests/Authorization/DummyAuthorizationDataProvider.php b/tests/Authorization/DummyAuthorizationDataProvider.php
new file mode 100644
index 0000000000000000000000000000000000000000..af4252a76644149c64656b5220967d2160e8e8ae
--- /dev/null
+++ b/tests/Authorization/DummyAuthorizationDataProvider.php
@@ -0,0 +1,39 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Dbp\Relay\CoreBundle\Tests\Authorization;
+
+use Dbp\Relay\CoreBundle\Authorization\AuthorizationDataProviderInterface;
+
+class DummyAuthorizationDataProvider implements AuthorizationDataProviderInterface
+{
+    /**
+     * @var array
+     */
+    private $attributes;
+
+    /**
+     * @var array
+     */
+    private $available;
+
+    public function __construct(array $attributes, array $available = null)
+    {
+        $this->attributes = $attributes;
+        $this->available = $available ?? array_keys($attributes);
+    }
+
+    /**
+     * @return string[]
+     */
+    public function getAvailableAttributes(): array
+    {
+        return $this->available;
+    }
+
+    public function getUserAttributes(?string $userIdentifier): array
+    {
+        return $this->attributes;
+    }
+}