Auth: Perform authentication only once and not lazily

Since authentication is now performed even for static
resources, there's no reason anymore to support implicit
authentication. This also limits authentication attempts
to a single one, previously failed attempts were repeated.

Requiring authentication during bootstrapping, i.e. before
authentication has been performed, will now trigger a
deprecation notice.

refs #5265
This commit is contained in:
Johannes Meyer 2025-07-08 14:22:56 +02:00
parent a28eb4beb8
commit 4ebd1e42e0
2 changed files with 50 additions and 15 deletions

View File

@ -120,14 +120,9 @@ class EmbeddedWeb extends ApplicationBootstrap
protected function setupUser(): static protected function setupUser(): static
{ {
$auth = Auth::getInstance(); $auth = Auth::getInstance();
if (! $this->request->isXmlHttpRequest() && $this->request->isApiRequest() && ! $auth->isAuthenticated()) { if ($auth->authenticate()->isAuthenticated()) {
$auth->authHttp(); $this->user = $auth->getUser();
} $this->getRequest()->setUser($this->user);
if ($auth->isAuthenticated()) {
$user = $auth->getUser();
$this->getRequest()->setUser($user);
$this->user = $user;
} }
return $this; return $this;

View File

@ -18,6 +18,7 @@ use Icinga\User\Preferences;
use Icinga\User\Preferences\PreferencesStore; use Icinga\User\Preferences\PreferencesStore;
use Icinga\Web\Session; use Icinga\Web\Session;
use Icinga\Web\StyleSheet; use Icinga\Web\StyleSheet;
use LogicException;
class Auth class Auth
{ {
@ -49,6 +50,14 @@ class Auth
*/ */
private $user; private $user;
/**
* Whether the user has been authenticated
*
* If true, this does NOT mean authentication was successful.
*
* @var bool
*/
private bool $authenticated = false;
/** /**
* @see getInstance() * @see getInstance()
@ -87,14 +96,11 @@ class Auth
*/ */
public function isAuthenticated() public function isAuthenticated()
{ {
if ($this->user !== null) { if (! $this->authenticated) {
return true; trigger_error('Authentication can no longer be triggered implicitly', E_USER_DEPRECATED);
} }
$this->authenticateFromSession();
if ($this->user === null && ! $this->authExternal()) { return $this->user !== null;
return false;
}
return true;
} }
public function setAuthenticated(User $user, $persist = true) public function setAuthenticated(User $user, $persist = true)
@ -213,6 +219,40 @@ class Auth
return $this; return $this;
} }
/**
* Authenticate the user
*
* This method will try to authenticate the user using the session first, then external backends and finally HTTP
* authentication. If authentication has already been performed, an exception will be thrown.
*
* @throws LogicException If authentication has already been performed
*
* @return $this
*/
public function authenticate(): static
{
if ($this->authenticated) {
throw new LogicException('Cannot perform authentication more than once');
}
$this->authenticateFromSession();
if ($this->user === null) {
$this->authExternal();
if (
$this->user === null
&& $this->getRequest()->isApiRequest()
&& ! $this->getRequest()->isXmlHttpRequest()
) {
$this->authHttp();
}
}
$this->authenticated = true;
return $this;
}
/** /**
* Try to authenticate the user with the current session * Try to authenticate the user with the current session
* *