aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Alexandre Alapetite <alexandre@alapetite.fr> 2014-08-13 00:09:48 +0200
committerGravatar Alexandre Alapetite <alexandre@alapetite.fr> 2014-08-13 00:09:48 +0200
commitee1b8f6f72e8c2cbd3e0ad7b4322a4bb6863c028 (patch)
tree464ff98e55a41955ac6a18e7cdcfc31698247eba
parent775ff40780935471dcd74b0d81c04b80e3e4603c (diff)
Long term cookie to keep session open
Token system https://github.com/marienfressinaud/FreshRSS/issues/465
-rwxr-xr-xapp/Controllers/indexController.php41
-rw-r--r--app/FreshRSS.php28
-rw-r--r--data/tokens/.gitignore1
-rw-r--r--data/tokens/index.html13
-rw-r--r--lib/Minz/Session.php19
5 files changed, 86 insertions, 16 deletions
diff --git a/app/Controllers/indexController.php b/app/Controllers/indexController.php
index b907c8eed..dd5b91e47 100755
--- a/app/Controllers/indexController.php
+++ b/app/Controllers/indexController.php
@@ -295,10 +295,39 @@ class FreshRSS_index_Controller extends Minz_ActionController {
Minz_Session::_param('passwordHash');
}
+ private static function makeLongTermCookie($username, $passwordHash) {
+ do {
+ $token = sha1(Minz_Configuration::salt() . $username . uniqid(mt_rand(), true));
+ $tokenFile = DATA_PATH . '/tokens/' . $token . '.txt';
+ } while (file_exists($tokenFile));
+ if (@file_put_contents($tokenFile, $username . "\t" . $passwordHash) === false) {
+ return false;
+ }
+ $expire = time() + 2629744; //1 month //TODO: Use a configuration instead
+ Minz_Session::setLongTermCookie('FreshRSS_login', $token, $expire);
+ Minz_Session::_param('token', $token);
+ return $token;
+ }
+
+ private static function deleteLongTermCookie() {
+ Minz_Session::deleteLongTermCookie('FreshRSS_login');
+ $token = Minz_Session::param('token', null);
+ if (ctype_alnum($token)) {
+ @unlink(DATA_PATH . '/tokens/' . $token . '.txt');
+ }
+ Minz_Session::_param('token');
+ if (rand(0, 10) === 1) {
+ self::purgeTokens();
+ }
+ }
+
+ private static function purgeTokens() {
+ //TODO: Delete old token files
+ }
+
public function formLoginAction () {
if (Minz_Request::isPost()) {
$ok = false;
- $keep_logged_in = Minz_Request::param('keep_logged_in', false);
$nonce = Minz_Session::param('nonce');
$username = Minz_Request::param('username', '');
$c = Minz_Request::param('challenge', '');
@@ -313,10 +342,8 @@ class FreshRSS_index_Controller extends Minz_ActionController {
if ($ok) {
Minz_Session::_param('currentUser', $username);
Minz_Session::_param('passwordHash', $s);
- if ($keep_logged_in) {
- // New cookie with a lifetime of 1 month.
- Minz_Session::keepCookie(2592000);
- Minz_Session::regenerateID();
+ if (Minz_Request::param('keep_logged_in', false)) {
+ self::makeLongTermCookie($username, $s);
}
} else {
Minz_Log::record('Password mismatch for user ' . $username . ', nonce=' . $nonce . ', c=' . $c, Minz_Log::WARNING);
@@ -377,9 +404,7 @@ class FreshRSS_index_Controller extends Minz_ActionController {
Minz_Session::_param('currentUser');
Minz_Session::_param('mail');
Minz_Session::_param('passwordHash');
- Minz_Session::keepCookie(0);
- Minz_Session::regenerateID();
-
+ self::deleteLongTermCookie();
Minz_Request::forward(array('c' => 'index', 'a' => 'index'), true);
}
}
diff --git a/app/FreshRSS.php b/app/FreshRSS.php
index 7c333b090..30f711e20 100644
--- a/app/FreshRSS.php
+++ b/app/FreshRSS.php
@@ -20,13 +20,35 @@ class FreshRSS extends Minz_FrontController {
$this->loadNotifications();
}
+ private static function getCredentialsFromLongTermCookie() {
+ $token = Minz_Session::getLongTermCookie('FreshRSS_login');
+ if (!ctype_alnum($token)) {
+ return array();
+ }
+ $tokenFile = DATA_PATH . '/tokens/' . $token . '.txt';
+ $mtime = @filemtime($tokenFile);
+ if ($mtime + 2629744 < time()) { //1 month //TODO: Use a configuration instead
+ @unlink($tokenFile);
+ return array(); //Expired or token does not exist
+ }
+ $credentials = @file_get_contents($tokenFile);
+ return $credentials === false ? array() : explode("\t", $credentials, 2);
+ }
+
private function accessControl($currentUser) {
if ($currentUser == '') {
switch (Minz_Configuration::authType()) {
case 'form':
- $currentUser = Minz_Configuration::defaultUser();
- Minz_Session::_param('passwordHash');
- $loginOk = false;
+ $credentials = self::getCredentialsFromLongTermCookie();
+ if (isset($credentials[1])) {
+ $currentUser = trim($credentials[0]);
+ Minz_Session::_param('passwordHash', trim($credentials[1]));
+ }
+ $loginOk = $currentUser != '';
+ if (!$loginOk) {
+ $currentUser = Minz_Configuration::defaultUser();
+ Minz_Session::_param('passwordHash');
+ }
break;
case 'http_auth':
$currentUser = httpAuthUser();
diff --git a/data/tokens/.gitignore b/data/tokens/.gitignore
new file mode 100644
index 000000000..2211df63d
--- /dev/null
+++ b/data/tokens/.gitignore
@@ -0,0 +1 @@
+*.txt
diff --git a/data/tokens/index.html b/data/tokens/index.html
new file mode 100644
index 000000000..85faaa37e
--- /dev/null
+++ b/data/tokens/index.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-GB" lang="en-GB">
+<head>
+<meta charset="UTF-8" />
+<meta http-equiv="Refresh" content="0; url=/" />
+<title>Redirection</title>
+<meta name="robots" content="noindex" />
+</head>
+
+<body>
+<p><a href="/">Redirection</a></p>
+</body>
+</html>
diff --git a/lib/Minz/Session.php b/lib/Minz/Session.php
index 906acc03c..af4de75bb 100644
--- a/lib/Minz/Session.php
+++ b/lib/Minz/Session.php
@@ -65,11 +65,8 @@ class Minz_Session {
* @param $l la durée de vie
*/
public static function keepCookie($l) {
- $cookie_dir = dirname(
- empty($_SERVER['REQUEST_URI']) ? '' : $_SERVER['REQUEST_URI']
- ) . '/';
- session_set_cookie_params($l, $cookie_dir, $_SERVER['HTTP_HOST'],
- false, true);
+ $cookie_dir = empty($_SERVER['REQUEST_URI']) ? '' : $_SERVER['REQUEST_URI'];
+ session_set_cookie_params($l, $cookie_dir, '', false, true);
}
@@ -81,4 +78,16 @@ class Minz_Session {
session_regenerate_id(true);
}
+ public static function deleteLongTermCookie($name) {
+ setcookie($name, '', 1, '', '', false, true);
+ }
+
+ public static function setLongTermCookie($name, $value, $expire) {
+ setcookie($name, $value, $expire, '', '', false, true);
+ }
+
+ public static function getLongTermCookie($name) {
+ return isset($_COOKIE[$name]) ? $_COOKIE[$name] : null;
+ }
+
}