clean up tryRememberLogin and save the timestamp of users last login

This commit is contained in:
Arthur Schiwon 2014-05-21 18:03:37 +02:00
parent 40fc1d5b4b
commit 2c89962919
5 changed files with 85 additions and 15 deletions

View File

@ -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;
}

View File

@ -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).

View File

@ -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();
});
}
/**

View File

@ -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
*/

View File

@ -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
*