diff options
| author | 2025-07-31 13:53:14 +0200 | |
|---|---|---|
| committer | 2025-07-31 13:53:14 +0200 | |
| commit | 3ce64d271b2b470bd6c9f7294946347dcdfed9b9 (patch) | |
| tree | 56b5a0928f1ce2b0486e866abd5456bc43ea8ed9 /app/Controllers | |
| parent | d0425f8c3ab14e72142b1a4f946d57b408f26c88 (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.php | 33 | ||||
| -rw-r--r-- | app/Controllers/updateController.php | 4 | ||||
| -rw-r--r-- | app/Controllers/userController.php | 57 |
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); |
