diff --git a/library/Icinga/Application/EmbeddedWeb.php b/library/Icinga/Application/EmbeddedWeb.php index 6d04c1048..38052e719 100644 --- a/library/Icinga/Application/EmbeddedWeb.php +++ b/library/Icinga/Application/EmbeddedWeb.php @@ -120,14 +120,9 @@ class EmbeddedWeb extends ApplicationBootstrap protected function setupUser(): static { $auth = Auth::getInstance(); - if (! $this->request->isXmlHttpRequest() && $this->request->isApiRequest() && ! $auth->isAuthenticated()) { - $auth->authHttp(); - } - - if ($auth->isAuthenticated()) { - $user = $auth->getUser(); - $this->getRequest()->setUser($user); - $this->user = $user; + if ($auth->authenticate()->isAuthenticated()) { + $this->user = $auth->getUser(); + $this->getRequest()->setUser($this->user); } return $this; diff --git a/library/Icinga/Authentication/Auth.php b/library/Icinga/Authentication/Auth.php index f358eac37..c2fbbeb4f 100644 --- a/library/Icinga/Authentication/Auth.php +++ b/library/Icinga/Authentication/Auth.php @@ -18,6 +18,7 @@ use Icinga\User\Preferences; use Icinga\User\Preferences\PreferencesStore; use Icinga\Web\Session; use Icinga\Web\StyleSheet; +use LogicException; class Auth { @@ -49,6 +50,14 @@ class Auth */ 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() @@ -87,14 +96,11 @@ class Auth */ public function isAuthenticated() { - if ($this->user !== null) { - return true; + if (! $this->authenticated) { + trigger_error('Authentication can no longer be triggered implicitly', E_USER_DEPRECATED); } - $this->authenticateFromSession(); - if ($this->user === null && ! $this->authExternal()) { - return false; - } - return true; + + return $this->user !== null; } public function setAuthenticated(User $user, $persist = true) @@ -213,6 +219,40 @@ class Auth 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 *