diff --git a/src/API/UserSessionInterface.php b/src/API/UserSessionInterface.php
index ce3e3df3264c2d58765dd696d0b3fb89c234974f..8bc5b1b62dbe32cf32a0fa18779a010b7434a5d5 100644
--- a/src/API/UserSessionInterface.php
+++ b/src/API/UserSessionInterface.php
@@ -6,58 +6,37 @@ namespace Dbp\Relay\CoreBundle\API;
 
 interface UserSessionInterface
 {
-    /**
-     * This gets called with the active JWT before any of the other methods are called.
-     */
-    public function setSessionToken(?array $jwt): void;
-
     /**
      * The unique identifier of the authenticated user. Or null in case it is called
      * before the user is known or if the user is a system.
-     *
-     * Can be derived from the session token for example.
      */
     public function getUserIdentifier(): ?string;
 
-    /**
-     * Returns a list of Symfony user roles, like ['ROLE_FOOBAR'].
-     *
-     * Can be derived from the session token for example.
-     */
-    public function getUserRoles(): array;
-
     /**
      * Returns an ID represents a "session" of a user which can be used for logging. It should not be possible to
      * figure out which user is behind the ID based on the ID itself and the ID should change regularly.
      * This is useful for connecting various requests together for logging while not exposing details about the user.
-     *
-     * Can be derived from long running session IDs embedded in the token for example.
-     *
-     * Return null in case no logging ID exists
      */
-    public function getSessionLoggingId(): ?string;
+    public function getSessionLoggingId(): string;
+
+    /**
+     * @deprecated
+     */
+    public function getUserRoles(): array;
 
     /**
      * Returns a unique caching key that can be used to cache metadata related to the current user session like
      * any user metadata, authorization related information etc.
      * It should not be possible to figure out which user is behind the ID based on the ID itself and the ID should
      * change regularly (after a logout/login or a key refresh for example).
-     *
-     * For example a hashed version of the token.
-     *
-     * Return null in case no appropriate cache key exists to disable any caching.
      */
-    public function getSessionCacheKey(): ?string;
+    public function getSessionCacheKey(): string;
 
     /**
-     * Should return the duration the session is valid (as a whole, not from now) in seconds.
+     * Returns the duration the session is valid (as a whole, not from now) in seconds.
      * After the specified amount of time has passed the logging ID and the caching key should have changed.
      *
      * This is mostly useful for limiting the cache.
-     *
-     * For example the lifespan of the token.
-     *
-     * Return <0 in case that information isn't available.
      */
     public function getSessionTTL(): int;
 }
diff --git a/src/Auth/ProxyAuthenticator.php b/src/Auth/ProxyAuthenticator.php
index 7fdafe8433cc8c410a2c0766ebd1e20b0a253d21..eb80e473f49e0d4a3bdc1d040e451fa2a7d61b3d 100644
--- a/src/Auth/ProxyAuthenticator.php
+++ b/src/Auth/ProxyAuthenticator.php
@@ -19,9 +19,15 @@ class ProxyAuthenticator extends AbstractAuthenticator
      */
     private $authenticators;
 
-    public function __construct()
+    /**
+     * @var UserSession
+     */
+    private $userSession;
+
+    public function __construct(UserSession $userSession)
     {
         $this->authenticators = [];
+        $this->userSession = $userSession;
     }
 
     public function addAuthenticator(AuthenticatorInterface $sub)
@@ -54,7 +60,11 @@ class ProxyAuthenticator extends AbstractAuthenticator
         $auth = $this->getAuthenticator($request);
         assert($auth !== null);
 
-        return $auth->authenticate($request);
+        $passport = $auth->authenticate($request);
+        $provider = $passport->getAttribute('relay_user_session_provider');
+        $this->userSession->setProvider($provider);
+
+        return $passport;
     }
 
     public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response
@@ -67,6 +77,8 @@ class ProxyAuthenticator extends AbstractAuthenticator
 
     public function onAuthenticationFailure(Request $request, AuthenticationException $exception): ?Response
     {
+        $this->userSession->setProvider(null);
+
         $auth = $this->getAuthenticator($request);
         assert($auth !== null);
 
diff --git a/src/Auth/UserSession.php b/src/Auth/UserSession.php
new file mode 100644
index 0000000000000000000000000000000000000000..461d9f3630c136b2b1ce8acb6e5b1d861a19a38d
--- /dev/null
+++ b/src/Auth/UserSession.php
@@ -0,0 +1,98 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Dbp\Relay\CoreBundle\Auth;
+
+use Dbp\Relay\CoreBundle\API\UserSessionInterface;
+use Dbp\Relay\CoreBundle\API\UserSessionProviderInterface;
+use Symfony\Component\Security\Core\Security;
+use Symfony\Component\Uid\Uuid;
+
+/**
+ * This service provides user session information, either sourcing information from the active auth provider
+ * or in case it is used from the CLI or unauthenticated then it returns some reasonable defaults.
+ */
+class UserSession implements UserSessionInterface
+{
+    /**
+     * @var ?UserSessionProviderInterface
+     */
+    private $provider;
+
+    /**
+     * @var Security
+     */
+    private $security;
+
+    public function __construct(?Security $security = null)
+    {
+        $this->security = $security;
+    }
+
+    public function setProvider(?UserSessionProviderInterface $provider)
+    {
+        $this->provider = $provider;
+    }
+
+    public function getUserIdentifier(): ?string
+    {
+        if ($this->provider === null) {
+            return null;
+        }
+
+        return $this->provider->getUserIdentifier();
+    }
+
+    public function getSessionLoggingId(): string
+    {
+        $id = null;
+        if ($this->provider !== null) {
+            $id = $this->provider->getSessionLoggingId();
+        }
+        if ($id === null) {
+            $id = 'unknown';
+        }
+
+        return $id;
+    }
+
+    public function getSessionCacheKey(): string
+    {
+        $key = null;
+        if ($this->provider !== null) {
+            $key = $this->provider->getSessionCacheKey();
+        }
+        if ($key === null) {
+            $key = (Uuid::v4())->toRfc4122();
+        }
+
+        return $key;
+    }
+
+    public function getSessionTTL(): int
+    {
+        $ttl = -1;
+        if ($this->provider !== null) {
+            $ttl = $this->provider->getSessionTTL();
+        }
+        if ($ttl === -1) {
+            $ttl = 60;
+        }
+
+        return $ttl;
+    }
+
+    public function getUserRoles(): array
+    {
+        if ($this->provider === null) {
+            return [];
+        }
+        $user = $this->security->getUser();
+        if ($user === null) {
+            return [];
+        }
+
+        return $user->getRoles();
+    }
+}
diff --git a/src/Logging/LoggingProcessor.php b/src/Logging/LoggingProcessor.php
index e014fabb08c0eac79ce40d9505dc1c347dde4233..0b6c309f90a30e5a71d495669a4278fd14943d29 100644
--- a/src/Logging/LoggingProcessor.php
+++ b/src/Logging/LoggingProcessor.php
@@ -43,10 +43,7 @@ final class LoggingProcessor
         $this->maskUserId($record);
 
         // Add a session ID (the same during multiple requests for the same user session)
-        $loggingId = $this->userDataProvider->getSessionLoggingId();
-        if ($loggingId !== null) {
-            $record['context']['relay-session-id'] = $loggingId;
-        }
+        $record['context']['relay-session-id'] = $this->userDataProvider->getSessionLoggingId();
 
         // Add a request ID (the same during the same client request)
         $request = $this->requestStack->getMainRequest();
diff --git a/src/Resources/config/services.yaml b/src/Resources/config/services.yaml
index 9a563541a14e17824d38792add600cc1fbfb4474..fef566f3e835fd5ff3bccce6ffb91d70a59ff8af 100644
--- a/src/Resources/config/services.yaml
+++ b/src/Resources/config/services.yaml
@@ -58,6 +58,13 @@ services:
     autowire: true
     autoconfigure: true
 
+  Dbp\Relay\CoreBundle\Auth\UserSession:
+    autowire: true
+    autoconfigure: true
+
+  Dbp\Relay\CoreBundle\API\UserSessionInterface:
+    '@Dbp\Relay\CoreBundle\Auth\UserSession'
+
   Dbp\Relay\CoreBundle\LocalData\LocalDataAwareEventDispatcher:
     autowire: true
     autoconfigure: true
diff --git a/src/TestUtils/TestUserSession.php b/src/TestUtils/TestUserSession.php
index 1abe5873c26ab63012b5b49ec61c9a71f1e49305..672648370e8d50131bf7665b9dfd1beadbcb199b 100644
--- a/src/TestUtils/TestUserSession.php
+++ b/src/TestUtils/TestUserSession.php
@@ -41,12 +41,12 @@ class TestUserSession implements UserSessionInterface
         return $this->roles;
     }
 
-    public function getSessionLoggingId(): ?string
+    public function getSessionLoggingId(): string
     {
         return 'logging-id';
     }
 
-    public function getSessionCacheKey(): ?string
+    public function getSessionCacheKey(): string
     {
         return 'cache';
     }
diff --git a/tests/Auth/AuthenticatorTest.php b/tests/Auth/AuthenticatorTest.php
index 26d9879b226455b678f50a1476312c9711976705..99dc9f9f491c58ed7953da392b08a20ac0d63992 100644
--- a/tests/Auth/AuthenticatorTest.php
+++ b/tests/Auth/AuthenticatorTest.php
@@ -6,6 +6,7 @@ namespace Dbp\Relay\CoreBundle\Tests\Auth;
 
 use Dbp\Relay\CoreBundle\Auth\AuthenticatorCompilerPass;
 use Dbp\Relay\CoreBundle\Auth\ProxyAuthenticator;
+use Dbp\Relay\CoreBundle\Auth\UserSession;
 use Dbp\Relay\CoreBundle\TestUtils\TestAuthenticator;
 use Dbp\Relay\CoreBundle\TestUtils\TestUser;
 use PHPUnit\Framework\TestCase;
@@ -17,13 +18,13 @@ class AuthenticatorTest extends TestCase
 {
     public function testSupports()
     {
-        $auth = new ProxyAuthenticator();
+        $auth = new ProxyAuthenticator(new UserSession());
         $this->assertFalse($auth->supports(new Request()));
     }
 
     public function testSingle()
     {
-        $auth = new ProxyAuthenticator();
+        $auth = new ProxyAuthenticator(new UserSession());
         $user = new TestUser();
         $sub = new TestAuthenticator($user, 'bla');
         $auth->addAuthenticator($sub);