diff --git a/app/Access/Controllers/LoginController.php b/app/Access/Controllers/LoginController.php
index 904736656..ce872ba88 100644
--- a/app/Access/Controllers/LoginController.php
+++ b/app/Access/Controllers/LoginController.php
@@ -10,27 +10,19 @@ use BookStack\Facades\Activity;
 use BookStack\Http\Controller;
 use Illuminate\Http\RedirectResponse;
 use Illuminate\Http\Request;
-use Illuminate\Support\Facades\Auth;
 use Illuminate\Validation\ValidationException;
 
 class LoginController extends Controller
 {
     use ThrottlesLogins;
 
-    protected SocialDriverManager $socialDriverManager;
-    protected LoginService $loginService;
-
-    /**
-     * Create a new controller instance.
-     */
-    public function __construct(SocialDriverManager $driverManager, LoginService $loginService)
-    {
+    public function __construct(
+        protected SocialDriverManager $socialDriverManager,
+        protected LoginService $loginService,
+    ) {
         $this->middleware('guest', ['only' => ['getLogin', 'login']]);
         $this->middleware('guard:standard,ldap', ['only' => ['login']]);
         $this->middleware('guard:standard,ldap,oidc', ['only' => ['logout']]);
-
-        $this->socialDriverManager = $driverManager;
-        $this->loginService = $loginService;
     }
 
     /**
@@ -52,7 +44,7 @@ class LoginController extends Controller
         // Store the previous location for redirect after login
         $this->updateIntendedFromPrevious();
 
-        if (!$preventInitiation && $this->shouldAutoInitiate()) {
+        if (!$preventInitiation && $this->loginService->shouldAutoInitiate()) {
             return view('auth.login-initiate', [
                 'authMethod'    => $authMethod,
             ]);
@@ -194,7 +186,7 @@ class LoginController extends Controller
     {
         // Store the previous location for redirect after login
         $previous = url()->previous('');
-        $isPreviousFromInstance = (strpos($previous, url('/')) === 0);
+        $isPreviousFromInstance = str_starts_with($previous, url('/'));
         if (!$previous || !setting('app-public') || !$isPreviousFromInstance) {
             return;
         }
@@ -205,7 +197,7 @@ class LoginController extends Controller
         ];
 
         foreach ($ignorePrefixList as $ignorePrefix) {
-            if (strpos($previous, url($ignorePrefix)) === 0) {
+            if (str_starts_with($previous, url($ignorePrefix))) {
                 return;
             }
         }
diff --git a/app/Access/LoginService.php b/app/Access/LoginService.php
index f0f6ad4d3..cc48e0f9b 100644
--- a/app/Access/LoginService.php
+++ b/app/Access/LoginService.php
@@ -176,14 +176,18 @@ class LoginService
     }
 
     /**
-     * Check if login auto-initiate should be valid based upon authentication config.
+     * Check if login auto-initiate should be active based upon authentication config.
      */
-    protected function shouldAutoInitiate(): bool
+    public function shouldAutoInitiate(): bool
     {
+        $autoRedirect = config('auth.auto_initiate');
+        if (!$autoRedirect) {
+            return false;
+        }
+
         $socialDrivers = $this->socialDriverManager->getActive();
         $authMethod = config('auth.method');
-        $autoRedirect = config('auth.auto_initiate');
 
-        return $autoRedirect && count($socialDrivers) === 0 && in_array($authMethod, ['oidc', 'saml2']);
+        return count($socialDrivers) === 0 && in_array($authMethod, ['oidc', 'saml2']);
     }
 }
diff --git a/app/Access/Oidc/OidcProviderSettings.php b/app/Access/Oidc/OidcProviderSettings.php
index fa3f579b1..bea6a523e 100644
--- a/app/Access/Oidc/OidcProviderSettings.php
+++ b/app/Access/Oidc/OidcProviderSettings.php
@@ -21,6 +21,7 @@ class OidcProviderSettings
     public ?string $redirectUri;
     public ?string $authorizationEndpoint;
     public ?string $tokenEndpoint;
+    public ?string $endSessionEndpoint;
 
     /**
      * @var string[]|array[]
@@ -132,6 +133,10 @@ class OidcProviderSettings
             $discoveredSettings['keys'] = $this->filterKeys($keys);
         }
 
+        if (!empty($result['end_session_endpoint'])) {
+            $discoveredSettings['endSessionEndpoint'] = $result['end_session_endpoint'];
+        }
+
         return $discoveredSettings;
     }
 
diff --git a/app/Access/Oidc/OidcService.php b/app/Access/Oidc/OidcService.php
index be869b179..3f9cd41b4 100644
--- a/app/Access/Oidc/OidcService.php
+++ b/app/Access/Oidc/OidcService.php
@@ -84,6 +84,7 @@ class OidcService
             'redirectUri'           => url('/oidc/callback'),
             'authorizationEndpoint' => $config['authorization_endpoint'],
             'tokenEndpoint'         => $config['token_endpoint'],
+            'endSessionEndpoint'    => $config['end_session_endpoint'],
         ]);
 
         // Use keys if configured
@@ -100,6 +101,11 @@ class OidcService
             }
         }
 
+        // Prevent use of RP-initiated logout if specifically disabled
+        if ($config['end_session_endpoint'] === false) {
+            $settings->endSessionEndpoint = null;
+        }
+
         $settings->validate();
 
         return $settings;
@@ -291,20 +297,23 @@ class OidcService
      * Start the RP-initiated logout flow if active, otherwise start a standard logout flow.
      * Returns a post-app-logout redirect URL.
      * Reference: https://openid.net/specs/openid-connect-rpinitiated-1_0.html
+     * @throws OidcException
      */
     public function logout(): string
     {
-        $endSessionEndpoint = $this->config()["end_session_endpoint"];
-
-        // TODO - Add autodiscovery and false/null config value support.
-
         $oidcToken = session()->pull("oidc_id_token");
         $defaultLogoutUrl = url($this->loginService->logout());
+        $oidcSettings = $this->getProviderSettings();
+
+        if (!$oidcSettings->endSessionEndpoint) {
+            return $defaultLogoutUrl;
+        }
+
         $endpointParams = [
             'id_token_hint' => $oidcToken,
             'post_logout_redirect_uri' => $defaultLogoutUrl,
         ];
 
-        return $endSessionEndpoint . '?' . http_build_query($endpointParams);
+        return $oidcSettings->endSessionEndpoint . '?' . http_build_query($endpointParams);
     }
 }
diff --git a/app/Config/oidc.php b/app/Config/oidc.php
index 5f61063f6..ed9302d10 100644
--- a/app/Config/oidc.php
+++ b/app/Config/oidc.php
@@ -36,10 +36,9 @@ return [
     'authorization_endpoint' => env('OIDC_AUTH_ENDPOINT', null),
     'token_endpoint'         => env('OIDC_TOKEN_ENDPOINT', null),
 
-    // OIDC RP-Initiated Logout endpoint
+    // OIDC RP-Initiated Logout endpoint URL.
     // A null value gets the URL from discovery, if active.
     // A false value force-disables RP-Initiated Logout.
-    // A string value forces the given URL to be used.
     'end_session_endpoint' => env('OIDC_END_SESSION_ENDPOINT', null),
 
     // Add extra scopes, upon those required, to the OIDC authentication request
diff --git a/tests/Auth/OidcTest.php b/tests/Auth/OidcTest.php
index 204a3bb5f..d10582d8c 100644
--- a/tests/Auth/OidcTest.php
+++ b/tests/Auth/OidcTest.php
@@ -44,6 +44,7 @@ class OidcTest extends TestCase
             'oidc.groups_claim'           => 'group',
             'oidc.remove_from_groups'     => false,
             'oidc.external_id_claim'      => 'sub',
+            'oidc.end_session_endpoint'   => null,
         ]);
     }
 
@@ -478,6 +479,81 @@ class OidcTest extends TestCase
         $this->assertTrue($user->hasRole($roleA->id));
     }
 
+    public function test_oidc_logout_form_active_when_oidc_active()
+    {
+        $this->runLogin();
+
+        $resp = $this->get('/');
+        $this->withHtml($resp)->assertElementExists('header form[action$="/oidc/logout"] button');
+    }
+    public function test_logout_with_autodiscovery()
+    {
+        $this->withAutodiscovery();
+
+        $transactions = $this->mockHttpClient([
+            $this->getAutoDiscoveryResponse(),
+            $this->getJwksResponse(),
+        ]);
+
+        $resp = $this->asEditor()->post('/oidc/logout');
+        $resp->assertRedirect('https://auth.example.com/oidc/logout?post_logout_redirect_uri=' . urlencode(url('/')));
+
+        $this->assertEquals(2, $transactions->requestCount());
+    }
+
+    public function test_logout_with_autodiscovery_but_oidc_logout_disabled()
+    {
+        $this->withAutodiscovery();
+        config()->set(['oidc.end_session_endpoint' => false]);
+
+        $this->mockHttpClient([
+            $this->getAutoDiscoveryResponse(),
+            $this->getJwksResponse(),
+        ]);
+
+        $resp = $this->asEditor()->post('/oidc/logout');
+        $resp->assertRedirect('/');
+    }
+
+    public function test_logout_without_autodiscovery_but_with_endpoint_configured()
+    {
+        config()->set(['oidc.end_session_endpoint' => 'https://example.com/logout']);
+
+        $resp = $this->asEditor()->post('/oidc/logout');
+        $resp->assertRedirect('https://example.com/logout?post_logout_redirect_uri=' . urlencode(url('/')));
+    }
+
+    public function test_logout_with_autodiscovery_and_auto_initiate_returns_to_auto_prevented_login()
+    {
+        $this->withAutodiscovery();
+        config()->set([
+            'auth.auto_initiate' => true,
+            'services.google.client_id' => false,
+            'services.github.client_id' => false,
+        ]);
+
+        $this->mockHttpClient([
+            $this->getAutoDiscoveryResponse(),
+            $this->getJwksResponse(),
+        ]);
+
+        $resp = $this->asEditor()->post('/oidc/logout');
+
+        $redirectUrl = url('/login?prevent_auto_init=true');
+        $resp->assertRedirect('https://auth.example.com/oidc/logout?post_logout_redirect_uri=' . urlencode($redirectUrl));
+    }
+
+    public function test_logout_redirect_contains_id_token_hint_if_existing()
+    {
+        config()->set(['oidc.end_session_endpoint' => 'https://example.com/logout']);
+
+        $this->runLogin();
+
+        $resp = $this->asEditor()->post('/oidc/logout');
+        $query = 'id_token_hint=' . urlencode(OidcJwtHelper::idToken()) .  '&post_logout_redirect_uri=' . urlencode(url('/'));
+        $resp->assertRedirect('https://example.com/logout?' . $query);
+    }
+
     public function test_oidc_id_token_pre_validate_theme_event_without_return()
     {
         $args = [];
@@ -563,6 +639,7 @@ class OidcTest extends TestCase
             'authorization_endpoint' => OidcJwtHelper::defaultIssuer() . '/oidc/authorize',
             'jwks_uri'               => OidcJwtHelper::defaultIssuer() . '/oidc/keys',
             'issuer'                 => OidcJwtHelper::defaultIssuer(),
+            'end_session_endpoint'   => OidcJwtHelper::defaultIssuer() . '/oidc/logout',
         ], $responseOverrides)));
     }