From 2c89962919fe45bf5a577ad94f3cc0d9bc84ba35 Mon Sep 17 00:00:00 2001 From: Arthur Schiwon Date: Wed, 21 May 2014 18:03:37 +0200 Subject: [PATCH] clean up tryRememberLogin and save the timestamp of users last login --- lib/base.php | 24 +++++++++--------------- lib/private/user.php | 11 +++++++++++ lib/private/user/manager.php | 6 ++++++ lib/private/user/session.php | 32 ++++++++++++++++++++++++++++++++ lib/private/user/user.php | 27 +++++++++++++++++++++++++++ 5 files changed, 85 insertions(+), 15 deletions(-) diff --git a/lib/base.php b/lib/base.php index abb76b94a5..9441749f1d 100644 --- a/lib/base.php +++ b/lib/base.php @@ -883,30 +883,24 @@ class OC { if (defined("DEBUG") && DEBUG) { OC_Log::write('core', 'Trying to login from cookie', OC_Log::DEBUG); } - // confirm credentials in cookie - if (isset($_COOKIE['oc_token']) && OC_User::userExists($_COOKIE['oc_username'])) { - // delete outdated cookies + + if(OC_User::userExists($_COOKIE['oc_username'])) { self::cleanupLoginTokens($_COOKIE['oc_username']); - // get stored tokens - $tokens = OC_Preferences::getKeys($_COOKIE['oc_username'], 'login_token'); - // test cookies token against stored tokens - if (in_array($_COOKIE['oc_token'], $tokens, true)) { - // replace successfully used token with a new one - OC_Preferences::deleteKey($_COOKIE['oc_username'], 'login_token', $_COOKIE['oc_token']); - $token = OC_Util::generateRandomBytes(32); - OC_Preferences::setValue($_COOKIE['oc_username'], 'login_token', $token, time()); - OC_User::setMagicInCookie($_COOKIE['oc_username'], $token); - // login - OC_User::setUserId($_COOKIE['oc_username']); + // confirm credentials in cookie + $granted = OC_User::loginWithCookie( + $_COOKIE['oc_username'], $_COOKIE['oc_token']); + if($granted === true) { OC_Util::redirectToDefaultPage(); // doesn't return } + OC_Log::write('core', 'Authentication cookie rejected for user ' . + $_COOKIE['oc_username'], OC_Log::WARN); // if you reach this point you have changed your password // or you are an attacker // we can not delete tokens here because users may reach // this point multiple times after a password change - OC_Log::write('core', 'Authentication cookie rejected for user ' . $_COOKIE['oc_username'], OC_Log::WARN); } + OC_User::unsetMagicInCookie(); return true; } diff --git a/lib/private/user.php b/lib/private/user.php index 9276d7923c..5d3ebb57c8 100644 --- a/lib/private/user.php +++ b/lib/private/user.php @@ -235,6 +235,17 @@ class OC_User { return self::getUserSession()->login($uid, $password); } + /** + * Try to login a user using the magic cookie (remember login) + * + * @param string $uid The username of the user to log in + * @param string $token + * @return bool + */ + public static function loginWithCookie($uid, $token) { + return self::getUserSession()->loginWithCookie($uid, $token); + } + /** * Try to login a user, assuming authentication * has already happened (e.g. via Single Sign On). diff --git a/lib/private/user/manager.php b/lib/private/user/manager.php index 0fcf1ceb6a..914baebdf6 100644 --- a/lib/private/user/manager.php +++ b/lib/private/user/manager.php @@ -52,6 +52,12 @@ class Manager extends PublicEmitter { unset($cachedUsers[$i]); } }); + $this->listen('\OC\User', 'postLogin', function ($user, $pw) { + $user->updateLastLoginTimestamp(); + }); + $this->listen('\OC\User', 'postRememberedLogin', function ($user) { + $user->updateLastLoginTimestamp(); + }); } /** diff --git a/lib/private/user/session.php b/lib/private/user/session.php index 3d10b134b8..91e203f044 100644 --- a/lib/private/user/session.php +++ b/lib/private/user/session.php @@ -170,6 +170,38 @@ class Session implements Emitter, \OCP\IUserSession { } } + /** + * perform login using the magic cookie (remember login) + * + * @param string $uid the username + * @param string $currentToken + * @return bool + */ + public function loginWithCookie($uid, $currentToken) { + $user = $this->manager->get($uid); + if(is_null($user)) { + // user does not exist + return false; + } + + // get stored tokens + $tokens = \OC_Preferences::getKeys($uid, 'login_token'); + // test cookies token against stored tokens + if(!in_array($currentToken, $tokens, true)) { + return false; + } + // replace successfully used token with a new one + \OC_Preferences::deleteKey($uid, 'login_token', $currentToken); + $newToken = \OC_Util::generateRandomBytes(32); + \OC_Preferences::setValue($uid, 'login_token', $newToken, time()); + $this->setMagicInCookie($user->getUID(), $newToken); + + //login + $this->setUser($user); + $this->manager->emit('\OC\User', 'postRememberedLogin', array($user)); + return true; + } + /** * logout the user from the session */ diff --git a/lib/private/user/user.php b/lib/private/user/user.php index bc5c541e52..e059881364 100644 --- a/lib/private/user/user.php +++ b/lib/private/user/user.php @@ -42,6 +42,11 @@ class User { */ private $home; + /** + * @var int $lastLogin + */ + private $lastLogin; + /** * @var \OC\AllConfig $config */ @@ -64,6 +69,7 @@ class User { } else { $this->enabled = true; } + $this->lastLogin = \OC_Preferences::getValue($uid, 'login', 'lastLogin', 0); } /** @@ -107,6 +113,27 @@ class User { } } + /** + * returns the timestamp of the user's last login or 0 if the user did never + * login + * + * @return int + */ + public function getLastLogin() { + return $this->lastLogin; + } + + /** + * updates the timestamp of the most recent login of this user + * + * @return null + */ + public function updateLastLoginTimestamp() { + $this->lastLogin = time(); + \OC_Preferences::setValue( + $this->uid, 'login', 'lastLogin', $this->lastLogin); + } + /** * Delete the user *