`LoginForm` is now responsible only for the first authentication factor. After a
successful credential check, users with 2FA enrolled are redirected to
`authentication/twofactor` where `TwoFactorChallengeForm` takes over.
Remove `assembleTwoFactorElements()`, the `SUBMIT_VERIFY_2FA` /
`SUBMIT_CANCEL_2FA` / `TOKEN_INPUT` constants, the `getResponse()` helper, and
the `2fa_must_challenge` session branch from `assemble()`. The `onSuccess()`
switch-on-button is replaced with a simple login-only handler.
Also removes the `ON_SENT` handler from `AuthenticationController` that handled
the cancel button. It referenced `SUBMIT_CANCEL_2FA` which is removed here, and
the responsibility moves to `TwoFactorChallengeForm` in the next commit.
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(...))`.
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. Replacing it with a bare `HtmlDocument` which
renders as nothing when empty suppresses that wrapper entirely, keeping the
login page markup clean.
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`)
Replace `assembleVerificationForm()` on the `TwoFactor` interface with
a generic `assembleTwoFactorElements()` method on `LoginForm` itself.
The token input, verify button, and cancel button are now owned by the
login form rather than each hook implementation.
Remove the `TOKEN_INPUT`, `SUBMIT_VERIFY_2FA`, and `SUBMIT_CANCEL_2FA`
constants from the `TwoFactor` interface and define them directly on
`LoginForm`. Update `AuthenticationController` to reference the new
location.
The form element name constants (`TOKEN_INPUT`, `SUBMIT_VERIFY_2FA`,
`SUBMIT_CANCEL_2FA`) are moved out of LoginForm onto TwoFactor so all call sites
share a single source of truth.
Replace the `LoginForm`-owned `assembleTwoFactorElements()` method and the
`getChallengeFormValidators()` interface stub with a proper
`assembleVerificationForm(CompatForm $form)` contract on `TwoFactor`. Each hook
implementation now builds its own verification UI. For the element names the
constants from `TwoFactor` have to be used, so the login form's success handler
can retrieve the values.
The parameter was only ever passed as true by the RememberMe path in
`loginAction()`, intending to let a cookie-based re-authentication bypass the
2FA gate. It was unnecessary for the following reason:
`RememberMe::authenticate()` already calls `setTwoFactorSuccessful()` on the
user before `setAuthenticated()` is called, so the gate condition evaluates to
false on its own.
The form displays either the login inputs or the inputs to verify
the totp token depending on whether `'2fa_must_challenge_token'`
is set `true` in the session.
If 2fa is enable the remember me cookie only gets set if the 2fa
authentication was successful. To log the user back in from the
cookie the 2fa will be skipped.
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.
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