Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 47 additions & 34 deletions application/controllers/AuthenticationController.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,40 +11,25 @@
use Icinga\Authentication\Auth;
use Icinga\Exception\Http\HttpException;
use Icinga\Module\Oidc\Common\Database;
use Icinga\Module\Oidc\LoginFormModifierHelper;
use Icinga\Module\Oidc\Model\Group;
use Icinga\Module\Oidc\Model\GroupMembership;
use Icinga\Module\Oidc\Model\Provider;
use Icinga\Module\Oidc\ProvidedHook\LoginButtonHook;
use Icinga\User;
use Icinga\Module\Oidc\Model\User as OidcUser;
use Icinga\Util\StringHelper;
use ipl\Html\Html;
use Icinga\Web\Notification;
use Icinga\Web\Session;
use Icinga\Web\Url as IcingaUrl;
use ipl\Stdlib\Filter;
use ipl\Web\Url;
use Jumbojett\OpenIDConnectClient;

/**
* Application wide controller for authentication
*/
class AuthenticationController extends \Icinga\Controllers\AuthenticationController
{
/**
* Log into the application
*/
public function loginAction()
{
$this->view->addHelperPath(
Icinga::app()->getBaseDir()
. DIRECTORY_SEPARATOR . "application/views/helpers/"
);
$this->view->addScriptPath(
Icinga::app()->getBaseDir()
. DIRECTORY_SEPARATOR . "application/views/scripts/"
);
parent::loginAction();
LoginFormModifierHelper::init();
$this->view->form = $this->view->form . "\n" . LoginFormModifierHelper::renderAfterForm();
}

public function realmAction()
{
$name = $this->params->getRequired("name");
Expand Down Expand Up @@ -78,7 +63,10 @@ public function realmAction()
if ($relogin) {
setcookie(
"oidc-internalurl",
$oidcUrl,
(string) Url::fromPath(
'oidc/authentication/realm',
['name' => $name]
)->getRelativeUrl(),
time() + 60 * 60 * 24 * 3,
str_replace("//", "/", Icinga::app()->getRequest()->getBasePath() . "/")
); // needs to be a cookie to work after logout
Expand All @@ -102,7 +90,18 @@ public function realmAction()

if ($oidc->authenticate()) {
if (!empty($_COOKIE['oidc-redirect'])) {
$redirect = $_COOKIE['oidc-redirect'];
$redirectUrl = IcingaUrl::fromPath(
(string) $_COOKIE['oidc-redirect'],
[],
$this->getRequest()
);
if (
! $redirectUrl->isExternal()
&& ! str_contains((string) $redirectUrl->getPath(), 'authentication/logout')
) {
$redirect = $redirectUrl;
}

setcookie(
"oidc-redirect",
"",
Expand Down Expand Up @@ -144,11 +143,17 @@ public function realmAction()
}
}
if (session_status() == PHP_SESSION_ACTIVE) {
// Icinga wants to handle the session so we destroy ours
// Destroy Jumbojett's native session before Icinga persists the authenticated user.
session_destroy();
}
}
} catch (\Throwable $e) {
if (session_status() === PHP_SESSION_ACTIVE) {
// Jumbojett may leave its native PHP session active after an exception.
// Destroy it before Icinga handles the failure redirect.
session_destroy();
}

Logger::error($e->getMessage());
Logger::error($e->getTraceAsString());
}
Expand Down Expand Up @@ -321,21 +326,29 @@ public function filter_by_patterns($array, $patterns)
});
}

public function failedAction()
public function failedAction(): void
{
$this->loginAction();
$div = Html::tag('div', ['class' => 'icinga-module module-oidc']);
$html = Html::tag('p', ['class' => 'oidc-error'], "OIDC: Something went wrong!");
$div->add($html);
$this->view->form = $this->view->form . $div;
$this->_helper->viewRenderer->setRender('authentication/login', null, true);
setcookie(
'oidc-internalurl',
'',
time() - 3600,
str_replace('//', '/', Icinga::app()->getRequest()->getBasePath() . '/')
);
Notification::error(LoginButtonHook::ERROR_MESSAGE);
// Let Notification create and merge its internal message objects instead of
// duplicating their session format. Persist the queue before redirectNow()
// sends headers because Notification's destructor would write too late. The
// login hook consumes the queue because LoginPage does not render it.
$notifications = Notification::getInstance();
$session = Session::getSession();
$session->set(Notification::SESSION_KEY, $notifications->popMessages());
$session->write();
$this->redirectNow('authentication/login?oidc-error=1');
}

public function oidcLogoutAction()
public function oidcLogoutAction(): void
{
// This workarround will not trigger the relogin
$this->_helper->viewRenderer->setRender('authentication/login', null, true);
$this->loginAction();
$this->redirectNow('authentication/login?oidc-logout=1');
}

}
75 changes: 0 additions & 75 deletions application/views/scripts/authentication/login.phtml

This file was deleted.

12 changes: 0 additions & 12 deletions configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,7 @@
]);


?>

<?php

$this->provideConfigTab('backend', array(
'title' => $this->translate('Configure the database backend'),
Expand All @@ -85,8 +83,6 @@
'url' => 'config/import-backend'
));

?>
<?php
$section->add(N_('Provider'))
->setUrl('oidc/providers')
->setPermission('oidc/provider')
Expand All @@ -112,9 +108,7 @@
->setUrl('oidc/groups')
->setPermission('oidc/group')
->setPriority(30);
?>

<?php

$section->add(N_('Files'))
->setUrl('oidc/file')
Expand All @@ -127,9 +121,3 @@
->setPermission('oidc/import')
->setPriority(40);
}


$this->provideUserBackend('oidc',\Icinga\Module\Oidc\Backend\OidcUserBackend::class);
$this->provideUserGroupBackend('oidc',\Icinga\Module\Oidc\Backend\OidcUserGroupBackend::class);

?>
5 changes: 3 additions & 2 deletions doc/02-Installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@

## Requirements <a id="module-oidc-installation-requirements"></a>

* Icinga Web 2 (&gt;= 2.12.1)
* PHP (&gt;= 7.3)
* Icinga Web 2 (≥2.13.0)
* PHP (≥8.2)
* Icinga PHP Library (ipl) (≥0.19.0)


## Installation from .tar.gz <a id="module-oidc-installation-manual"></a>
Expand Down
10 changes: 8 additions & 2 deletions doc/03-Configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,16 @@ This allows you to fetch the account using ldap with the IcingaWeb2 LDAP functio
Under the Backend config you will also find all the settings that are experimental and can be turned on.

### Relogin
For this feature we store a cookie for the last used oidc login url so we can redirect to the oidc login page.
When enabled, the module stores the module-local route for the last OIDC
provider in the `oidc-internalurl` cookie. Opening the login page then starts
OIDC authentication automatically. Invalid values and references to missing or
disabled providers are discarded, and the login page opens normally.

Since this breaks the logic of the AuthenticationHook and redirect to a different logoutpage, make sure to use it only if no other AuthenticationHook implements an onLogout function
Explicit logout clears this cookie and opens the login page with an
`oidc-logout=1` parameter, which bypasses automatic reauthentication.

This feature changes the `AuthenticationHook` logout flow. Enable it only when
no other authentication hook implements `onLogout()`.



Expand Down
3 changes: 2 additions & 1 deletion library/Oidc/Common/Database.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use Icinga\Application\Config;
use Icinga\Data\ResourceFactory;
use ipl\Sql;
use Pdo\Mysql;
use PDO;

final class Database
Expand Down Expand Up @@ -46,7 +47,7 @@ private static function getDb(): Sql\Connection

$options = [PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_OBJ];
if ($config->db === 'mysql') {
$options[PDO::MYSQL_ATTR_INIT_COMMAND] = "SET SESSION SQL_MODE='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE"
$options[Mysql::ATTR_INIT_COMMAND] = "SET SESSION SQL_MODE='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE"
. ",NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION'";
}

Expand Down
Loading