-
Notifications
You must be signed in to change notification settings - Fork 282
Two Factor Authentication #5397
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
Jan-Schuppik
wants to merge
15
commits into
main
Choose a base branch
from
2fa
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
jrauh01
reviewed
Sep 12, 2025
Contributor
jrauh01
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add to the description:
- Short section about the functionality of 2FA with TOTP
- How does the authentication currently work in Icinga Web
- Information about your implementation
- Reference to the required icinga-php-thirdparty PR
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This PR introduces basic two-factor authentication (2FA) using Time-based One-Time Passwords (TOTP) support for Icinga Web 2. The implementation is functional and provides an additional security layer, but it’s an initial version.
TOTP is an algorithm that generates a time-limited numeric code based on a shared secret and the current time, ensuring that each code is valid only for a short window. After enabling 2FA, users authenticate with their usual Icinga Web credentials and are then prompted to provide a valid TOTP code from their authenticator app (e.g., Google Authenticator, Authy).
current authentication process
Currently, Icinga Web authentication follows this workflow:
First, it checks whether the current request is already authenticated via session.
If not, it checks whether the request is authenticated via external authentication.
If both checks fail, and if the request is an API request with the header X-REQUESTED-WITH not set to XMLHttpRequest, authentication falls back to HTTP Basic Auth. In this case, credentials are verified directly and external user backends are skipped.
If authentication still fails, the user is redirected to the login page (icingaweb2/authentication/login). The login form requires a username and password and stores a successful authentication in session.
about the implementation
Login flow & session gating
After a successful username/password login, we set a session flag must_challenge_2fa_token. The login action then renders a dedicated Challenge2FAForm to collect the TOTP code. On success we flip twoFactorSuccessful in session and complete the login. There’s also a Cancel button to return to the password form.
If 2FA is enabled for a user, this user isn't able to use the HTTP-authentication (API request)
2FA runtime checks
Auth::setupUser() initializes twoFactorEnabled from user preferences and twoFactorSuccessful from session. Auth::isAuthenticated() now denies access if 2FA is enabled but the TOTP challenge hasn’t succeeded yet. Audit logging is moved to the point where both factors have passed.
User preferences & permissions
New privilege user/two-factor-authentication controls who may configure 2FA in Account → Preferences. When allowed, we render a new TotpForm above the existing preferences that lets users enable/disable 2FA and manage their TOTP secret.
(It would make more sense to be able to enforce 2FA instead of requiring permission to use it)
TOTP management UI (TotpForm)
Allows Generate, Renew, Delete secret and Save changes. Pending secrets are kept in session until the user confirms; submitting persists to preferences and writes/deletes the secret in the DB as needed. Labels, temporary state handling, and error-proofing (when enabled_2fa isn’t set) are included.
Backend: TOTP generation/verification
New Icinga\Authentication\Totp service encapsulates secret lifecycle and code verification using a PSR clock. It stores per-user secrets in table icingaweb_totp with columns username, secret, ctime, mtime. Methods include generateSecret(), renewSecret(), deleteSecret(), verify(), makeStatePersistent() and helpers for QR provisioning. A lightweight PsrClock is added.
QR provisioning
When creating/renewing a secret, we display an otpauth:// QR code in the form so users can enroll with an authenticator app (Google Authenticator, Authy, etc.). Styling tweaks are included.
Schema & setup
require: