diff --git a/library/Icinga/Application/EmbeddedWeb.php b/library/Icinga/Application/EmbeddedWeb.php index 83cc99995..6adcf644d 100644 --- a/library/Icinga/Application/EmbeddedWeb.php +++ b/library/Icinga/Application/EmbeddedWeb.php @@ -122,14 +122,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 50339988c..c6bb1432f 100644 --- a/library/Icinga/Authentication/Auth.php +++ b/library/Icinga/Authentication/Auth.php @@ -21,6 +21,8 @@ use Icinga\User\Preferences; use Icinga\User\Preferences\PreferencesStore; use Icinga\Web\Session; use Icinga\Web\StyleSheet; +use LogicException; +use RuntimeException; class Auth { @@ -52,6 +54,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() @@ -90,14 +100,14 @@ class Auth */ public function isAuthenticated() { - if ($this->user !== null) { - return true; + if (! $this->authenticated) { + throw new RuntimeException( + 'This should not happen. Please report this as a bug.' + . 'Include the full stack trace in your report and a list of *all* installed modules.' + ); } - $this->authenticateFromSession(); - if ($this->user === null && ! $this->authExternal()) { - return false; - } - return true; + + return $this->user !== null; } public function setAuthenticated(User $user, $persist = true) @@ -212,6 +222,40 @@ class Auth public function setUser(User $user) { $this->user = $user; + $this->authenticated = true; + + 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; }