aboutsummaryrefslogtreecommitdiff
path: root/app/Controllers
diff options
context:
space:
mode:
authorGravatar Inverle <inverle@proton.me> 2025-07-31 13:53:14 +0200
committerGravatar GitHub <noreply@github.com> 2025-07-31 13:53:14 +0200
commit3ce64d271b2b470bd6c9f7294946347dcdfed9b9 (patch)
tree56b5a0928f1ce2b0486e866abd5456bc43ea8ed9 /app/Controllers
parentd0425f8c3ab14e72142b1a4f946d57b408f26c88 (diff)
Implement sudo mode / reauthentication (#7753)
* Implement sudo mode / reauthentication * i18n: fr * generate flags * Improvements * Remove HMAC check * Don't require reauth to access logs when signed in as admin * Notify user of bad login via notification instead --------- Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>
Diffstat (limited to 'app/Controllers')
-rw-r--r--app/Controllers/authController.php33
-rw-r--r--app/Controllers/updateController.php4
-rw-r--r--app/Controllers/userController.php57
3 files changed, 87 insertions, 7 deletions
diff --git a/app/Controllers/authController.php b/app/Controllers/authController.php
index b090eb486..6b8d924d6 100644
--- a/app/Controllers/authController.php
+++ b/app/Controllers/authController.php
@@ -21,6 +21,10 @@ class FreshRSS_auth_Controller extends FreshRSS_ActionController {
Minz_Error::error(403);
}
+ if (FreshRSS_Auth::requestReauth()) {
+ return;
+ }
+
FreshRSS_View::prependTitle(_t('admin.auth.title') . ' · ');
if (Minz_Request::isPost()) {
@@ -219,6 +223,35 @@ class FreshRSS_auth_Controller extends FreshRSS_ActionController {
}
}
+ public function reauthAction(): void {
+ if (!FreshRSS_Auth::hasAccess()) {
+ Minz_Error::error(403);
+ return;
+ }
+ /** @var array{c?: string, a?: string, params?: array<string, mixed>} $redirect */
+ $redirect = Minz_Url::unserialize(Minz_Request::paramString('r'));
+ if (!FreshRSS_Auth::needsReauth()) {
+ Minz_Request::forward($redirect, true);
+ return;
+ }
+ if (Minz_Request::isPost()) {
+ $username = Minz_User::name() ?? '';
+ $nonce = Minz_Session::paramString('nonce');
+ $challenge = Minz_Request::paramString('challenge');
+ if (!FreshRSS_FormAuth::checkCredentials(
+ $username, FreshRSS_Context::userConf()->passwordHash, $nonce, $challenge
+ )) {
+ Minz_Request::setBadNotification(_t('feedback.auth.login.invalid'));
+ } else {
+ Minz_Session::_param('lastReauth', time());
+ Minz_Request::forward($redirect, true);
+ return;
+ }
+ }
+ FreshRSS_View::prependTitle(_t('gen.auth.reauth.title') . ' · ');
+ FreshRSS_View::appendScript(Minz_Url::display('/scripts/vendor/bcrypt.js?' . @filemtime(PUBLIC_PATH . '/scripts/vendor/bcrypt.js')));
+ }
+
/**
* This action removes all accesses of the current user.
*/
diff --git a/app/Controllers/updateController.php b/app/Controllers/updateController.php
index f6ed00986..b76b528d8 100644
--- a/app/Controllers/updateController.php
+++ b/app/Controllers/updateController.php
@@ -270,6 +270,10 @@ class FreshRSS_update_Controller extends FreshRSS_ActionController {
Minz_Request::forward(['c' => 'update'], true);
}
+ if (FreshRSS_Auth::requestReauth()) {
+ return;
+ }
+
if (Minz_Request::paramBoolean('post_conf')) {
if (self::isGit()) {
$res = !self::hasGitUpdate();
diff --git a/app/Controllers/userController.php b/app/Controllers/userController.php
index 05d73f971..c4c3c00a8 100644
--- a/app/Controllers/userController.php
+++ b/app/Controllers/userController.php
@@ -72,6 +72,10 @@ class FreshRSS_user_Controller extends FreshRSS_ActionController {
}
if (Minz_Request::isPost()) {
+ if (self::reauthRedirect()) {
+ return;
+ }
+
$username = Minz_Request::paramString('username');
$newPasswordPlain = Minz_User::name() !== $username ? Minz_Request::paramString('newPasswordPlain', true) : '';
@@ -190,21 +194,41 @@ class FreshRSS_user_Controller extends FreshRSS_ActionController {
}
}
+ public static function reauthRedirect(): bool {
+ $url_redirect = [
+ 'c' => 'user',
+ 'a' => 'manage',
+ 'params' => [],
+ ];
+ $username = Minz_Request::paramStringNull('username');
+ if ($username !== null) {
+ $url_redirect['a'] = 'details';
+ $url_redirect['params']['username'] = $username;
+ }
+ return FreshRSS_Auth::requestReauth($url_redirect);
+ }
+
public function purgeAction(): void {
if (!FreshRSS_Auth::hasAccess('admin')) {
Minz_Error::error(403);
}
- if (Minz_Request::isPost()) {
- $username = Minz_Request::paramString('username');
+ if (!Minz_Request::isPost()) {
+ Minz_Error::error(403);
+ }
- if (!FreshRSS_UserDAO::exists($username)) {
- Minz_Error::error(404);
- }
+ if (self::reauthRedirect()) {
+ return;
+ }
+
+ $username = Minz_Request::paramString('username');
- $feedDAO = FreshRSS_Factory::createFeedDao($username);
- $feedDAO->purge();
+ if (!FreshRSS_UserDAO::exists($username)) {
+ Minz_Error::error(404);
}
+
+ $feedDAO = FreshRSS_Factory::createFeedDao($username);
+ $feedDAO->purge();
}
/**
@@ -215,6 +239,10 @@ class FreshRSS_user_Controller extends FreshRSS_ActionController {
Minz_Error::error(403);
}
+ if (self::reauthRedirect()) {
+ return;
+ }
+
FreshRSS_View::prependTitle(_t('admin.user.title') . ' · ');
if (Minz_Request::isPost()) {
@@ -337,6 +365,10 @@ class FreshRSS_user_Controller extends FreshRSS_ActionController {
Minz_Error::error(403);
}
+ if (self::reauthRedirect()) {
+ return;
+ }
+
if (Minz_Request::isPost()) {
$new_user_name = Minz_Request::paramString('new_user_name');
$email = Minz_Request::paramString('new_user_email');
@@ -602,7 +634,10 @@ class FreshRSS_user_Controller extends FreshRSS_ActionController {
$username, FreshRSS_Context::userConf()->passwordHash,
$nonce, $challenge
);
+ } elseif (self::reauthRedirect()) {
+ return;
}
+
if ($ok) {
$ok &= self::deleteUser($username);
}
@@ -647,6 +682,10 @@ class FreshRSS_user_Controller extends FreshRSS_ActionController {
Minz_Error::error(403);
}
+ if (self::reauthRedirect()) {
+ return;
+ }
+
$username = Minz_Request::paramString('username');
if (!FreshRSS_UserDAO::exists($username)) {
Minz_Error::error(404);
@@ -682,6 +721,10 @@ class FreshRSS_user_Controller extends FreshRSS_ActionController {
Minz_Error::error(403);
}
+ if (self::reauthRedirect()) {
+ return;
+ }
+
$username = Minz_Request::paramString('username');
if (!FreshRSS_UserDAO::exists($username)) {
Minz_Error::error(404);