mirror of
https://github.com/FreshRSS/FreshRSS.git
synced 2026-04-27 09:47:35 -04:00
Add HTTP_REMOTE_USER header for auth (#4063)
* add HTTP_REMOTE_USER header for auth * add ip whitelist for HTTP_REMOTE_USER header * add IPv6 support for header auth * fix formatting * A few fixes * Add some default trusted sources * Fix IPv6 doc * More standard header names Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>
This commit is contained in:
@@ -22,6 +22,7 @@
|
||||
* @property-read string $salt
|
||||
* @property-read bool $simplepie_syslog_enabled
|
||||
* @property string $unsafe_autologin_enabled
|
||||
* @property-read array<string> $trusted_sources
|
||||
*/
|
||||
class FreshRSS_SystemConfiguration extends Minz_Configuration {
|
||||
|
||||
|
||||
@@ -189,4 +189,12 @@ return array(
|
||||
|
||||
# Disable self-update,
|
||||
'disable_update' => false,
|
||||
|
||||
# Trusted IPs that are allowed to send unsafe headers
|
||||
# Please read the documentation, before configuring this
|
||||
# https://freshrss.github.io/FreshRSS/en/admins/09_AccessControl.html
|
||||
'trusted_sources' => [
|
||||
'127.0.0.0/8',
|
||||
'::1/128',
|
||||
]
|
||||
);
|
||||
|
||||
@@ -15,13 +15,23 @@ You may also choose to use HTTP Authentication provided by your web server.[^1]
|
||||
|
||||
If you choose to use this option, create a `./p/i/.htaccess` file with a matching `.htpasswd` file.
|
||||
|
||||
You can also use any authentication backend as long as your web server exposes the authenticated user through the `REMOTE_USER` variable.
|
||||
You can also use any authentication backend as long as your web server exposes the authenticated user through the `Remote-User` variable.
|
||||
|
||||
By default, new users allowed by HTTP Basic Auth will automatically be created in FreshRSS the first time they log in.
|
||||
You can disable auto-registration of new users by setting `http_auth_auto_register` to `false` in the configuration file.
|
||||
When using auto-registration, you can optionally use the `http_auth_auto_register_email_field` to specify the name of a web server
|
||||
variable containing the email address of the authenticated user (e.g. `REMOTE_USER_EMAIL`).
|
||||
|
||||
## External Authentication
|
||||
|
||||
You may also use the `Remote-User` or `X-WebAuth-User` header to integrate with a your reverse-proxy’s authentication.
|
||||
|
||||
To enable this feature, you need to add the IP range (in CIDR notation) of your trusted proxy in the `trusted_sources` configuration option.
|
||||
To allow only one IPv4, you can use a `/32` like this: `trusted_sources => [ '192.168.1.10/32' ]`.
|
||||
Likewise to allow only one IPv6, you can use a `/128` like this: `trusted_sources => [ '::1/128' ]`.
|
||||
|
||||
WARNING: FreshRSS will trust any IP configured in the `trusted_sources` option, if your proxy isn’t properly secured, an attacker could simply attach this header and get admin access.
|
||||
|
||||
## No Authentication
|
||||
|
||||
Not using authentication on your server is dangerous, as anyone with access to your server would be able to make changes as an admin.
|
||||
|
||||
@@ -554,15 +554,68 @@ function get_user_configuration($username) {
|
||||
return $user_conf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts an IP (v4 or v6) to a binary representation using inet_pton
|
||||
*
|
||||
* @param string $ip the IP to convert
|
||||
* @return string a binary representation of the specified IP
|
||||
*/
|
||||
function ipToBits(string $ip): string {
|
||||
$binaryip = '';
|
||||
foreach (str_split(inet_pton($ip)) as $char) {
|
||||
$binaryip .= str_pad(decbin(ord($char)), 8, '0', STR_PAD_LEFT);
|
||||
}
|
||||
return $binaryip;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if an ip belongs to the provided range (in CIDR format)
|
||||
*
|
||||
* @param string $ip the IP that we want to verify (ex: 192.168.16.1)
|
||||
* @param string $range the range to check against (ex: 192.168.16.0/24)
|
||||
* @return boolean true if the IP is in the range, otherwise false
|
||||
*/
|
||||
function checkCIDR(string $ip, string $range): bool {
|
||||
$binary_ip = ipToBits($ip);
|
||||
list($subnet, $mask_bits) = explode('/', $range);
|
||||
$mask_bits = intval($mask_bits);
|
||||
$binary_subnet = ipToBits($subnet);
|
||||
|
||||
$ip_net_bits = substr($binary_ip, 0, $mask_bits);
|
||||
$subnet_bits = substr($binary_subnet, 0, $mask_bits);
|
||||
|
||||
return $ip_net_bits === $subnet_bits;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the client is allowed to send unsafe headers
|
||||
* This uses the REMOTE_ADDR header to determine the sender's IP
|
||||
* and the configuration option "trusted_sources" to get an array of the authorized ranges
|
||||
*
|
||||
* @return boolean, true if the sender's IP is in one of the ranges defined in the configuration, else false
|
||||
*/
|
||||
function checkTrustedIP(): bool {
|
||||
if (!empty($_SERVER['REMOTE_ADDR'])) {
|
||||
foreach (FreshRSS_Context::$system_conf->trusted_sources as $cidr) {
|
||||
if (checkCIDR($_SERVER['REMOTE_ADDR'], $cidr)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
function httpAuthUser() {
|
||||
if (!empty($_SERVER['REMOTE_USER'])) {
|
||||
return $_SERVER['REMOTE_USER'];
|
||||
} elseif (!empty($_SERVER['HTTP_REMOTE_USER']) && checkTrustedIP()) {
|
||||
return $_SERVER['HTTP_REMOTE_USER'];
|
||||
} elseif (!empty($_SERVER['REDIRECT_REMOTE_USER'])) {
|
||||
return $_SERVER['REDIRECT_REMOTE_USER'];
|
||||
} elseif (!empty($_SERVER['HTTP_X_WEBAUTH_USER'])) {
|
||||
} elseif (!empty($_SERVER['HTTP_X_WEBAUTH_USER']) && checkTrustedIP()) {
|
||||
return $_SERVER['HTTP_X_WEBAUTH_USER'];
|
||||
}
|
||||
return '';
|
||||
|
||||
Reference in New Issue
Block a user