add Config::DISABLE_LOGIN_FORM to allow limiting logins to SSO providers

This commit is contained in:
Andrew Dolgov 2025-03-14 11:32:46 +03:00
parent 1fc4eed6cd
commit d373c1f978
No known key found for this signature in database
GPG Key ID: 1A56B4FA25D4AF2A
4 changed files with 67 additions and 48 deletions

View File

@ -189,6 +189,9 @@ class Config {
/** delay updates for this feed if received HTTP 429 (Too Many Requests) for this amount of seconds (base value, actual delay is base...base*2) */
const HTTP_429_THROTTLE_INTERVAL = "HTTP_429_THROTTLE_INTERVAL";
/** disables login form controls except HOOK_LOGINFORM_ADDITIONAL_BUTTONS (for SSO providers), also prevents logging in through auth_internal */
const DISABLE_LOGIN_FORM = "DISABLE_LOGIN_FORM";
/** default values for all global configuration options */
private const _DEFAULTS = [
Config::DB_TYPE => [ "pgsql", Config::T_STRING ],
@ -245,7 +248,8 @@ class Config {
Config::AUTH_MIN_INTERVAL => [ 5, Config::T_INT ],
Config::HTTP_USER_AGENT => [ 'Tiny Tiny RSS/%s (https://tt-rss.org/)',
Config::T_STRING ],
Config::HTTP_429_THROTTLE_INTERVAL => [ 3600, Config::T_INT ]
Config::HTTP_429_THROTTLE_INTERVAL => [ 3600, Config::T_INT ],
Config::DISABLE_LOGIN_FORM => [ "", Config::T_BOOL ]
];
private static ?Config $instance = null;

View File

@ -431,6 +431,13 @@ class Handler_Public extends Handler {
}
function forgotpass(): void {
if (Config::get(Config::DISABLE_LOGIN_FORM) || !str_contains(Config::get(Config::PLUGINS), "auth_internal")) {
header($_SERVER["SERVER_PROTOCOL"]." 403 Forbidden");
echo "Forbidden.";
return;
}
startup_gettext();
session_start();

View File

@ -121,79 +121,84 @@
<fieldset>
<label><?= __("Login:") ?></label>
<input name="login" id="login" dojoType="dijit.form.TextBox" type="text"
onchange="UtilityApp.fetchProfiles()"
onfocus="UtilityApp.fetchProfiles()"
onblur="UtilityApp.fetchProfiles()"
required="1" value="<?= $_SESSION["fake_login"] ?? "" ?>" />
onchange="UtilityApp.fetchProfiles()"
onfocus="UtilityApp.fetchProfiles()"
onblur="UtilityApp.fetchProfiles()"
<?= Config::get(Config::DISABLE_LOGIN_FORM) ? 'disabled="disabled"' : '' ?>
required="1" value="<?= $_SESSION["fake_login"] ?? "" ?>" />
</fieldset>
<fieldset>
<label><?= __("Password:") ?></label>
<input type="password" name="password" required="1"
dojoType="dijit.form.TextBox"
class="input input-text"
onchange="UtilityApp.fetchProfiles()"
onfocus="UtilityApp.fetchProfiles()"
onblur="UtilityApp.fetchProfiles()"
value="<?= $_SESSION["fake_password"] ?? "" ?>"/>
dojoType="dijit.form.TextBox"
class="input input-text"
onchange="UtilityApp.fetchProfiles()"
onfocus="UtilityApp.fetchProfiles()"
onblur="UtilityApp.fetchProfiles()"
<?= Config::get(Config::DISABLE_LOGIN_FORM) ? 'disabled="disabled"' : '' ?>
value="<?= $_SESSION["fake_password"] ?? "" ?>"/>
</fieldset>
<?php if (str_contains(Config::get(Config::PLUGINS), "auth_internal")) { ?>
<?php if (!Config::get(Config::DISABLE_LOGIN_FORM) && str_contains(Config::get(Config::PLUGINS), "auth_internal")) { ?>
<fieldset class="align-right">
<a href="public.php?op=forgotpass"><?= __("I forgot my password") ?></a>
</fieldset>
<?php } ?>
<fieldset>
<label><?= __("Profile:") ?></label>
<?php if (!Config::get(Config::DISABLE_LOGIN_FORM)) { ?>
<fieldset>
<label><?= __("Profile:") ?></label>
<select disabled='disabled' name="profile" id="profile" dojoType='dijit.form.Select'>
<option><?= __("Default profile") ?></option>
</select>
</fieldset>
<fieldset class="narrow">
<label> </label>
<label id="bw_limit_label">
<?= \Controls\checkbox_tag("bw_limit", false, "",
["onchange" => 'UtilityApp.bwLimitChange(this)'], 'bw_limit') ?>
<?= __("Use less traffic") ?></label>
</fieldset>
<div dojoType="dijit.Tooltip" connectId="bw_limit_label" position="below" style="display:none">
<?= __("Does not display images in articles, reduces automatic refreshes."); ?>
</div>
<fieldset class="narrow">
<label> </label>
<label id="safe_mode_label">
<?= \Controls\checkbox_tag("safe_mode") ?>
<?= __("Safe mode") ?>
</label>
</fieldset>
<div dojoType="dijit.Tooltip" connectId="safe_mode_label" position="below" style="display:none">
<?= __("Uses default theme and prevents all plugins from loading."); ?>
</div>
<?php if (Config::get(Config::SESSION_COOKIE_LIFETIME) > 0) { ?>
<select disabled='disabled' name="profile" id="profile" dojoType='dijit.form.Select'>
<option><?= __("Default profile") ?></option>
</select>
</fieldset>
<fieldset class="narrow">
<label> </label>
<label>
<?= \Controls\checkbox_tag("remember_me") ?>
<?= __("Remember me") ?>
<label id="bw_limit_label">
<?= \Controls\checkbox_tag("bw_limit", false, "",
["onchange" => 'UtilityApp.bwLimitChange(this)'], 'bw_limit') ?>
<?= __("Use less traffic") ?></label>
</fieldset>
<div dojoType="dijit.Tooltip" connectId="bw_limit_label" position="below" style="display:none">
<?= __("Does not display images in articles, reduces automatic refreshes."); ?>
</div>
<fieldset class="narrow">
<label> </label>
<label id="safe_mode_label">
<?= \Controls\checkbox_tag("safe_mode") ?>
<?= __("Safe mode") ?>
</label>
</fieldset>
<div dojoType="dijit.Tooltip" connectId="safe_mode_label" position="below" style="display:none">
<?= __("Uses default theme and prevents all plugins from loading."); ?>
</div>
<?php if (Config::get(Config::SESSION_COOKIE_LIFETIME) > 0) { ?>
<fieldset class="narrow">
<label> </label>
<label>
<?= \Controls\checkbox_tag("remember_me") ?>
<?= __("Remember me") ?>
</label>
</fieldset>
<?php } ?>
<?php } ?>
<hr/>
<fieldset class="align-right">
<label> </label>
<?php if (!Config::get(Config::DISABLE_LOGIN_FORM)) { ?>
<?= \Controls\submit_tag(__('Log in')) ?>
<?php } ?>
<?php PluginHost::getInstance()->run_hooks(PluginHost::HOOK_LOGINFORM_ADDITIONAL_BUTTONS) ?>
</fieldset>

View File

@ -15,6 +15,9 @@ class Auth_Internal extends Auth_Base implements IAuthModule2 {
/** @param string $service */
function authenticate($login, $password, $service = '') {
if (Config::get(Config::DISABLE_LOGIN_FORM))
return false;
$otp = (int) ($_REQUEST["otp"] ?? 0);
// don't bother with null/null logins for auth_external etc