snappymail/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Admin.php
Rong Zhou 640c567210 Admin panel: accept trusted proxy-auth header (X-NC-Admin) on the admin host
Allows gating the SnappyMail admin panel behind an external single sign-on
layer (e.g. a reverse-proxy auth_request validated against an OpenID Connect /
Nextcloud session) without embedding an OIDC client in SnappyMail. The header
is honored only when present AND the request Host matches admin_panel.host
(defense in depth), so it has no effect on regular webmail or on the panel
when admin_panel.host is unset.

Behavior is unchanged when the header is absent: the existing
admin_login/admin_password (+ optional admin_totp) check applies.

Contributed from Ron-RONZZ-org/ronzz-nextcloud (webmail/patches/).
2026-08-16 18:17:08 +02:00

51 lines
1.5 KiB
PHP

<?php
namespace RainLoop\Actions;
use RainLoop\Exceptions\ClientException;
use RainLoop\KeyPathHelper;
use RainLoop\Notifications;
use RainLoop\Utils;
trait Admin
{
protected static string $AUTH_ADMIN_TOKEN_KEY = 'smadmin';
public function IsAdminLoggined(bool $bThrowExceptionOnFalse = true) : bool
{
if ($this->Config()->Get('security', 'allow_admin_panel', true)) {
// [PATCH ronzz.org] OIDC bridge: nginx auth_request (webmail-admin.ronzz.org)
// sets X-NC-Admin after validating the Nextcloud session. Honored only on the
// dedicated admin host (admin_panel.host); the header is stripped/overridden
// at nginx for any other path.
if (!empty($_SERVER['HTTP_X_NC_ADMIN'])
&& \strtolower((string) $this->Config()->Get('admin_panel', 'host', '')) === \strtolower($this->Http()->GetHost()))
{
return true;
}
$sAdminKey = $this->getAdminAuthKey();
if ($sAdminKey && $this->Cacher(null, true)->Get(KeyPathHelper::SessionAdminKey($sAdminKey))) {
return true;
}
}
if ($bThrowExceptionOnFalse) {
throw new ClientException(Notifications::AuthError);
}
return false;
}
protected function getAdminAuthKey() : string
{
$cookie = \SnappyMail\Cookies::get(static::$AUTH_ADMIN_TOKEN_KEY);
if ($cookie) {
$aAdminHash = Utils::DecodeKeyValuesQ($cookie);
if (!empty($aAdminHash[1]) && 'token' === $aAdminHash[0]) {
return $aAdminHash[1];
}
\SnappyMail\Cookies::clear(static::$AUTH_ADMIN_TOKEN_KEY);
}
return '';
}
}