diff --git a/action.php b/action.php
index 3e0fa36..db55df8 100644
--- a/action.php
+++ b/action.php
@@ -76,6 +76,8 @@ function handle_login_form (&$event, $param) {
$href = $form->addTagOpen('a');
$href->attr('href', $this->_selfdo('caslogin'));
$form->addHTML($caslogo);
+ // Add remember me checkbox using addCheckbox
+ $form->addCheckbox('remember', $lang['remember_me']);
$form->addHTML($lang['btn_login']);
$form->addTagClose('a');
$form->addFieldsetClose();
@@ -91,8 +93,9 @@ function handle_login_form (&$event, $param) {
$event->data->_content = array(); // remove the login form
$event->data->insertElement(0,'
'.$this->getConf('name').' ');
- $event->data->insertElement(1,''.$caslogo.'
'.$lang['btn_login'].'
');
- $event->data->insertElement(2,' ');
+ $event->data>insertElement(1, form_makeCheckboxField('remember', '1', $lang['remember_me'], 'remember', 'remember__me'));
+ $event->data->insertElement(2,''.$caslogo.'
'.$lang['btn_login'].'
');
+ $event->data->insertElement(3,'');
//instead of removing, one could implement a local login here...
// if ($this->getConf('jshidelocal')) {
@@ -102,14 +105,11 @@ function handle_login_form (&$event, $param) {
// $event->data->replaceElement(3,''.$this->getConf('localname').' ');
// }
- $insertElement = 3;
if ($auth && $auth->canDo('modPass') && actionOK('resendpwd')) {
- $event->data->insertElement($insertElement,''.$lang['pwdforget'].': '.$lang['btn_resendpwd'].'
');
+ $event->data->insertElement(4,''.$lang['pwdforget'].': '.$lang['btn_resendpwd'].'
');
}
}
-
}
-
}
function handle_caslogin () {
diff --git a/auth.php b/auth.php
index 084c912..46818af 100644
--- a/auth.php
+++ b/auth.php
@@ -40,6 +40,9 @@ class auth_plugin_authplaincas extends DokuWiki_Auth_Plugin {
var $casuserfile = null;
var $localuserfile = NULL;
+ protected $rememberMeCookieName = 'DOKU_PLAINCAS_AUTH';
+ protected $rememberMeFileName = '/_plaincas_tokens.php';
+
/**
* Constructor
*
@@ -106,7 +109,7 @@ public function __construct() {
$this->cando['logout'] = true;
$this->cando['logoff'] = true;
- // The default options which need to be set in the settins file.
+ // The default options which need to be set in the settings file.
$defaults = array(
// 'server' => 'galaxy.esn.org',
// 'rootcas' => '/cas',
@@ -269,6 +272,24 @@ public function logOff() {
session_destroy();
unset($_SESSION['phpCAS']);
}
+
+ // Clear RememberMe data
+ setcookie($this->rememberMeCookieName, '', time() - 3600, DOKU_BASE);
+ $this->clearPersistentToken($_SERVER['REMOTE_USER']);
+ }
+
+ protected function clearPersistentToken($user) {
+ global $conf;
+ $tokenFile = $conf['metadir'].$this->rememberMeFileName;
+
+ if (file_exists($tokenFile)) {
+ $tokens = include($tokenFile);
+ if (isset($tokens[$user])) {
+ unset($tokens[$user]);
+ $content = "_getOption('autologin') && phpCAS::checkAuthentication() )) {
+ $remoteUser = $this->checkRememberedLogin();
+ if ($remoteUser == null) { // RememberMe cookie not available
+ if (phpCAS::isAuthenticated() || ( $this->_getOption('autologin') && phpCAS::checkAuthentication() )) {
+ $remoteUser = phpCAS::getUser(); // User logged in
+ } else {
+ return false; // Not logged in
+ }
+ $this->setAuthCookie($remoteUser);
+
+ }
+
+ $this->_userInfo = $this->getUserData($remoteUser);
+ // msg(print_r($this->_userInfo,true) . __LINE__);
+
+ // Create the user if he doesn't exist
+ if ($this->_userInfo === false) {
+ $attributes = plaincas_user_attributes(phpCAS::getAttributes());
+ $this->_userInfo = array(
+ 'uid' => $remoteUser,
+ 'name' => $attributes['name'],
+ 'mail' => $attributes['mail']
+ );
+
+ $this->_assembleGroups($remoteUser);
+ $this->_saveUserGroup();
+ $this->_saveUserInfo();
- $remoteUser = phpCAS::getUser();
- $this->_userInfo = $this->getUserData($remoteUser);
// msg(print_r($this->_userInfo,true) . __LINE__);
- // Create the user if he doesn't exist
- if ($this->_userInfo === false) {
- $attributes = plaincas_user_attributes(phpCAS::getAttributes());
+ $USERINFO = $this->_userInfo;
+ $_SESSION[DOKU_COOKIE]['auth']['user'] = $USERINFO['uid'];
+ $_SESSION[DOKU_COOKIE]['auth']['info'] = $USERINFO;
+ $_SERVER['REMOTE_USER'] = $USERINFO['uid'];
+ } else { // User exists, check for updates
+ $this->_userInfo['uid'] = $remoteUser;
+ $this->_assembleGroups($remoteUser);
+
+ $attributes = plaincas_user_attributes(phpCAS::getAttributes());
+
+ if ($this->_userInfo['grps'] != $this->_userInfo['tmp_grps'] ||
+ $attributes['name'] !== $this->_userInfo['name'] ||
+ $attributes['mail'] !== $this->_userInfo['mail']
+ ) {
+ //msg("new roles, email, or name");
+ $this->deleteUsers(array($remoteUser));
$this->_userInfo = array(
'uid' => $remoteUser,
'name' => $attributes['name'],
'mail' => $attributes['mail']
);
-
$this->_assembleGroups($remoteUser);
$this->_saveUserGroup();
$this->_saveUserInfo();
+ }
- // msg(print_r($this->_userInfo,true) . __LINE__);
-
- $USERINFO = $this->_userInfo;
- $_SESSION[DOKU_COOKIE]['auth']['user'] = $USERINFO['uid'];
- $_SESSION[DOKU_COOKIE]['auth']['info'] = $USERINFO;
- $_SERVER['REMOTE_USER'] = $USERINFO['uid'];
- return true;
+ $USERINFO = $this->_userInfo;
+ $_SESSION[DOKU_COOKIE]['auth']['user'] = $USERINFO['uid'];
+ $_SESSION[DOKU_COOKIE]['auth']['info'] = $USERINFO;
+ $_SERVER['REMOTE_USER'] = $USERINFO['uid'];
+ }
- // User exists, check for updates
- } else {
- $this->_userInfo['uid'] = $remoteUser;
- $this->_assembleGroups($remoteUser);
+ return true;
+ }
- $attributes = plaincas_user_attributes(phpCAS::getAttributes());
-
- if ($this->_userInfo['grps'] != $this->_userInfo['tmp_grps'] ||
- $attributes['name'] !== $this->_userInfo['name'] ||
- $attributes['mail'] !== $this->_userInfo['mail']
- ) {
- //msg("new roles, email, or name");
- $this->deleteUsers(array($remoteUser));
- $this->_userInfo = array(
- 'uid' => $remoteUser,
- 'name' => $attributes['name'],
- 'mail' => $attributes['mail']
- );
- $this->_assembleGroups($remoteUser);
- $this->_saveUserGroup();
- $this->_saveUserInfo();
+ protected function checkRememberedLogin() {
+ if (isset($_COOKIE[$this->rememberMeCookieName])) {
+ try {
+ $data = json_decode(base64_decode($_COOKIE[$this->rememberMeCookieName]), true);
+ if ($data &&
+ isset($data['user']) &&
+ isset($data['token']) &&
+ isset($data['expires']) &&
+ $data['expires'] > time()) {
+ if ($this->verifyPersistentToken($data['user'], $data['token'])) {
+ return $data['user'];
+ }
}
+ } catch (Exception $e) {
+ msg($e->getMessage(), -1);
+ }
- $USERINFO = $this->_userInfo;
- $_SESSION[DOKU_COOKIE]['auth']['user'] = $USERINFO['uid'];
- $_SESSION[DOKU_COOKIE]['auth']['info'] = $USERINFO;
- $_SERVER['REMOTE_USER'] = $USERINFO['uid'];
+ // Clear invalid cookie
+ setcookie($this->rememberMeCookieName, '', time() - 3600, DOKU_BASE);
+ }
+ return null;
+ }
+
+ protected function verifyPersistentToken($user, $token) {
+ global $conf;
+ $tokenFile = $conf['metadir'].$this->rememberMeFileName;
+ if (file_exists($tokenFile)) {
+ $tokens = include($tokenFile);
+ if (isset($tokens[$user]) &&
+ $tokens[$user]['token'] === $token &&
+ $tokens[$user]['expires'] > time()) {
return true;
}
-
}
- // else{
- // }
return false;
}
+ protected function setAuthCookie($user) {
+ $cookie_lifetime = time() + 30 * 24 * 60 * 60; // 30 days
+
+ $token = bin2hex(random_bytes(32));
+
+ $cookie_data = base64_encode(json_encode([
+ 'user' => $user,
+ 'token' => $token,
+ 'expires' => $cookie_lifetime
+ ]));
+
+ setcookie(
+ $this->rememberMeCookieName,
+ $cookie_data,
+ [
+ 'expires' => $cookie_lifetime,
+ 'path' => DOKU_BASE,
+ 'secure' => (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off'),
+ 'httponly' => true,
+ 'samesite' => 'Strict',
+ ]
+ );
+
+ // Store token in metadata
+ $this->storePersistentToken($user, $token, $cookie_lifetime);
+ }
+
+ protected function storePersistentToken($user, $token, $cookie_lifetime) {
+ global $conf;
+ $tokenFile = $conf['metadir'].$this->rememberMeFileName;
+
+ $tokens = array();
+ if (file_exists($tokenFile)) {
+ $tokens = include($tokenFile);
+ }
+
+ $tokens[$user] = [
+ 'token' => $token,
+ 'expires' => $cookie_lifetime
+ ];
+
+ $content = "