Commit graph

111 commits

Author SHA1 Message Date
Johannes Rauh
215d2ec108 Avoid storing full remember-me cookie in session during 2FA challenge
Previously the `RememberMe` object (containing the AES-encrypted password and
the decryption key) was serialized directly into the PHP session while waiting
for the user to complete the 2FA challenge. Because PHP sessions are written
to disk in plaintext, this exposed the key and ciphertext in the same place,
sufficient to recover the user's password.

Fix by splitting the secret across the session and the database, mirroring the
design of the normal (non-2FA) remember-me flow:

- Call `persist()` at login time so the AES key goes to the database
  immediately, never touching the session.
- Store only the cookie value string (ciphertext + IV) in the session.
  The ciphertext is not exploitable without the key.
- After a successful 2FA challenge, reconstruct the `RememberMe` object via a
  new `RememberMe::fromCookieData()` factory that does a DB lookup by IV and
  restores the canonical expiry from the database row.
- Only then send the browser cookie, so the cookie never reaches the browser
  unless the second factor was verified.

Canceled challenges remove the created DB row, while abandoned challenges
leave an orphaned DB row which is cleaned up by the existing
`RememberMe::removeExpired()` mechanism.

`RememberMe::fromCookieData()` sets `$expiresAt` from the database row so
the browser cookie issued after 2FA inherits the expiry stored at login time
rather than receiving a fresh 30-day window computed at challenge-completion
time. The renewal path in `AuthenticationController::loginAction()` is
unaffected, because `renew()` constructs a new object via `fromCredentials()`.
2026-05-27 10:47:21 +02:00
Johannes Rauh
8f52c7639e Deduplicate redirect logic into LoginRedirect element
Add `LoginRedirect` that extends `HiddenElement` with a single `getUrl()` method
that encapsulates the three-step redirect resolution used in both login and
two-factor challenge form: fall back to `LoginForm::REDIRECT_URL` when the value
is empty or points to the logout action, then reject external URLs with a 400.

`LoginForm` and `TwoFactorChallengeForm` both replace their plain `'hidden'`
element with `LoginRedirect` and drop their identical `createRedirectUrl()`
methods in favor of `$this->getElement('redirect')->getUrl()`.

`AuthenticationController::loginAction()` had a pre-assembly call to
`$form->createRedirectUrl()` for the already-authenticated path. At that point
`handleRequest()` has not yet been called, so the form is not assembled and the
`redirect` element does not exist — calling `getElement()` would throw. That
path is also only reached when no `redirect` query param is present (the param
is handled explicitly on the line above), so the call always returned the
fallback URL anyway. It is replaced with a direct
`Url::fromPath(LoginForm::REDIRECT_URL)`.
2026-05-27 10:47:21 +02:00
Johannes Rauh
c9a60e38b0 Add AuthenticationController::twofactorAction()
`loginAction()` now redirects immediately when a challenge is already active, so
hitting the login URL mid-flow sends the user to the token page instead of
showing the login form.

`twofactorAction()` renders `TwoFactorChallengeForm` inside `LoginPage`. On a
cancel press it purges the session and returns to login.

`withRedirect()` is a small helper that propagates the `redirect` query
parameter across both steps so the original destination is not lost.
2026-05-26 15:27:51 +02:00
Johannes Rauh
8dff2712a1 Use Form::ON_SUBMIT instead of ON_SUCCESS for login buttons 2026-05-18 12:14:13 +02:00
Johannes Rauh
650ea2b597 Migrate AuthenticationController to CompatController
Convert `AuthenticationController` from the legacy Zend Controller to
`CompatController`, dropping `login.phtml` in favour of the new `LoginPage`
widget and `addContent()`. The view variable assignments are replaced by
`setTitle()` and `addContent(new LoginPage(...))`. Improve `httpBadRequest()`
message for external redirect attempts.

In `CompatController`, `$this->controls` is the tab bar area rendered
above the page content. When no tabs are added it still emits an empty
`<div class="controls">` wrapper. Setting `$this->view->compact = true`
suppresses that wrapper entirely, keeping the login page markup clean.

Handle the redirect on success in an `ON_SUBMIT` event handler. Delegate
the external-backend-only check to `LoginForm::onRequest()` via `ON_REQUEST`.
Use `$this->getServerRequest()` instead of `ServerRequest::fromGlobals()`.

Two structural fixes required by the changed DOM nesting:
- `login.less`: height `100%` -> `100vh` (`#login` is now inside `.content`
  which has no explicit height, so percentage inheritance breaks)
- `history.js`: `#layout > #login` -> `#layout #login` (direct-child selector
  breaks because `#login` is now a grandchild of `#layout` through `.content`)
2026-05-18 12:14:13 +02:00
Eric Lippmann
662de28f85 License source files as GPL-3.0-or-later
Add SPDX license headers and mark source files as GPL-3.0-or-later to
preserve the option to relicense under later GPL versions.
2026-03-26 17:49:26 +01:00
Alexander Aleksandrovič Klimov
4037eb51b1
LoginButtonHook: Support additional buttons below the login form (#5442)
Some checks failed
L10n Update / update (push) Has been cancelled
CI / PHP (push) Has been cancelled
Introduces `LoginButtonHook`, a new hook for rendering additional buttons
below the login form. Extend this class to display custom buttons on the
Icinga Web login page — useful for alternative authentication flows such
as SSO. Register your implementation by calling
`YourLoginButtons::register()` during module initialization.
2026-03-04 15:32:06 +01:00
raviks789
0476046ce6 AuthenticationController: Use correct name case for method AesCrypt::getIV() 2023-08-23 10:53:14 +02:00
Johannes Meyer
ec7fb82a94 login: Don't redirect to external resources
fixes #4945
2022-12-07 11:54:45 +01:00
Sukhwinder Dhillon
8c22514758 Utilize multiple encryption ciphers for remember me 2021-08-09 16:58:58 +02:00
Sukhwinder Dhillon
645c0770a2
Rememberme compatibility with php version 5.6+ (#4472) 2021-07-26 17:37:38 +02:00
Eric Lippmann
68acf12407
Remember me (#4112)
Co-authored-by: Sukhwinder Dhillon <sukhwinder.dhillon@icinga.com>
2021-05-21 15:43:06 +02:00
Johannes Meyer
67c8053dc9 login: Override the default title instead of setting a title
refs #3851
2019-07-15 08:26:23 +02:00
Johannes Meyer
4c96da3d56 auth/external: Use a stripped down layout for the logout workaround
We've used the standard layout before which caused a automatic login.
Automatic because the browser saw our js/css <link> tags and accessed
the routes which in turn logged in the user, but only if there's a
enabled module which's configuration.php (or run.php) accesses the
Auth singleton. The stripped down layout provides its own js/css so
there's no need for our full-blown resources.

fixes #3583
2018-10-02 15:24:11 +02:00
Davide Bizzarri
8b5fe61996 Add AuthenticationHook
Created AuthenticationHook class with two main methods: onLogin and
onLogout that are called after login and before logout.
2018-03-28 16:18:31 +02:00
Alexander A. Klimov
474803fee4 Change all license headers to only reflect a file's year of creation
refs #11000
2016-02-08 15:41:00 +01:00
Eric Lippmann
271b5f9d5c Move cookie support detection to a helper class
Icinga\Web\Cookie will become a real cookie implementation.
2015-11-27 15:42:18 +01:00
Eric Lippmann
e92414ea6d Use Request::setBody() for cookies disabled message 2015-08-27 13:21:43 +02:00
Eric Lippmann
016bcf070f Remove unused alias in the AuthenticationController 2015-08-27 13:10:21 +02:00
Eric Lippmann
5518f61614 Namespace the AuthenticationController
refs #5786
2015-08-27 13:09:58 +02:00
Alexander Fuhr
a9ff6eebc0 Merge branch 'master' into bugfix/cookie-support-7383 2015-08-13 11:22:14 +02:00
Alexander Fuhr
d468c59e32 AuthenticationController: Add cookie detection to login action
refs #7383
2015-08-13 11:21:05 +02:00
Johannes Meyer
fa1e3a763d Do not show the full layout on the login page
...

refs #9892
2015-08-13 08:12:30 +02:00
Eric Lippmann
1b5c5deace lib: Rename remote user to external user
We renamed our backend. Code now reflects this.

refs #9660
2015-07-29 15:44:32 +02:00
Eric Lippmann
23fcd39503 Relax auth controller complexity
refs #9660
2015-07-29 14:17:07 +02:00
Johannes Meyer
6ca68f438d Move concrete UserBackend classes to Icinga\Authentication\User
refs #8826
2015-04-21 12:51:31 +02:00
Eric Lippmann
7288f2e92b Use space after the boolean negotiation operator 2015-03-11 22:25:52 +01:00
Eric Lippmann
4570151b4b Fix indentation for strings spanning multiple lines in our auth controller 2015-03-11 22:11:10 +01:00
Johannes Meyer
dfc18e0f95 Display authentication exceptions as form errors 2015-02-12 09:11:03 +01:00
Eric Lippmann
6bae2e0a53 Note that our license is GPL v2 or any later version in our license header instead of pointing to the license's URL 2015-02-04 10:52:27 +01:00
Eric Lippmann
5b4fab0750 Add license header
This time without syntax errors hopefully :)
2015-02-03 16:27:59 +01:00
Eric Lippmann
5fa2e3cfdc Revert "Add license header"
This reverts commit 338d067aba.
2015-02-03 16:16:26 +01:00
Eric Lippmann
338d067aba Add license header
fixes #7788
2015-02-03 15:51:04 +01:00
Johannes Meyer
7ad44b8411 login: Show a note if the only active external auth backend is not available
refs #8274
2015-01-27 14:26:06 +01:00
Johannes Meyer
d99d147901 Fix usages of AutoLoginBackend
refs #8274
2015-01-27 13:45:13 +01:00
Eric Lippmann
250e05f2e8 Optimize imports in AuthenticationController.php 2014-12-29 14:30:47 +01:00
Eric Lippmann
9d8fab51b1 Use the setup related utility functions in AuthenticationController.php 2014-12-29 14:30:06 +01:00
Johannes Meyer
be6358452e Do not redirect to the wizard in case of an empty config.ini 2014-11-18 13:13:02 +01:00
Thomas Gelf
da47c7fc7e Merge remote-tracking branch 'origin/master' into feature/redesign-7144 2014-11-14 21:32:57 +01:00
Johannes Meyer
775c20d9ad Rename namespace Icinga\Form to Icinga\Forms
refs #7553
2014-11-14 10:57:14 +01:00
Bernd Erk
c98a6d5912 Fixes type in error message 2014-11-13 15:41:31 +01:00
Johannes Meyer
259a465f97 Show only the most important warning on the login page 2014-11-12 16:23:55 +01:00
Johannes Meyer
2eb9a771c9 Do not check for any config file, just the directory to show the login-warning
refs #7163
2014-11-12 15:58:18 +01:00
Johannes Meyer
b26e585837 Fix that the authentication.ini is being used as trigger for the config warning
Should have been the config.ini instead.

refs #7163
2014-11-11 12:42:49 +01:00
Johannes Meyer
8909bd5d59 Show warning on login page even if the configuration directory exists
refs #7163
2014-11-11 10:04:01 +01:00
Johannes Meyer
79493592bb Do not use Installer anywhere.
"It's setup."

refs #7163
2014-11-10 10:30:52 +01:00
Johannes Meyer
170ded6510 Merge branch 'master' into feature/setup-wizard-7163
Conflicts:
	library/Icinga/Authentication/Backend/LdapUserBackend.php
	library/Icinga/File/Ini/IniWriter.php
2014-11-04 14:22:53 +01:00
Eric Lippmann
16352fc10c Move Logger to the Application namespace
fixes #7148
2014-10-31 10:27:17 +01:00
Johannes Meyer
c1bff9a26e Merge branch 'master' into feature/setup-wizard-7163 2014-10-30 10:38:21 +01:00
Eric Lippmann
2698516005 Auth: Remove setting the not existent layout 'login' when logging out externally authenticated users
fixes #7191
2014-10-29 16:31:17 +01:00