diff --git a/core/Controller/LoginController.php b/core/Controller/LoginController.php
index fe1ad41aedb89e89a9f86e9e93c121298474efc3..e13d8ae10d2078bfc8a2df6e92cf4688f9850173 100644
--- a/core/Controller/LoginController.php
+++ b/core/Controller/LoginController.php
@@ -26,7 +26,6 @@ namespace OC\Core\Controller;
 use OC;
 use OC\User\Session;
 use OC_App;
-use OC_User;
 use OC_Util;
 use OCP\AppFramework\Controller;
 use OCP\AppFramework\Http\RedirectResponse;
diff --git a/db_structure.xml b/db_structure.xml
index 68a812a6b8f020c13553370eb646a4a5580c2a85..dcbf426e5b82ec349a21bdd5f44617ef815f2971 100644
--- a/db_structure.xml
+++ b/db_structure.xml
@@ -1057,10 +1057,10 @@
 
 			<field>
 				<name>password</name>
-				<type>text</type>
+				<type>clob</type>
 				<default></default>
 				<notnull>true</notnull>
-				<length>100</length>
+				<length>4000</length>
 			</field>
 
 			<field>
diff --git a/lib/private/Authentication/Token/DefaultToken.php b/lib/private/Authentication/Token/DefaultToken.php
index 9bdae789afd541a31e6555695677a69ca11180cd..6b859d7d063f1295652a0082a7afec734fac3346 100644
--- a/lib/private/Authentication/Token/DefaultToken.php
+++ b/lib/private/Authentication/Token/DefaultToken.php
@@ -51,13 +51,8 @@ class DefaultToken extends Entity implements IToken {
 	 */
 	protected $lastActivity;
 
-	/**
-	 * Get the token ID
-	 *
-	 * @return string
-	 */
 	public function getId() {
-		return $this->token;
+		return $this->id;
 	}
 
 }
diff --git a/lib/private/Authentication/Token/DefaultTokenMapper.php b/lib/private/Authentication/Token/DefaultTokenMapper.php
index 9a73192c0d87ada5e26f90fa4e0bfc1ec9fe46e9..d54d2489399b8e54cbc0d787cefba3d2bf9a81f1 100644
--- a/lib/private/Authentication/Token/DefaultTokenMapper.php
+++ b/lib/private/Authentication/Token/DefaultTokenMapper.php
@@ -61,10 +61,10 @@ class DefaultTokenMapper extends Mapper {
 	 *
 	 * @param string $token
 	 * @throws DoesNotExistException
-	 * @return string
+	 * @return DefaultToken
 	 */
-	public function getTokenUser($token) {
-		$sql = 'SELECT `uid` '
+	public function getToken($token) {
+		$sql = 'SELECT `id`, `uid`, `password`, `name`, `token`, `last_activity` '
 			. 'FROM `' . $this->getTableName() . '` '
 			. 'WHERE `token` = ?';
 		return $this->findEntity($sql, [
diff --git a/lib/private/Authentication/Token/DefaultTokenProvider.php b/lib/private/Authentication/Token/DefaultTokenProvider.php
index 71f798da3700a8f7988681e672213d4e74bfc741..b3564e0e81b8fd8bf820470beac24f568fa9780d 100644
--- a/lib/private/Authentication/Token/DefaultTokenProvider.php
+++ b/lib/private/Authentication/Token/DefaultTokenProvider.php
@@ -48,8 +48,7 @@ class DefaultTokenProvider implements IProvider {
 	 * @param IConfig $config
 	 * @param ILogger $logger
 	 */
-	public function __construct(DefaultTokenMapper $mapper, ICrypto $crypto,
-		IConfig $config, ILogger $logger) {
+	public function __construct(DefaultTokenMapper $mapper, ICrypto $crypto, IConfig $config, ILogger $logger) {
 		$this->mapper = $mapper;
 		$this->crypto = $crypto;
 		$this->config = $config;
@@ -67,8 +66,7 @@ class DefaultTokenProvider implements IProvider {
 	public function generateToken($token, $uid, $password, $name) {
 		$dbToken = new DefaultToken();
 		$dbToken->setUid($uid);
-		$secret = $this->config->getSystemValue('secret');
-		$dbToken->setPassword($this->crypto->encrypt($password . $secret));
+		$dbToken->setPassword($this->encryptPassword($password, $token));
 		$dbToken->setName($name);
 		$dbToken->setToken($this->hashToken($token));
 		$dbToken->setLastActivity(time());
@@ -78,6 +76,37 @@ class DefaultTokenProvider implements IProvider {
 		return $dbToken;
 	}
 
+	/**
+	 * Update token activity timestamp
+	 *
+	 * @param DefaultToken $token
+	 */
+	public function updateToken(DefaultToken $token) {
+		$token->setLastActivity(time());
+
+		$this->mapper->update($token);
+	}
+
+	/**
+	 * @param string $token
+	 * @throws InvalidTokenException
+	 */
+	public function getToken($token) {
+		try {
+			return $this->mapper->getToken($this->hashToken($token));
+		} catch (DoesNotExistException $ex) {
+			throw new InvalidTokenException();
+		}
+	}
+
+	/**
+	 * @param DefaultToken $savedToken
+	 * @param string $token session token
+	 */
+	public function getPassword(DefaultToken $savedToken, $token) {
+		return $this->decryptPassword($savedToken->getPassword(), $token);
+	}
+
 	/**
 	 * Invalidate (delete) the given session token
 	 *
@@ -104,7 +133,7 @@ class DefaultTokenProvider implements IProvider {
 	public function validateToken($token) {
 		$this->logger->debug('validating default token <' . $token . '>');
 		try {
-			$dbToken = $this->mapper->getTokenUser($this->hashToken($token));
+			$dbToken = $this->mapper->getToken($this->hashToken($token));
 			$this->logger->debug('valid token for ' . $dbToken->getUid());
 			return $dbToken->getUid();
 		} catch (DoesNotExistException $ex) {
@@ -121,4 +150,32 @@ class DefaultTokenProvider implements IProvider {
 		return hash('sha512', $token);
 	}
 
+	/**
+	 * Encrypt the given password
+	 *
+	 * The token is used as key
+	 *
+	 * @param string $password
+	 * @param string $token
+	 * @return string encrypted password
+	 */
+	private function encryptPassword($password, $token) {
+		$secret = $this->config->getSystemValue('secret');
+		return $this->crypto->encrypt($password, $token . $secret);
+	}
+
+	/**
+	 * Decrypt the given password
+	 *
+	 * The token is used as key
+	 *
+	 * @param string $password
+	 * @param string $token
+	 * @return string the decrypted key
+	 */
+	private function decryptPassword($password, $token) {
+		$secret = $this->config->getSystemValue('secret');
+		return $this->crypto->decrypt($password, $token . $secret);
+	}
+
 }
diff --git a/lib/private/User/Session.php b/lib/private/User/Session.php
index 9db503e6add8cd41b44157b9484599fce6d3560c..7d4594e7205be051f202e6657028fdc9b4223c52 100644
--- a/lib/private/User/Session.php
+++ b/lib/private/User/Session.php
@@ -96,8 +96,7 @@ class Session implements IUserSession, Emitter {
 	 * @param ISession $session
 	 * @param IProvider[] $tokenProviders
 	 */
-	public function __construct(IUserManager $manager, ISession $session,
-		DefaultTokenProvider $tokenProvider, array $tokenProviders = []) {
+	public function __construct(IUserManager $manager, ISession $session, DefaultTokenProvider $tokenProvider, array $tokenProviders = []) {
 		$this->manager = $manager;
 		$this->session = $session;
 		$this->tokenProvider = $tokenProvider;
@@ -118,8 +117,7 @@ class Session implements IUserSession, Emitter {
 	 * @param string $method optional
 	 * @param callable $callback optional
 	 */
-	public function removeListener($scope = null, $method = null,
-		callable $callback = null) {
+	public function removeListener($scope = null, $method = null, callable $callback = null) {
 		$this->manager->removeListener($scope, $method, $callback);
 	}
 
@@ -183,8 +181,7 @@ class Session implements IUserSession, Emitter {
 			return $this->activeUser;
 		} else {
 			$uid = $this->session->get('user_id');
-			if ($uid !== null) {
-				$this->activeUser = $this->manager->get($uid);
+			if ($uid !== null && $this->isValidSession($uid)) {
 				return $this->activeUser;
 			} else {
 				return null;
@@ -192,6 +189,41 @@ class Session implements IUserSession, Emitter {
 		}
 	}
 
+	private function isValidSession($uid) {
+		$this->activeUser = $this->manager->get($uid);
+		if (is_null($this->activeUser)) {
+			// User does not exist
+			return false;
+		}
+		// TODO: use ISession::getId(), https://github.com/owncloud/core/pull/24229
+		$sessionId = session_id();
+		try {
+			$token = $this->tokenProvider->getToken($sessionId);
+		} catch (InvalidTokenException $ex) {
+			// Session was inalidated
+			$this->logout();
+			return false;
+		}
+
+		// Check whether login credentials are still valid
+		// This check is performed each 5 minutes
+		$lastCheck = $this->session->get('last_login_check') ? : 0;
+		if ($lastCheck < (time() - 60 * 5)) {
+			$pwd = $this->tokenProvider->getPassword($token, $sessionId);
+			if ($this->manager->checkPassword($uid, $pwd) === false) {
+				// Password has changed -> log user out
+				$this->logout();
+				return false;
+			}
+			$this->session->set('last_login_check', time());
+		}
+
+		// Session is valid, so the token can be refreshed
+		$this->tokenProvider->updateToken($token);
+
+		return true;
+	}
+
 	/**
 	 * Checks whether the user is logged in
 	 *
@@ -334,7 +366,6 @@ class Session implements IUserSession, Emitter {
 	 * @return boolean
 	 */
 	private function validateToken(IRequest $request, $token) {
-		// TODO: hash token
 		foreach ($this->tokenProviders as $provider) {
 			try {
 				$user = $provider->validateToken($token);
diff --git a/lib/private/legacy/user.php b/lib/private/legacy/user.php
index 575011d39856469e061341efae6c0cd410703c67..ca408d347bd059b9d89cd9bd3f5a1a93ff83ef4b 100644
--- a/lib/private/legacy/user.php
+++ b/lib/private/legacy/user.php
@@ -68,7 +68,7 @@ class OC_User {
 
 	private static $_setupedBackends = array();
 
-	// bool, stores if a user want to access a resource anonymously, e.g if he opens a public link
+	// bool, stores if a user want to access a resource anonymously, e.g if they open a public link
 	private static $incognitoMode = false;
 
 	/**