diff --git a/core/Application.php b/core/Application.php
index 805208d469690c7a6af2dc68f66fe59e9121d502..0a54386a2ce7d781b89515af1ae892a9ec57cfbf 100644
--- a/core/Application.php
+++ b/core/Application.php
@@ -97,7 +97,8 @@ class Application extends App {
 				$c->query('UserManager'),
 				$c->query('Config'),
 				$c->query('Session'),
-				$c->query('UserSession')
+				$c->query('UserSession'),
+				$c->query('URLGenerator')
 			);
 		});
 
diff --git a/core/Controller/LoginController.php b/core/Controller/LoginController.php
index faed7e291eaa51efe63402df3f45b1143660879c..796706d364a25d6b53222e0d39da2db3e92d77f1 100644
--- a/core/Controller/LoginController.php
+++ b/core/Controller/LoginController.php
@@ -28,6 +28,7 @@ use OCP\AppFramework\Http\TemplateResponse;
 use OCP\IConfig;
 use OCP\IRequest;
 use OCP\ISession;
+use OCP\IURLGenerator;
 use OCP\IUser;
 use OCP\IUserManager;
 use OCP\IUserSession;
@@ -41,6 +42,8 @@ class LoginController extends Controller {
 	private $session;
 	/** @var IUserSession */
 	private $userSession;
+	/** @var IURLGenerator */
+	private $urlGenerator;
 
 	/**
 	 * @param string $appName
@@ -49,18 +52,37 @@ class LoginController extends Controller {
 	 * @param IConfig $config
 	 * @param ISession $session
 	 * @param IUserSession $userSession
+	 * @param IURLGenerator $urlGenerator
 	 */
 	function __construct($appName,
 						 IRequest $request,
 						 IUserManager $userManager,
 						 IConfig $config,
 						 ISession $session,
-						 IUserSession $userSession) {
+						 IUserSession $userSession,
+						 IURLGenerator $urlGenerator) {
 		parent::__construct($appName, $request);
 		$this->userManager = $userManager;
 		$this->config = $config;
 		$this->session = $session;
 		$this->userSession = $userSession;
+		$this->urlGenerator = $urlGenerator;
+	}
+
+	/**
+	 * @NoAdminRequired
+	 * @UseSession
+	 *
+	 * @return RedirectResponse
+	 */
+	public function logout() {
+		$loginToken = $this->request->getCookie('oc_token');
+		if (!is_null($loginToken)) {
+			$this->config->deleteUserValue($this->userSession->getUser()->getUID(), 'login_token', $loginToken);
+		}
+		$this->userSession->logout();
+
+		return new RedirectResponse($this->urlGenerator->linkToRouteAbsolute('core.login.showLoginForm'));
 	}
 
 	/**
diff --git a/core/routes.php b/core/routes.php
index bcad9d0dad35473cae560721bf64ea1637281213..2b7a19f7d86724fecbbe848d0a00deda2e29d47b 100644
--- a/core/routes.php
+++ b/core/routes.php
@@ -43,6 +43,7 @@ $application->registerRoutes($this, [
 		['name' => 'avatar#getTmpAvatar', 'url' => '/avatar/tmp', 'verb' => 'GET'],
 		['name' => 'avatar#postAvatar', 'url' => '/avatar/', 'verb' => 'POST'],
 		['name' => 'login#showLoginForm', 'url' => '/login', 'verb' => 'GET'],
+		['name' => 'login#logout', 'url' => '/logout', 'verb' => 'GET'],
 	]
 ]);
 
diff --git a/lib/base.php b/lib/base.php
index 27967588360ba203af27a1d91afb1ffda40e21dd..6bc0fecf04dc6d2e81b9573927e64310aaef525f 100644
--- a/lib/base.php
+++ b/lib/base.php
@@ -858,7 +858,7 @@ class OC {
 			}
 		}
 
-		if (!self::$CLI and (!isset($_GET["logout"]) or ($_GET["logout"] !== 'true'))) {
+		if (!self::$CLI) {
 			try {
 				if (!$systemConfig->getValue('maintenance', false) && !self::checkUpgrade(false)) {
 					OC_App::loadApps(array('filesystem', 'logging'));
@@ -897,31 +897,13 @@ class OC {
 			return;
 		}
 
-		// Redirect to index if the logout link is accessed without valid session
-		// this is needed to prevent "Token expired" messages while login if a session is expired
-		// @see https://github.com/owncloud/core/pull/8443#issuecomment-42425583
-		if(isset($_GET['logout']) && !OC_User::isLoggedIn()) {
-			header("Location: " . \OC::$server->getURLGenerator()->getAbsoluteURL('/'));
-			return;
-		}
-
 		// Someone is logged in
 		if (OC_User::isLoggedIn()) {
 			OC_App::loadApps();
 			OC_User::setupBackends();
 			OC_Util::setupFS();
-			if (isset($_GET["logout"]) and ($_GET["logout"])) {
-				OC_JSON::callCheck();
-				if (isset($_COOKIE['oc_token'])) {
-					\OC::$server->getConfig()->deleteUserValue(OC_User::getUser(), 'login_token', $_COOKIE['oc_token']);
-				}
-				OC_User::logout();
-				// redirect to webroot and add slash if webroot is empty
-				header("Location: " . \OC::$server->getURLGenerator()->getAbsoluteURL('/'));
-			} else {
-				// Redirect to default application
-				OC_Util::redirectToDefaultPage();
-			}
+			// Redirect to default application
+			OC_Util::redirectToDefaultPage();
 		} else {
 			// Not handled and not logged in
 			self::handleLogin();
diff --git a/lib/private/api.php b/lib/private/api.php
index 12a78f1424b330fe4fa495ad6ce9204e9013314e..bab879c95f8f469c598804351c3046159f8e54cf 100644
--- a/lib/private/api.php
+++ b/lib/private/api.php
@@ -179,7 +179,7 @@ class OC_API {
 		$response = self::mergeResponses($responses);
 		$format = self::requestedFormat();
 		if (self::$logoutRequired) {
-			OC_User::logout();
+			\OC::$server->getUserSession()->logout();
 		}
 
 		self::respond($response, $format);
diff --git a/lib/private/appframework/http/request.php b/lib/private/appframework/http/request.php
index c8525d1d14163c068a6d179b75886dccfd842e91..7cd8cedcfdd45e0db0c3b4368d0a1e5dfe0c6189 100644
--- a/lib/private/appframework/http/request.php
+++ b/lib/private/appframework/http/request.php
@@ -368,7 +368,7 @@ class Request implements \ArrayAccess, \Countable, IRequest {
 	/**
 	 * Shortcut for getting cookie variables
 	 * @param string $key the key that will be taken from the $_COOKIE array
-	 * @return array the value in the $_COOKIE element
+	 * @return string the value in the $_COOKIE element
 	 */
 	public function getCookie($key) {
 		return isset($this->cookies[$key]) ? $this->cookies[$key] : null;
diff --git a/lib/private/user.php b/lib/private/user.php
index 26062f503d28e053fd0e81c0b3a2df8cd8a8aeff..8767a8d5b6d468180944510b725bd3e95044cb30 100644
--- a/lib/private/user.php
+++ b/lib/private/user.php
@@ -267,15 +267,6 @@ class OC_User {
 		}
 	}
 
-	/**
-	 * Logs the current user out and kills all the session data
-	 *
-	 * Logout, destroys session
-	 */
-	public static function logout() {
-		self::getUserSession()->logout();
-	}
-
 	/**
 	 * Tries to login the user with HTTP Basic Authentication
 	 */
@@ -342,7 +333,14 @@ class OC_User {
 			return $backend->getLogoutAttribute();
 		}
 
-		return 'href="' . link_to('', 'index.php') . '?logout=true&requesttoken=' . urlencode(\OCP\Util::callRegister()) . '"';
+		$logoutUrl = \OC::$server->getURLGenerator()->linkToRouteAbsolute(
+			'core.login.logout',
+			[
+				'requesttoken' => \OCP\Util::callRegister(),
+			]
+		);
+
+		return 'href="'.$logoutUrl.'"';
 	}
 
 	/**
diff --git a/lib/public/irequest.php b/lib/public/irequest.php
index a0040aa464ddfd3746b11d5b9581c5c158331e70..296c70f4ecc6ee47228bce9942394c1ffb9c1bab 100644
--- a/lib/public/irequest.php
+++ b/lib/public/irequest.php
@@ -129,7 +129,7 @@ interface IRequest {
 	 * Shortcut for getting cookie variables
 	 *
 	 * @param string $key the key that will be taken from the $_COOKIE array
-	 * @return array the value in the $_COOKIE element
+	 * @return string the value in the $_COOKIE element
 	 * @since 6.0.0
 	 */
 	public function getCookie($key);
diff --git a/lib/public/user.php b/lib/public/user.php
index 825e77aef6d4da939ad98e0e91aa0468f456923c..64ac92d21005bd68d8b9d9ede02a27bac3d48578 100644
--- a/lib/public/user.php
+++ b/lib/public/user.php
@@ -119,7 +119,7 @@ class User {
 	 * @since 5.0.0
 	 */
 	public static function logout() {
-		\OC_User::logout();
+		\OC::$server->getUserSession()->logout();
 	}
 
 	/**
diff --git a/tests/core/controller/LoginControllerTest.php b/tests/core/controller/LoginControllerTest.php
index f0ffe57d7b42cda42456bfa7741d3950facf678e..f9a6080892bf8c55fd9a24ccacd8ad580743063b 100644
--- a/tests/core/controller/LoginControllerTest.php
+++ b/tests/core/controller/LoginControllerTest.php
@@ -26,6 +26,7 @@ use OCP\AppFramework\Http\TemplateResponse;
 use OCP\IConfig;
 use OCP\IRequest;
 use OCP\ISession;
+use OCP\IURLGenerator;
 use OCP\IUserManager;
 use OCP\IUserSession;
 use Test\TestCase;
@@ -43,6 +44,8 @@ class LoginControllerTest extends TestCase {
 	private $session;
 	/** @var IUserSession */
 	private $userSession;
+	/** @var IURLGenerator */
+	private $urlGenerator;
 
 	public function setUp() {
 		parent::setUp();
@@ -51,6 +54,7 @@ class LoginControllerTest extends TestCase {
 		$this->config = $this->getMock('\\OCP\\IConfig');
 		$this->session = $this->getMock('\\OCP\\ISession');
 		$this->userSession = $this->getMock('\\OCP\\IUserSession');
+		$this->urlGenerator = $this->getMock('\\OCP\\IURLGenerator');
 
 		$this->loginController = new LoginController(
 			'core',
@@ -58,10 +62,59 @@ class LoginControllerTest extends TestCase {
 			$this->userManager,
 			$this->config,
 			$this->session,
-			$this->userSession
+			$this->userSession,
+			$this->urlGenerator
 		);
 	}
 
+	public function testLogoutWithoutToken() {
+		$this->request
+			->expects($this->once())
+			->method('getCookie')
+			->with('oc_token')
+			->willReturn(null);
+		$this->config
+			->expects($this->never())
+			->method('deleteUserValue');
+		$this->urlGenerator
+			->expects($this->once())
+			->method('linkToRouteAbsolute')
+			->with('core.login.showLoginForm')
+			->willReturn('/login');
+
+		$expected = new RedirectResponse('/login');
+		$this->assertEquals($expected, $this->loginController->logout());
+	}
+
+	public function testLogoutWithToken() {
+		$this->request
+			->expects($this->once())
+			->method('getCookie')
+			->with('oc_token')
+			->willReturn('MyLoginToken');
+		$user = $this->getMock('\\OCP\\IUser');
+		$user
+			->expects($this->once())
+			->method('getUID')
+			->willReturn('JohnDoe');
+		$this->userSession
+			->expects($this->once())
+			->method('getUser')
+			->willReturn($user);
+		$this->config
+			->expects($this->once())
+			->method('deleteUserValue')
+			->with('JohnDoe', 'login_token', 'MyLoginToken');
+		$this->urlGenerator
+			->expects($this->once())
+			->method('linkToRouteAbsolute')
+			->with('core.login.showLoginForm')
+			->willReturn('/login');
+
+		$expected = new RedirectResponse('/login');
+		$this->assertEquals($expected, $this->loginController->logout());
+	}
+
 	public function testShowLoginFormForLoggedInUsers() {
 		$this->userSession
 			->expects($this->once())